github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/compile/internal/arm/ssa.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package arm
     6  
     7  import (
     8  	"cmd/compile/internal/gc"
     9  	"cmd/compile/internal/ssa"
    10  	"cmd/internal/obj"
    11  	"cmd/internal/obj/arm"
    12  )
    13  
    14  var ssaRegToReg = []int16{
    15  	arm.REG_R0,
    16  	arm.REG_R1,
    17  	arm.REG_R2,
    18  	arm.REG_R3,
    19  	arm.REGSP, // aka R13
    20  }
    21  
    22  func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
    23  	s.SetLineno(v.Line)
    24  	switch v.Op {
    25  	case ssa.OpInitMem:
    26  		// memory arg needs no code
    27  	case ssa.OpArg:
    28  		// input args need no code
    29  	case ssa.OpSP, ssa.OpSB:
    30  		// nothing to do
    31  	case ssa.OpCopy:
    32  	case ssa.OpLoadReg:
    33  		// TODO: by type
    34  		p := gc.Prog(arm.AMOVW)
    35  		n, off := gc.AutoVar(v.Args[0])
    36  		p.From.Type = obj.TYPE_MEM
    37  		p.From.Node = n
    38  		p.From.Sym = gc.Linksym(n.Sym)
    39  		p.From.Offset = off
    40  		if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
    41  			p.From.Name = obj.NAME_PARAM
    42  			p.From.Offset += n.Xoffset
    43  		} else {
    44  			p.From.Name = obj.NAME_AUTO
    45  		}
    46  		p.To.Type = obj.TYPE_REG
    47  		p.To.Reg = gc.SSARegNum(v)
    48  
    49  	case ssa.OpStoreReg:
    50  		// TODO: by type
    51  		p := gc.Prog(arm.AMOVW)
    52  		p.From.Type = obj.TYPE_REG
    53  		p.From.Reg = gc.SSARegNum(v.Args[0])
    54  		n, off := gc.AutoVar(v)
    55  		p.To.Type = obj.TYPE_MEM
    56  		p.To.Node = n
    57  		p.To.Sym = gc.Linksym(n.Sym)
    58  		p.To.Offset = off
    59  		if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
    60  			p.To.Name = obj.NAME_PARAM
    61  			p.To.Offset += n.Xoffset
    62  		} else {
    63  			p.To.Name = obj.NAME_AUTO
    64  		}
    65  	case ssa.OpARMADD:
    66  		r := gc.SSARegNum(v)
    67  		r1 := gc.SSARegNum(v.Args[0])
    68  		r2 := gc.SSARegNum(v.Args[1])
    69  		p := gc.Prog(v.Op.Asm())
    70  		p.From.Type = obj.TYPE_REG
    71  		p.From.Reg = r1
    72  		p.Reg = r2
    73  		p.To.Type = obj.TYPE_REG
    74  		p.To.Reg = r
    75  	case ssa.OpARMADDconst:
    76  		p := gc.Prog(v.Op.Asm())
    77  		p.From.Type = obj.TYPE_CONST
    78  		p.From.Offset = v.AuxInt
    79  		if v.Aux != nil {
    80  			panic("can't handle symbolic constant yet")
    81  		}
    82  		p.Reg = gc.SSARegNum(v.Args[0])
    83  		p.To.Type = obj.TYPE_REG
    84  		p.To.Reg = gc.SSARegNum(v)
    85  	case ssa.OpARMMOVWconst:
    86  		p := gc.Prog(v.Op.Asm())
    87  		p.From.Type = obj.TYPE_CONST
    88  		p.From.Offset = v.AuxInt
    89  		p.To.Type = obj.TYPE_REG
    90  		p.To.Reg = gc.SSARegNum(v)
    91  	case ssa.OpARMCMP:
    92  		p := gc.Prog(v.Op.Asm())
    93  		p.From.Type = obj.TYPE_REG
    94  		// Special layout in ARM assembly
    95  		// Comparing to x86, the operands of ARM's CMP are reversed.
    96  		p.From.Reg = gc.SSARegNum(v.Args[1])
    97  		p.Reg = gc.SSARegNum(v.Args[0])
    98  	case ssa.OpARMMOVWload:
    99  		p := gc.Prog(v.Op.Asm())
   100  		p.From.Type = obj.TYPE_MEM
   101  		p.From.Reg = gc.SSARegNum(v.Args[0])
   102  		gc.AddAux(&p.From, v)
   103  		p.To.Type = obj.TYPE_REG
   104  		p.To.Reg = gc.SSARegNum(v)
   105  	case ssa.OpARMMOVWstore:
   106  		p := gc.Prog(v.Op.Asm())
   107  		p.From.Type = obj.TYPE_REG
   108  		p.From.Reg = gc.SSARegNum(v.Args[1])
   109  		p.To.Type = obj.TYPE_MEM
   110  		p.To.Reg = gc.SSARegNum(v.Args[0])
   111  		gc.AddAux(&p.To, v)
   112  	case ssa.OpARMCALLstatic:
   113  		// TODO: deferreturn
   114  		p := gc.Prog(obj.ACALL)
   115  		p.To.Type = obj.TYPE_MEM
   116  		p.To.Name = obj.NAME_EXTERN
   117  		p.To.Sym = gc.Linksym(v.Aux.(*gc.Sym))
   118  		if gc.Maxarg < v.AuxInt {
   119  			gc.Maxarg = v.AuxInt
   120  		}
   121  	case ssa.OpVarDef:
   122  		gc.Gvardef(v.Aux.(*gc.Node))
   123  	case ssa.OpVarKill:
   124  		gc.Gvarkill(v.Aux.(*gc.Node))
   125  	case ssa.OpVarLive:
   126  		gc.Gvarlive(v.Aux.(*gc.Node))
   127  	case ssa.OpARMLessThan:
   128  		v.Fatalf("pseudo-op made it to output: %s", v.LongString())
   129  	default:
   130  		v.Unimplementedf("genValue not implemented: %s", v.LongString())
   131  	}
   132  }
   133  
   134  func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
   135  	s.SetLineno(b.Line)
   136  
   137  	switch b.Kind {
   138  	case ssa.BlockCall:
   139  		if b.Succs[0].Block() != next {
   140  			p := gc.Prog(obj.AJMP)
   141  			p.To.Type = obj.TYPE_BRANCH
   142  			s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
   143  		}
   144  	case ssa.BlockRet:
   145  		gc.Prog(obj.ARET)
   146  	case ssa.BlockARMLT:
   147  		p := gc.Prog(arm.ABLT)
   148  		p.To.Type = obj.TYPE_BRANCH
   149  		s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[0].Block()})
   150  		p = gc.Prog(obj.AJMP)
   151  		p.To.Type = obj.TYPE_BRANCH
   152  		s.Branches = append(s.Branches, gc.Branch{P: p, B: b.Succs[1].Block()})
   153  	}
   154  }