Best Syzkaller code snippet using prog.Target
asm.go
Source:asm.go
1// Copyright 2014 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4package asm5import (6 "bytes"7 "fmt"8 "strconv"9 "text/scanner"10 "cmd/asm/internal/arch"11 "cmd/asm/internal/flags"12 "cmd/asm/internal/lex"13 "cmd/internal/obj"14 "cmd/internal/obj/x86"15 "cmd/internal/objabi"16 "cmd/internal/sys"17)18// TODO: configure the architecture19var testOut *bytes.Buffer // Gathers output when testing.20// append adds the Prog to the end of the program-thus-far.21// If doLabel is set, it also defines the labels collect for this Prog.22func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {23 if cond != "" {24 switch p.arch.Family {25 case sys.ARM:26 if !arch.ARMConditionCodes(prog, cond) {27 p.errorf("unrecognized condition code .%q", cond)28 return29 }30 case sys.ARM64:31 if !arch.ARM64Suffix(prog, cond) {32 p.errorf("unrecognized suffix .%q", cond)33 return34 }35 case sys.AMD64, sys.I386:36 if err := x86.ParseSuffix(prog, cond); err != nil {37 p.errorf("%v", err)38 return39 }40 default:41 p.errorf("unrecognized suffix .%q", cond)42 return43 }44 }45 if p.firstProg == nil {46 p.firstProg = prog47 } else {48 p.lastProg.Link = prog49 }50 p.lastProg = prog51 if doLabel {52 p.pc++53 for _, label := range p.pendingLabels {54 if p.labels[label] != nil {55 p.errorf("label %q multiply defined", label)56 return57 }58 p.labels[label] = prog59 }60 p.pendingLabels = p.pendingLabels[0:0]61 }62 prog.Pc = p.pc63 if *flags.Debug {64 fmt.Println(p.lineNum, prog)65 }66 if testOut != nil {67 fmt.Fprintln(testOut, prog)68 }69}70// validSymbol checks that addr represents a valid name for a pseudo-op.71func (p *Parser) validSymbol(pseudo string, addr *obj.Addr, offsetOk bool) bool {72 if addr.Sym == nil || addr.Name != obj.NAME_EXTERN && addr.Name != obj.NAME_STATIC || addr.Scale != 0 || addr.Reg != 0 {73 p.errorf("%s symbol %q must be a symbol(SB)", pseudo, symbolName(addr))74 return false75 }76 if !offsetOk && addr.Offset != 0 {77 p.errorf("%s symbol %q must not be offset from SB", pseudo, symbolName(addr))78 return false79 }80 return true81}82// evalInteger evaluates an integer constant for a pseudo-op.83func (p *Parser) evalInteger(pseudo string, operands []lex.Token) int64 {84 addr := p.address(operands)85 return p.getConstantPseudo(pseudo, &addr)86}87// validImmediate checks that addr represents an immediate constant.88func (p *Parser) validImmediate(pseudo string, addr *obj.Addr) bool {89 if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {90 p.errorf("%s: expected immediate constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))91 return false92 }93 return true94}95// asmText assembles a TEXT pseudo-op.96// TEXT runtime·sigtramp(SB),4,$0-097func (p *Parser) asmText(operands [][]lex.Token) {98 if len(operands) != 2 && len(operands) != 3 {99 p.errorf("expect two or three operands for TEXT")100 return101 }102 // Labels are function scoped. Patch existing labels and103 // create a new label space for this TEXT.104 p.patch()105 p.labels = make(map[string]*obj.Prog)106 // Operand 0 is the symbol name in the form foo(SB).107 // That means symbol plus indirect on SB and no offset.108 nameAddr := p.address(operands[0])109 if !p.validSymbol("TEXT", &nameAddr, false) {110 return111 }112 name := symbolName(&nameAddr)113 next := 1114 // Next operand is the optional text flag, a literal integer.115 var flag = int64(0)116 if len(operands) == 3 {117 flag = p.evalInteger("TEXT", operands[1])118 next++119 }120 // Issue an error if we see a function defined as ABIInternal121 // without NOSPLIT. In ABIInternal, obj needs to know the function122 // signature in order to construct the morestack path, so this123 // currently isn't supported for asm functions.124 if nameAddr.Sym.ABI() == obj.ABIInternal && flag&obj.NOSPLIT == 0 {125 p.errorf("TEXT %q: ABIInternal requires NOSPLIT", name)126 }127 // Next operand is the frame and arg size.128 // Bizarre syntax: $frameSize-argSize is two words, not subtraction.129 // Both frameSize and argSize must be simple integers; only frameSize130 // can be negative.131 // The "-argSize" may be missing; if so, set it to objabi.ArgsSizeUnknown.132 // Parse left to right.133 op := operands[next]134 if len(op) < 2 || op[0].ScanToken != '$' {135 p.errorf("TEXT %s: frame size must be an immediate constant", name)136 return137 }138 op = op[1:]139 negative := false140 if op[0].ScanToken == '-' {141 negative = true142 op = op[1:]143 }144 if len(op) == 0 || op[0].ScanToken != scanner.Int {145 p.errorf("TEXT %s: frame size must be an immediate constant", name)146 return147 }148 frameSize := p.positiveAtoi(op[0].String())149 if negative {150 frameSize = -frameSize151 }152 op = op[1:]153 argSize := int64(objabi.ArgsSizeUnknown)154 if len(op) > 0 {155 // There is an argument size. It must be a minus sign followed by a non-negative integer literal.156 if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {157 p.errorf("TEXT %s: argument size must be of form -integer", name)158 return159 }160 argSize = p.positiveAtoi(op[1].String())161 }162 p.ctxt.InitTextSym(nameAddr.Sym, int(flag))163 prog := &obj.Prog{164 Ctxt: p.ctxt,165 As: obj.ATEXT,166 Pos: p.pos(),167 From: nameAddr,168 To: obj.Addr{169 Type: obj.TYPE_TEXTSIZE,170 Offset: frameSize,171 // Argsize set below.172 },173 }174 nameAddr.Sym.Func().Text = prog175 prog.To.Val = int32(argSize)176 p.append(prog, "", true)177}178// asmData assembles a DATA pseudo-op.179// DATA masks<>+0x00(SB)/4, $0x00000000180func (p *Parser) asmData(operands [][]lex.Token) {181 if len(operands) != 2 {182 p.errorf("expect two operands for DATA")183 return184 }185 // Operand 0 has the general form foo<>+0x04(SB)/4.186 op := operands[0]187 n := len(op)188 if n < 3 || op[n-2].ScanToken != '/' || op[n-1].ScanToken != scanner.Int {189 p.errorf("expect /size for DATA argument")190 return191 }192 szop := op[n-1].String()193 sz, err := strconv.Atoi(szop)194 if err != nil {195 p.errorf("bad size for DATA argument: %q", szop)196 }197 op = op[:n-2]198 nameAddr := p.address(op)199 if !p.validSymbol("DATA", &nameAddr, true) {200 return201 }202 name := symbolName(&nameAddr)203 // Operand 1 is an immediate constant or address.204 valueAddr := p.address(operands[1])205 switch valueAddr.Type {206 case obj.TYPE_CONST, obj.TYPE_FCONST, obj.TYPE_SCONST, obj.TYPE_ADDR:207 // OK208 default:209 p.errorf("DATA value must be an immediate constant or address")210 return211 }212 // The addresses must not overlap. Easiest test: require monotonicity.213 if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {214 p.errorf("overlapping DATA entry for %s", name)215 return216 }217 p.dataAddr[name] = nameAddr.Offset + int64(sz)218 switch valueAddr.Type {219 case obj.TYPE_CONST:220 switch sz {221 case 1, 2, 4, 8:222 nameAddr.Sym.WriteInt(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Offset)223 default:224 p.errorf("bad int size for DATA argument: %d", sz)225 }226 case obj.TYPE_FCONST:227 switch sz {228 case 4:229 nameAddr.Sym.WriteFloat32(p.ctxt, nameAddr.Offset, float32(valueAddr.Val.(float64)))230 case 8:231 nameAddr.Sym.WriteFloat64(p.ctxt, nameAddr.Offset, valueAddr.Val.(float64))232 default:233 p.errorf("bad float size for DATA argument: %d", sz)234 }235 case obj.TYPE_SCONST:236 nameAddr.Sym.WriteString(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Val.(string))237 case obj.TYPE_ADDR:238 if sz == p.arch.PtrSize {239 nameAddr.Sym.WriteAddr(p.ctxt, nameAddr.Offset, int(sz), valueAddr.Sym, valueAddr.Offset)240 } else {241 p.errorf("bad addr size for DATA argument: %d", sz)242 }243 }244}245// asmGlobl assembles a GLOBL pseudo-op.246// GLOBL shifts<>(SB),8,$256247// GLOBL shifts<>(SB),$256248func (p *Parser) asmGlobl(operands [][]lex.Token) {249 if len(operands) != 2 && len(operands) != 3 {250 p.errorf("expect two or three operands for GLOBL")251 return252 }253 // Operand 0 has the general form foo<>+0x04(SB).254 nameAddr := p.address(operands[0])255 if !p.validSymbol("GLOBL", &nameAddr, false) {256 return257 }258 next := 1259 // Next operand is the optional flag, a literal integer.260 var flag = int64(0)261 if len(operands) == 3 {262 flag = p.evalInteger("GLOBL", operands[1])263 next++264 }265 // Final operand is an immediate constant.266 addr := p.address(operands[next])267 if !p.validImmediate("GLOBL", &addr) {268 return269 }270 // log.Printf("GLOBL %s %d, $%d", name, flag, size)271 p.ctxt.Globl(nameAddr.Sym, addr.Offset, int(flag))272}273// asmPCData assembles a PCDATA pseudo-op.274// PCDATA $2, $705275func (p *Parser) asmPCData(operands [][]lex.Token) {276 if len(operands) != 2 {277 p.errorf("expect two operands for PCDATA")278 return279 }280 // Operand 0 must be an immediate constant.281 key := p.address(operands[0])282 if !p.validImmediate("PCDATA", &key) {283 return284 }285 // Operand 1 must be an immediate constant.286 value := p.address(operands[1])287 if !p.validImmediate("PCDATA", &value) {288 return289 }290 // log.Printf("PCDATA $%d, $%d", key.Offset, value.Offset)291 prog := &obj.Prog{292 Ctxt: p.ctxt,293 As: obj.APCDATA,294 Pos: p.pos(),295 From: key,296 To: value,297 }298 p.append(prog, "", true)299}300// asmPCAlign assembles a PCALIGN pseudo-op.301// PCALIGN $16302func (p *Parser) asmPCAlign(operands [][]lex.Token) {303 if len(operands) != 1 {304 p.errorf("expect one operand for PCALIGN")305 return306 }307 // Operand 0 must be an immediate constant.308 key := p.address(operands[0])309 if !p.validImmediate("PCALIGN", &key) {310 return311 }312 prog := &obj.Prog{313 Ctxt: p.ctxt,314 As: obj.APCALIGN,315 From: key,316 }317 p.append(prog, "", true)318}319// asmFuncData assembles a FUNCDATA pseudo-op.320// FUNCDATA $1, funcdata<>+4(SB)321func (p *Parser) asmFuncData(operands [][]lex.Token) {322 if len(operands) != 2 {323 p.errorf("expect two operands for FUNCDATA")324 return325 }326 // Operand 0 must be an immediate constant.327 valueAddr := p.address(operands[0])328 if !p.validImmediate("FUNCDATA", &valueAddr) {329 return330 }331 // Operand 1 is a symbol name in the form foo(SB).332 nameAddr := p.address(operands[1])333 if !p.validSymbol("FUNCDATA", &nameAddr, true) {334 return335 }336 prog := &obj.Prog{337 Ctxt: p.ctxt,338 As: obj.AFUNCDATA,339 Pos: p.pos(),340 From: valueAddr,341 To: nameAddr,342 }343 p.append(prog, "", true)344}345// asmJump assembles a jump instruction.346// JMP R1347// JMP exit348// JMP 3(PC)349func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {350 var target *obj.Addr351 prog := &obj.Prog{352 Ctxt: p.ctxt,353 Pos: p.pos(),354 As: op,355 }356 switch len(a) {357 case 0:358 if p.arch.Family == sys.Wasm {359 target = &obj.Addr{Type: obj.TYPE_NONE}360 break361 }362 p.errorf("wrong number of arguments to %s instruction", op)363 return364 case 1:365 target = &a[0]366 case 2:367 // Special 2-operand jumps.368 target = &a[1]369 prog.From = a[0]370 case 3:371 if p.arch.Family == sys.PPC64 {372 // Special 3-operand jumps.373 // First two must be constants; a[1] is a register number.374 target = &a[2]375 prog.From = obj.Addr{376 Type: obj.TYPE_CONST,377 Offset: p.getConstant(prog, op, &a[0]),378 }379 reg := int16(p.getConstant(prog, op, &a[1]))380 reg, ok := p.arch.RegisterNumber("R", reg)381 if !ok {382 p.errorf("bad register number %d", reg)383 return384 }385 prog.Reg = reg386 break387 }388 if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 || p.arch.Family == sys.RISCV64 {389 // 3-operand jumps.390 // First two must be registers391 target = &a[2]392 prog.From = a[0]393 prog.Reg = p.getRegister(prog, op, &a[1])394 break395 }396 if p.arch.Family == sys.S390X {397 // 3-operand jumps.398 target = &a[2]399 prog.From = a[0]400 if a[1].Reg != 0 {401 // Compare two registers and jump.402 prog.Reg = p.getRegister(prog, op, &a[1])403 } else {404 // Compare register with immediate and jump.405 prog.SetFrom3(a[1])406 }407 break408 }409 if p.arch.Family == sys.ARM64 {410 // Special 3-operand jumps.411 // a[0] must be immediate constant; a[1] is a register.412 if a[0].Type != obj.TYPE_CONST {413 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, &a[0]))414 return415 }416 prog.From = a[0]417 prog.Reg = p.getRegister(prog, op, &a[1])418 target = &a[2]419 break420 }421 p.errorf("wrong number of arguments to %s instruction", op)422 return423 case 4:424 if p.arch.Family == sys.S390X {425 // 4-operand compare-and-branch.426 prog.From = a[0]427 prog.Reg = p.getRegister(prog, op, &a[1])428 prog.SetFrom3(a[2])429 target = &a[3]430 break431 }432 p.errorf("wrong number of arguments to %s instruction", op)433 return434 default:435 p.errorf("wrong number of arguments to %s instruction", op)436 return437 }438 switch {439 case target.Type == obj.TYPE_BRANCH:440 // JMP 4(PC)441 prog.To = obj.Addr{442 Type: obj.TYPE_BRANCH,443 Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in append, below.444 }445 case target.Type == obj.TYPE_REG:446 // JMP R1447 prog.To = *target448 case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):449 // JMP main·morestack(SB)450 prog.To = *target451 case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):452 // JMP *main·morestack(SB)453 prog.To = *target454 prog.To.Type = obj.TYPE_INDIR455 case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:456 // JMP exit457 if target.Sym == nil {458 // Parse error left name unset.459 return460 }461 targetProg := p.labels[target.Sym.Name]462 if targetProg == nil {463 p.toPatch = append(p.toPatch, Patch{prog, target.Sym.Name})464 } else {465 p.branch(prog, targetProg)466 }467 case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:468 // JMP 4(R0)469 prog.To = *target470 // On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.471 if p.arch.Family == sys.PPC64 && target.Offset == 0 {472 prog.To.Type = obj.TYPE_REG473 }474 case target.Type == obj.TYPE_CONST:475 // JMP $4476 prog.To = a[0]477 case target.Type == obj.TYPE_NONE:478 // JMP479 default:480 p.errorf("cannot assemble jump %+v", target)481 return482 }483 p.append(prog, cond, true)484}485func (p *Parser) patch() {486 for _, patch := range p.toPatch {487 targetProg := p.labels[patch.label]488 if targetProg == nil {489 p.errorf("undefined label %s", patch.label)490 return491 }492 p.branch(patch.prog, targetProg)493 }494 p.toPatch = p.toPatch[:0]495}496func (p *Parser) branch(jmp, target *obj.Prog) {497 jmp.To = obj.Addr{498 Type: obj.TYPE_BRANCH,499 Index: 0,500 }501 jmp.To.Val = target502}503// asmInstruction assembles an instruction.504// MOVW R9, (R10)505func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {506 // fmt.Printf("%s %+v\n", op, a)507 prog := &obj.Prog{508 Ctxt: p.ctxt,509 Pos: p.pos(),510 As: op,511 }512 switch len(a) {513 case 0:514 // Nothing to do.515 case 1:516 if p.arch.UnaryDst[op] || op == obj.ARET || op == obj.AGETCALLERPC {517 // prog.From is no address.518 prog.To = a[0]519 } else {520 prog.From = a[0]521 // prog.To is no address.522 }523 if p.arch.Family == sys.PPC64 && arch.IsPPC64NEG(op) {524 // NEG: From and To are both a[0].525 prog.To = a[0]526 prog.From = a[0]527 break528 }529 case 2:530 if p.arch.Family == sys.ARM {531 if arch.IsARMCMP(op) {532 prog.From = a[0]533 prog.Reg = p.getRegister(prog, op, &a[1])534 break535 }536 // Strange special cases.537 if arch.IsARMFloatCmp(op) {538 prog.From = a[0]539 prog.Reg = p.getRegister(prog, op, &a[1])540 break541 }542 } else if p.arch.Family == sys.ARM64 && arch.IsARM64CMP(op) {543 prog.From = a[0]544 prog.Reg = p.getRegister(prog, op, &a[1])545 break546 } else if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 {547 if arch.IsMIPSCMP(op) || arch.IsMIPSMUL(op) {548 prog.From = a[0]549 prog.Reg = p.getRegister(prog, op, &a[1])550 break551 }552 }553 prog.From = a[0]554 prog.To = a[1]555 case 3:556 switch p.arch.Family {557 case sys.MIPS, sys.MIPS64:558 prog.From = a[0]559 prog.Reg = p.getRegister(prog, op, &a[1])560 prog.To = a[2]561 case sys.ARM:562 // Special cases.563 if arch.IsARMSTREX(op) {564 /*565 STREX x, (y), z566 from=(y) reg=x to=z567 */568 prog.From = a[1]569 prog.Reg = p.getRegister(prog, op, &a[0])570 prog.To = a[2]571 break572 }573 if arch.IsARMBFX(op) {574 // a[0] and a[1] must be constants, a[2] must be a register575 prog.From = a[0]576 prog.SetFrom3(a[1])577 prog.To = a[2]578 break579 }580 // Otherwise the 2nd operand (a[1]) must be a register.581 prog.From = a[0]582 prog.Reg = p.getRegister(prog, op, &a[1])583 prog.To = a[2]584 case sys.AMD64:585 prog.From = a[0]586 prog.SetFrom3(a[1])587 prog.To = a[2]588 case sys.ARM64:589 switch {590 case arch.IsARM64STLXR(op):591 // ARM64 instructions with one input and two outputs.592 prog.From = a[0]593 prog.To = a[1]594 if a[2].Type != obj.TYPE_REG {595 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)596 return597 }598 prog.RegTo2 = a[2].Reg599 case arch.IsARM64TBL(op):600 // one of its inputs does not fit into prog.Reg.601 prog.From = a[0]602 prog.SetFrom3(a[1])603 prog.To = a[2]604 case arch.IsARM64CASP(op):605 prog.From = a[0]606 prog.To = a[1]607 // both 1st operand and 3rd operand are (Rs, Rs+1) register pair.608 // And the register pair must be contiguous.609 if (a[0].Type != obj.TYPE_REGREG) || (a[2].Type != obj.TYPE_REGREG) {610 p.errorf("invalid addressing modes for 1st or 3rd operand to %s instruction, must be register pair", op)611 return612 }613 // For ARM64 CASP-like instructions, its 2nd destination operand is register pair(Rt, Rt+1) that can614 // not fit into prog.RegTo2, so save it to the prog.RestArgs.615 prog.SetTo2(a[2])616 default:617 prog.From = a[0]618 prog.Reg = p.getRegister(prog, op, &a[1])619 prog.To = a[2]620 }621 case sys.I386:622 prog.From = a[0]623 prog.SetFrom3(a[1])624 prog.To = a[2]625 case sys.PPC64:626 if arch.IsPPC64CMP(op) {627 // CMPW etc.; third argument is a CR register that goes into prog.Reg.628 prog.From = a[0]629 prog.Reg = p.getRegister(prog, op, &a[2])630 prog.To = a[1]631 break632 }633 // Arithmetic. Choices are:634 // reg reg reg635 // imm reg reg636 // reg imm reg637 // If the immediate is the middle argument, use From3.638 switch a[1].Type {639 case obj.TYPE_REG:640 prog.From = a[0]641 prog.Reg = p.getRegister(prog, op, &a[1])642 prog.To = a[2]643 case obj.TYPE_CONST:644 prog.From = a[0]645 prog.SetFrom3(a[1])646 prog.To = a[2]647 default:648 p.errorf("invalid addressing modes for %s instruction", op)649 return650 }651 case sys.RISCV64:652 // RISCV64 instructions with one input and two outputs.653 if arch.IsRISCV64AMO(op) {654 prog.From = a[0]655 prog.To = a[1]656 if a[2].Type != obj.TYPE_REG {657 p.errorf("invalid addressing modes for third operand to %s instruction, must be register", op)658 return659 }660 prog.RegTo2 = a[2].Reg661 break662 }663 prog.From = a[0]664 prog.Reg = p.getRegister(prog, op, &a[1])665 prog.To = a[2]666 case sys.S390X:667 prog.From = a[0]668 if a[1].Type == obj.TYPE_REG {669 prog.Reg = p.getRegister(prog, op, &a[1])670 } else {671 prog.SetFrom3(a[1])672 }673 prog.To = a[2]674 default:675 p.errorf("TODO: implement three-operand instructions for this architecture")676 return677 }678 case 4:679 if p.arch.Family == sys.ARM {680 if arch.IsARMBFX(op) {681 // a[0] and a[1] must be constants, a[2] and a[3] must be registers682 prog.From = a[0]683 prog.SetFrom3(a[1])684 prog.Reg = p.getRegister(prog, op, &a[2])685 prog.To = a[3]686 break687 }688 if arch.IsARMMULA(op) {689 // All must be registers.690 p.getRegister(prog, op, &a[0])691 r1 := p.getRegister(prog, op, &a[1])692 r2 := p.getRegister(prog, op, &a[2])693 p.getRegister(prog, op, &a[3])694 prog.From = a[0]695 prog.To = a[3]696 prog.To.Type = obj.TYPE_REGREG2697 prog.To.Offset = int64(r2)698 prog.Reg = r1699 break700 }701 }702 if p.arch.Family == sys.AMD64 {703 prog.From = a[0]704 prog.SetRestArgs([]obj.Addr{a[1], a[2]})705 prog.To = a[3]706 break707 }708 if p.arch.Family == sys.ARM64 {709 prog.From = a[0]710 prog.Reg = p.getRegister(prog, op, &a[1])711 prog.SetFrom3(a[2])712 prog.To = a[3]713 break714 }715 if p.arch.Family == sys.PPC64 {716 if arch.IsPPC64RLD(op) {717 prog.From = a[0]718 prog.Reg = p.getRegister(prog, op, &a[1])719 prog.SetFrom3(a[2])720 prog.To = a[3]721 break722 } else if arch.IsPPC64ISEL(op) {723 // ISEL BC,RB,RA,RT becomes isel rt,ra,rb,bc724 prog.SetFrom3(a[2]) // ra725 prog.From = a[0] // bc726 prog.Reg = p.getRegister(prog, op, &a[1]) // rb727 prog.To = a[3] // rt728 break729 }730 // Else, it is a VA-form instruction731 // reg reg reg reg732 // imm reg reg reg733 // Or a VX-form instruction734 // imm imm reg reg735 if a[1].Type == obj.TYPE_REG {736 prog.From = a[0]737 prog.Reg = p.getRegister(prog, op, &a[1])738 prog.SetFrom3(a[2])739 prog.To = a[3]740 break741 } else if a[1].Type == obj.TYPE_CONST {742 prog.From = a[0]743 prog.Reg = p.getRegister(prog, op, &a[2])744 prog.SetFrom3(a[1])745 prog.To = a[3]746 break747 } else {748 p.errorf("invalid addressing modes for %s instruction", op)749 return750 }751 }752 if p.arch.Family == sys.RISCV64 {753 prog.From = a[0]754 prog.Reg = p.getRegister(prog, op, &a[1])755 prog.SetRestArgs([]obj.Addr{a[2]})756 prog.To = a[3]757 break758 }759 if p.arch.Family == sys.S390X {760 if a[1].Type != obj.TYPE_REG {761 p.errorf("second operand must be a register in %s instruction", op)762 return763 }764 prog.From = a[0]765 prog.Reg = p.getRegister(prog, op, &a[1])766 prog.SetFrom3(a[2])767 prog.To = a[3]768 break769 }770 p.errorf("can't handle %s instruction with 4 operands", op)771 return772 case 5:773 if p.arch.Family == sys.PPC64 {774 prog.From = a[0]775 // Second arg is always a register type on ppc64.776 prog.Reg = p.getRegister(prog, op, &a[1])777 prog.SetRestArgs([]obj.Addr{a[2], a[3]})778 prog.To = a[4]779 break780 }781 if p.arch.Family == sys.AMD64 {782 prog.From = a[0]783 prog.SetRestArgs([]obj.Addr{a[1], a[2], a[3]})784 prog.To = a[4]785 break786 }787 if p.arch.Family == sys.S390X {788 prog.From = a[0]789 prog.SetRestArgs([]obj.Addr{a[1], a[2], a[3]})790 prog.To = a[4]791 break792 }793 p.errorf("can't handle %s instruction with 5 operands", op)794 return795 case 6:796 if p.arch.Family == sys.ARM && arch.IsARMMRC(op) {797 // Strange special case: MCR, MRC.798 prog.To.Type = obj.TYPE_CONST799 x0 := p.getConstant(prog, op, &a[0])800 x1 := p.getConstant(prog, op, &a[1])801 x2 := int64(p.getRegister(prog, op, &a[2]))802 x3 := int64(p.getRegister(prog, op, &a[3]))803 x4 := int64(p.getRegister(prog, op, &a[4]))804 x5 := p.getConstant(prog, op, &a[5])805 // Cond is handled specially for this instruction.806 offset, MRC, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5)807 if !ok {808 p.errorf("unrecognized condition code .%q", cond)809 }810 prog.To.Offset = offset811 cond = ""812 prog.As = MRC // Both instructions are coded as MRC.813 break814 }815 fallthrough816 default:817 p.errorf("can't handle %s instruction with %d operands", op, len(a))818 return819 }820 p.append(prog, cond, true)821}822// newAddr returns a new(Addr) initialized to x.823func newAddr(x obj.Addr) *obj.Addr {824 p := new(obj.Addr)825 *p = x826 return p827}828// symbolName returns the symbol name, or an error string if none if available.829func symbolName(addr *obj.Addr) string {830 if addr.Sym != nil {831 return addr.Sym.Name832 }833 return "<erroneous symbol>"834}835var emptyProg obj.Prog836// getConstantPseudo checks that addr represents a plain constant and returns its value.837func (p *Parser) getConstantPseudo(pseudo string, addr *obj.Addr) int64 {838 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {839 p.errorf("%s: expected integer constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))840 }841 return addr.Offset842}843// getConstant checks that addr represents a plain constant and returns its value.844func (p *Parser) getConstant(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {845 if addr.Type != obj.TYPE_MEM || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {846 p.errorf("%s: expected integer constant; found %s", op, obj.Dconv(prog, addr))847 }848 return addr.Offset849}850// getImmediate checks that addr represents an immediate constant and returns its value.851func (p *Parser) getImmediate(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {852 if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {853 p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, addr))854 }855 return addr.Offset856}857// getRegister checks that addr represents a register and returns its value.858func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 {859 if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {860 p.errorf("%s: expected register; found %s", op, obj.Dconv(prog, addr))861 }862 return addr.Reg863}...
Target
Using AI Code Generation
1import (2func main() {3 p := new(prog)4 p.Target()5}6import (7func main() {8 p := new(prog)9 p.Target()10}11import (12func main() {13 p := new(prog)14 p.Target()15}16import (17func main() {18 p := new(prog)19 p.Target()20}21import (22func main() {23 p := new(prog)24 p.Target()25}26import (27func main() {28 p := new(prog)29 p.Target()30}31import (32func main() {33 p := new(prog)34 p.Target()35}36import (37func main() {38 p := new(prog)39 p.Target()40}41import (42func main() {43 p := new(prog)44 p.Target()45}46import (47func main() {48 p := new(prog)49 p.Target()50}51import (52func main() {53 p := new(prog)54 p.Target()55}56import (57func main() {58 p := new(prog)59 p.Target()60}
Target
Using AI Code Generation
1import (2func main() {3 cmd := exec.Command("ls", "-la")4 cmd.Run()5 fmt.Println("Target of cmd is:", cmd.Process.Pid)6}
Target
Using AI Code Generation
1import "fmt"2func main() {3 fmt.Println("Hello, playground")4 p := new(prog)5 p.Target()6}7import "fmt"8type prog struct {9}10func (p *prog) Target() {11 fmt.Println("Target method")12}13prog.go:9: cannot use p (type *prog) as type prog in assignment14prog.go:10: cannot use p (type *prog) as type prog in assignment15prog.go:10: cannot use p (type *prog) as type prog in assignment16I have a Go file, prog.go , that defines a prog class. I have another Go file, 2.go , that uses the Target method of the prog class. I have another Go file, 1.go , that imports the prog class. I want to run 2.go file by using the following command go run 1.go prog.go 2.go . But I am getting the following error prog.go:9: cannot use p (type *prog) as type prog in assignment prog.go:10: cannot use p (type *prog) as type prog in assignment prog.go:10: cannot use p (type *prog) as type prog in assignment
Target
Using AI Code Generation
1import "fmt"2func main() {3 fmt.Println("Hello, playground")4 p.Target()5}6import "fmt"7type prog struct {8}9func (p *prog) Target() {10 fmt.Println("target")11}
Target
Using AI Code Generation
1import "fmt"2func main() {3 fmt.Println("Hello, playground")4 p := new(prog)5 p.Target()6}7import "fmt"8type prog struct {9}10func (p *prog) Target() {11 fmt.Println("Hello, playground")12}
Target
Using AI Code Generation
1import "fmt"2import "prog"3func main() {4fmt.Println(prog.Target())5}6You can use the import button to import the packages in your code. You can use the import button to import the packages in your code. You can use the import button to import the packages in your code. You can use the import button to imp
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!