func outgcode(a int, g1 *obj.Addr, reg int, g2, g3 *obj.Addr) { var p *obj.Prog var pl *obj.Plist if asm.Pass == 1 { goto out } p = asm.Ctxt.NewProg() p.As = int16(a) p.Lineno = stmtline if nosched != 0 { p.Mark |= ppc64.NOSCHED } p.From = *g1 p.Reg = int16(reg) p.From3 = *g2 p.To = *g3 p.Pc = int64(asm.PC) if lastpc == nil { pl = obj.Linknewplist(asm.Ctxt) pl.Firstpc = p } else { lastpc.Link = p } lastpc = p out: if a != obj.AGLOBL && a != obj.ADATA { asm.PC++ } }
func outcode(a int, g2 *Addr2) { var p *obj.Prog var pl *obj.Plist if asm.Pass == 1 { goto out } p = new(obj.Prog) *p = obj.Prog{} p.Ctxt = asm.Ctxt p.As = int16(a) p.Lineno = stmtline p.From = g2.from p.To = g2.to p.Pc = int64(asm.PC) if lastpc == nil { pl = obj.Linknewplist(asm.Ctxt) pl.Firstpc = p } else { lastpc.Link = p } lastpc = p out: if a != obj.AGLOBL && a != obj.ADATA { asm.PC++ } }
func outcode(a int, g1 *obj.Addr, reg int, g2 *obj.Addr) { var p *obj.Prog var pl *obj.Plist if asm.Pass == 1 { goto out } if g1.Scale != 0 { if reg != 0 || g2.Scale != 0 { yyerror("bad addressing modes") } reg = int(g1.Scale) } else if g2.Scale != 0 { if reg != 0 { yyerror("bad addressing modes") } reg = int(g2.Scale) } p = asm.Ctxt.NewProg() p.As = int16(a) p.Lineno = stmtline if nosched != 0 { p.Mark |= ppc64.NOSCHED } p.From = *g1 p.Reg = int16(reg) p.To = *g2 p.Pc = int64(asm.PC) if lastpc == nil { pl = obj.Linknewplist(asm.Ctxt) pl.Firstpc = p } else { lastpc.Link = p } lastpc = p out: if a != obj.AGLOBL && a != obj.ADATA { asm.PC++ } }
func outcode(a, scond int32, g1 *obj.Addr, reg int32, g2 *obj.Addr) { var p *obj.Prog var pl *obj.Plist /* hack to make B.NE etc. work: turn it into the corresponding conditional */ if a == arm.AB { a = int32(bcode[(scond^arm.C_SCOND_XOR)&0xf]) scond = (scond &^ 0xf) | Always } if asm.Pass == 1 { goto out } p = new(obj.Prog) *p = obj.Prog{} p.Ctxt = asm.Ctxt p.As = int16(a) p.Lineno = stmtline p.Scond = uint8(scond) p.From = *g1 p.Reg = int16(reg) p.To = *g2 p.Pc = int64(asm.PC) if lastpc == nil { pl = obj.Linknewplist(asm.Ctxt) pl.Firstpc = p } else { lastpc.Link = p } lastpc = p out: if a != obj.AGLOBL && a != obj.ADATA { asm.PC++ } }
func compile(fn *Node) { if Newproc == nil { Newproc = Sysfunc("newproc") Deferproc = Sysfunc("deferproc") Deferreturn = Sysfunc("deferreturn") Panicindex = Sysfunc("panicindex") panicslice = Sysfunc("panicslice") throwreturn = Sysfunc("throwreturn") } lno := setlineno(fn) Curfn = fn dowidth(Curfn.Type) var oldstksize int64 var nod1 Node var ptxt *obj.Prog var pl *obj.Plist var p *obj.Prog var n *Node var nam *Node var gcargs *Sym var gclocals *Sym if fn.Nbody == nil { if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") { Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name) goto ret } if Debug['A'] != 0 { goto ret } emitptrargsmap() goto ret } saveerrors() // set up domain for labels clearlabels() if Curfn.Type.Outnamed { // add clearing of the output parameters var save Iter t := Structfirst(&save, Getoutarg(Curfn.Type)) for t != nil { if t.Nname != nil { n = Nod(OAS, t.Nname, nil) typecheck(&n, Etop) Curfn.Nbody = concat(list1(n), Curfn.Nbody) } t = structnext(&save) } } order(Curfn) if nerrors != 0 { goto ret } hasdefer = false walk(Curfn) if nerrors != 0 { goto ret } if instrumenting { instrument(Curfn) } if nerrors != 0 { goto ret } continpc = nil breakpc = nil pl = newplist() pl.Name = Linksym(Curfn.Func.Nname.Sym) setlineno(Curfn) Nodconst(&nod1, Types[TINT32], 0) nam = Curfn.Func.Nname if isblank(nam) { nam = nil } ptxt = Thearch.Gins(obj.ATEXT, nam, &nod1) Afunclit(&ptxt.From, Curfn.Func.Nname) ptxt.From3 = new(obj.Addr) if fn.Func.Dupok { ptxt.From3.Offset |= obj.DUPOK } if fn.Func.Wrapper { ptxt.From3.Offset |= obj.WRAPPER } if fn.Func.Needctxt { ptxt.From3.Offset |= obj.NEEDCTXT } if fn.Func.Nosplit { ptxt.From3.Offset |= obj.NOSPLIT } if fn.Func.Systemstack { ptxt.From.Sym.Cfunc = 1 } // Clumsy but important. // See test/recover.go for test cases and src/reflect/value.go // for the actual functions being considered. if myimportpath != "" && myimportpath == "reflect" { if Curfn.Func.Nname.Sym.Name == "callReflect" || Curfn.Func.Nname.Sym.Name == "callMethod" { ptxt.From3.Offset |= obj.WRAPPER } } ginit() gcargs = makefuncdatasym("gcargs·%d", obj.FUNCDATA_ArgsPointerMaps) gclocals = makefuncdatasym("gclocals·%d", obj.FUNCDATA_LocalsPointerMaps) for _, t := range Curfn.Func.Fieldtrack { gtrack(tracksym(t)) } for l := fn.Func.Dcl; l != nil; l = l.Next { n = l.N if n.Op != ONAME { // might be OTYPE or OLITERAL continue } switch n.Class { case PAUTO, PPARAM, PPARAMOUT: Nodconst(&nod1, Types[TUINTPTR], l.N.Type.Width) p = Thearch.Gins(obj.ATYPE, l.N, &nod1) p.From.Gotype = Linksym(ngotype(l.N)) } } Genlist(Curfn.Func.Enter) Genlist(Curfn.Nbody) gclean() checklabels() if nerrors != 0 { goto ret } if Curfn.Func.Endlineno != 0 { lineno = Curfn.Func.Endlineno } if Curfn.Type.Outtuple != 0 { Ginscall(throwreturn, 0) } ginit() // TODO: Determine when the final cgen_ret can be omitted. Perhaps always? cgen_ret(nil) if hasdefer { // deferreturn pretends to have one uintptr argument. // Reserve space for it so stack scanner is happy. if Maxarg < int64(Widthptr) { Maxarg = int64(Widthptr) } } gclean() if nerrors != 0 { goto ret } Pc.As = obj.ARET // overwrite AEND Pc.Lineno = lineno fixjmp(ptxt) if Debug['N'] == 0 || Debug['R'] != 0 || Debug['P'] != 0 { regopt(ptxt) nilopt(ptxt) } Thearch.Expandchecks(ptxt) oldstksize = Stksize allocauto(ptxt) if false { fmt.Printf("allocauto: %d to %d\n", oldstksize, int64(Stksize)) } setlineno(Curfn) if int64(Stksize)+Maxarg > 1<<31 { Yyerror("stack frame too large (>2GB)") goto ret } // Emit garbage collection symbols. liveness(Curfn, ptxt, gcargs, gclocals) gcsymdup(gcargs) gcsymdup(gclocals) Thearch.Defframe(ptxt) if Debug['f'] != 0 { frame(0) } // Remove leftover instrumentation from the instruction stream. removevardef(ptxt) ret: lineno = lno }