// Called after regopt and peep have run. // Expand CHECKNIL pseudo-op into actual nil pointer check. func expandchecks(firstp *obj.Prog) { var p1 *obj.Prog var p2 *obj.Prog for p := firstp; p != nil; p = p.Link { if p.As != obj.ACHECKNIL { continue } if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers gc.Warnl(int(p.Lineno), "generated nil check") } // check is // CMP arg, $0 // JNE 2(PC) (likely) // MOV AX, 0 p1 = gc.Ctxt.NewProg() p2 = gc.Ctxt.NewProg() gc.Clearp(p1) gc.Clearp(p2) p1.Link = p2 p2.Link = p.Link p.Link = p1 p1.Lineno = p.Lineno p2.Lineno = p.Lineno p1.Pc = 9999 p2.Pc = 9999 p.As = int16(cmpptr) p.To.Type = obj.TYPE_CONST p.To.Offset = 0 p1.As = x86.AJNE p1.From.Type = obj.TYPE_CONST p1.From.Offset = 1 // likely p1.To.Type = obj.TYPE_BRANCH p1.To.Val = p2.Link // crash by write to memory address 0. // if possible, since we know arg is 0, use 0(arg), // which will be shorter to encode than plain 0. p2.As = x86.AMOVL p2.From.Type = obj.TYPE_REG p2.From.Reg = x86.REG_AX if regtyp(&p.From) { p2.To.Type = obj.TYPE_MEM p2.To.Reg = p.From.Reg } else { p2.To.Type = obj.TYPE_MEM p2.To.Reg = x86.REG_NONE } p2.To.Offset = 0 } }
// Called after regopt and peep have run. // Expand CHECKNIL pseudo-op into actual nil pointer check. func expandchecks(firstp *obj.Prog) { var p1 *obj.Prog var p2 *obj.Prog for p := (*obj.Prog)(firstp); p != nil; p = p.Link { if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 { fmt.Printf("expandchecks: %v\n", p) } if p.As != obj.ACHECKNIL { continue } if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers gc.Warnl(int(p.Lineno), "generated nil check") } if p.From.Type != obj.TYPE_REG { gc.Fatal("invalid nil check %v\n", p) } // check is // CMP arg, ZR // BNE 2(PC) [likely] // MOVD ZR, 0(arg) p1 = gc.Ctxt.NewProg() p2 = gc.Ctxt.NewProg() gc.Clearp(p1) gc.Clearp(p2) p1.Link = p2 p2.Link = p.Link p.Link = p1 p1.Lineno = p.Lineno p2.Lineno = p.Lineno p1.Pc = 9999 p2.Pc = 9999 p.As = arm64.ACMP p.Reg = arm64.REGZERO p1.As = arm64.ABNE //p1->from.type = TYPE_CONST; //p1->from.offset = 1; // likely p1.To.Type = obj.TYPE_BRANCH p1.To.Val = p2.Link // crash by write to memory address 0. p2.As = arm64.AMOVD p2.From.Type = obj.TYPE_REG p2.From.Reg = arm64.REGZERO p2.To.Type = obj.TYPE_MEM p2.To.Reg = p.From.Reg p2.To.Offset = 0 } }
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 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++ } }
// append adds the Prog to the end of the program-thus-far. // If doLabel is set, it also defines the labels collect for this Prog. func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) { if cond != "" { switch p.arch.Thechar { case '5': if !arch.ARMConditionCodes(prog, cond) { p.errorf("unrecognized condition code .%q", cond) return } case '7': if !arch.ARM64Suffix(prog, cond) { p.errorf("unrecognized suffix .%q", cond) return } default: p.errorf("unrecognized suffix .%q", cond) return } } if p.firstProg == nil { p.firstProg = prog } else { p.lastProg.Link = prog } p.lastProg = prog if doLabel { p.pc++ for _, label := range p.pendingLabels { if p.labels[label] != nil { p.errorf("label %q multiply defined", label) return } p.labels[label] = prog } p.pendingLabels = p.pendingLabels[0:0] } prog.Pc = int64(p.pc) if *flags.Debug { fmt.Println(p.histLineNum, prog) } if testOut != nil { fmt.Fprintln(testOut, p.histLineNum, prog) } }
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++ } }
// Called after regopt and peep have run. // Expand CHECKNIL pseudo-op into actual nil pointer check. func expandchecks(firstp *obj.Prog) { var p1 *obj.Prog for p := (*obj.Prog)(firstp); p != nil; p = p.Link { if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 { fmt.Printf("expandchecks: %v\n", p) } if p.As != obj.ACHECKNIL { continue } if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers gc.Warnl(int(p.Lineno), "generated nil check") } if p.From.Type != obj.TYPE_REG { gc.Fatalf("invalid nil check %v\n", p) } // check is // CBNZ arg, 2(PC) // MOVD ZR, 0(arg) p1 = gc.Ctxt.NewProg() gc.Clearp(p1) p1.Link = p.Link p.Link = p1 p1.Lineno = p.Lineno p1.Pc = 9999 p.As = arm64.ACBNZ p.To.Type = obj.TYPE_BRANCH p.To.Val = p1.Link // crash by write to memory address 0. p1.As = arm64.AMOVD p1.From.Type = obj.TYPE_REG p1.From.Reg = arm64.REGZERO p1.To.Type = obj.TYPE_MEM p1.To.Reg = p.From.Reg p1.To.Offset = 0 } }
// Called after regopt and peep have run. // Expand CHECKNIL pseudo-op into actual nil pointer check. func expandchecks(firstp *obj.Prog) { var reg int var p1 *obj.Prog for p := firstp; p != nil; p = p.Link { if p.As != obj.ACHECKNIL { continue } if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers gc.Warnl(int(p.Lineno), "generated nil check") } if p.From.Type != obj.TYPE_REG { gc.Fatalf("invalid nil check %v", p) } reg = int(p.From.Reg) // check is // CMP arg, $0 // MOV.EQ arg, 0(arg) p1 = gc.Ctxt.NewProg() gc.Clearp(p1) p1.Link = p.Link p.Link = p1 p1.Lineno = p.Lineno p1.Pc = 9999 p1.As = arm.AMOVW p1.From.Type = obj.TYPE_REG p1.From.Reg = int16(reg) p1.To.Type = obj.TYPE_MEM p1.To.Reg = int16(reg) p1.To.Offset = 0 p1.Scond = arm.C_SCOND_EQ p.As = arm.ACMP p.From.Type = obj.TYPE_CONST p.From.Reg = 0 p.From.Offset = 0 p.Reg = int16(reg) } }
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 Clearp(p *obj.Prog) { obj.Nopout(p) p.As = obj.AEND p.Pc = int64(pcloc) pcloc++ }
// Called after regopt and peep have run. // Expand CHECKNIL pseudo-op into actual nil pointer check. func expandchecks(firstp *obj.Prog) { var p1 *obj.Prog var p2 *obj.Prog for p := (*obj.Prog)(firstp); p != nil; p = p.Link { if gc.Debug_checknil != 0 && gc.Ctxt.Debugvlog != 0 { fmt.Printf("expandchecks: %v\n", p) } if p.As != obj.ACHECKNIL { continue } if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers gc.Warnl(int(p.Lineno), "generated nil check") } if p.From.Type != obj.TYPE_REG { gc.Fatal("invalid nil check %v\n", p) } /* // check is // TD $4, R0, arg (R0 is always zero) // eqv. to: // tdeq r0, arg // NOTE: this needs special runtime support to make SIGTRAP recoverable. reg = p->from.reg; p->as = ATD; p->from = p->to = p->from3 = zprog.from; p->from.type = TYPE_CONST; p->from.offset = 4; p->from.reg = 0; p->reg = REGZERO; p->to.type = TYPE_REG; p->to.reg = reg; */ // check is // CMP arg, R0 // BNE 2(PC) [likely] // MOVD R0, 0(R0) p1 = gc.Ctxt.NewProg() p2 = gc.Ctxt.NewProg() gc.Clearp(p1) gc.Clearp(p2) p1.Link = p2 p2.Link = p.Link p.Link = p1 p1.Lineno = p.Lineno p2.Lineno = p.Lineno p1.Pc = 9999 p2.Pc = 9999 p.As = ppc64.ACMP p.To.Type = obj.TYPE_REG p.To.Reg = ppc64.REGZERO p1.As = ppc64.ABNE //p1->from.type = TYPE_CONST; //p1->from.offset = 1; // likely p1.To.Type = obj.TYPE_BRANCH p1.To.Val = p2.Link // crash by write to memory address 0. p2.As = ppc64.AMOVD p2.From.Type = obj.TYPE_REG p2.From.Reg = ppc64.REGZERO p2.To.Type = obj.TYPE_MEM p2.To.Reg = ppc64.REGZERO p2.To.Offset = 0 } }