Best Syzkaller code snippet using compiler.addConst
compile.go
Source:compile.go
...195 return false196}197// Add a constant to the current bytecodetype's constant pool198// and return it's index199func (c *compiler) addConst(value Value) int {200 f := c.block.bytecode201 valueType := value.Type()202 for i, c := range f.Consts {203 if c.Type() == valueType && c == value {204 return i205 }206 }207 if f.NumConsts > bytecodeMaxConsts-1 {208 c.error(0, "too many constants") // should never happen209 }210 f.Consts = append(f.Consts, value)211 f.NumConsts++212 return int(f.NumConsts - 1)213}214// Try to "constant fold" an expression215func (c *compiler) constFold(node ast.Node) (Value, bool) {216 switch t := node.(type) {217 case *ast.Number:218 return Number(t.Value), true219 case *ast.Bool:220 return Bool(t.Value), true221 case *ast.String:222 return String(t.Value), true223 case *ast.Id:224 info, ok := c.block.nameInfo(t.Value)225 if ok && info.isConst {226 return info.value, true227 }228 case *ast.CallExpr:229 id, ok := t.Left.(*ast.Id)230 if ok && len(t.Args) == 1 {231 rv, ok := c.constFold(t.Args[0])232 if !ok {233 return nil, false234 }235 if id.Value == "string" {236 return String(rv.String()), true237 } else if id.Value == "number" {238 switch rv.Type() {239 case ValueNumber:240 return rv, true241 case ValueString:242 n, err := parseNumber(rv.String())243 if err != nil {244 return nil, false245 }246 return Number(n), true247 }248 } else if id.Value == "bool" {249 return Bool(rv.ToBool()), true250 }251 }252 case *ast.UnaryExpr:253 if t.Op == ast.TokenMinus {254 val, ok := c.constFold(t.Right)255 if ok && val.Type() == ValueNumber {256 f64, _ := val.assertFloat64()257 return Number(-f64), true258 }259 return nil, false260 } else {261 // 'not' operator262 val, ok := c.constFold(t.Right)263 if ok && val.Type() == ValueBool {264 bool_, _ := val.assertBool()265 return Bool(!bool_), true266 }267 return nil, false268 }269 case *ast.BinaryExpr:270 left, leftOk := c.constFold(t.Left)271 right, rightOk := c.constFold(t.Right)272 if leftOk && rightOk {273 var ret Value274 if left.Type() != right.Type() {275 if t.Op == ast.TokenEqeq {276 return Bool(false), true277 }278 if t.Op == ast.TokenBangeq {279 return Bool(true), true280 }281 return nil, false282 }283 lf64, ok := left.assertFloat64()284 rf64, _ := right.assertFloat64()285 if !ok {286 goto boolOps287 }288 // first check all arithmetic/relational operations289 switch t.Op {290 case ast.TokenPlus:291 ret = Number(lf64 + rf64)292 case ast.TokenMinus:293 ret = Number(lf64 - rf64)294 case ast.TokenTimes:295 ret = Number(lf64 * rf64)296 case ast.TokenDiv:297 ret = Number(lf64 / rf64)298 case ast.TokenTimestimes:299 ret = Number(math.Pow(lf64, rf64))300 case ast.TokenLt:301 ret = Bool(lf64 < rf64)302 case ast.TokenLteq:303 ret = Bool(lf64 <= rf64)304 case ast.TokenGt:305 ret = Bool(lf64 > rf64)306 case ast.TokenGteq:307 ret = Bool(lf64 >= rf64)308 case ast.TokenEqeq:309 ret = Bool(lf64 == rf64)310 }311 if ret != nil {312 return ret, true313 }314 boolOps:315 // not arithmetic/relational, maybe logic?316 lb, ok := left.assertBool()317 rb, _ := right.assertBool()318 if !ok {319 goto stringOps320 }321 switch t.Op {322 case ast.TokenAmpamp:323 return Bool(lb && rb), true324 case ast.TokenPipepipe:325 return Bool(lb || rb), true326 }327 stringOps:328 ls, ok := left.assertString()329 rs, _ := right.assertString()330 if !ok {331 return nil, false332 }333 switch t.Op {334 case ast.TokenPlus:335 return String(ls + rs), true336 case ast.TokenLt:337 ret = Bool(ls < rs)338 case ast.TokenLteq:339 ret = Bool(ls <= rs)340 case ast.TokenGt:341 ret = Bool(ls > rs)342 case ast.TokenGteq:343 ret = Bool(ls >= rs)344 case ast.TokenEqeq:345 return Bool(ls == rs), true346 case ast.TokenBangeq:347 return Bool(ls != rs), true348 }349 }350 }351 return nil, false352}353// declare local variables354// assignments are done in sequence, since the registers are created as needed355func (c *compiler) declare(names []*ast.Id, values []ast.Node) {356 var isCall, isUnpack bool357 nameCount, valueCount := len(names), len(values)358 if valueCount > 0 {359 _, isCall = values[valueCount-1].(*ast.CallExpr)360 _, isUnpack = values[valueCount-1].(*ast.VarArg)361 }362 start := c.block.register363 end := start + nameCount - 1364 for i, id := range names {365 _, ok := c.block.names[id.Value]366 if ok {367 c.error(id.NodeInfo.Line, fmt.Sprintf("cannot redeclare '%s'", id.Value))368 }369 reg := c.genRegister()370 exprdata := exprdata{false, reg, reg}371 if i == valueCount-1 && (isCall || isUnpack) {372 // last expression receives all the remaining registers373 // in case it's a function call with multiple return values374 rem := i + 1375 for rem < nameCount {376 // reserve the registers377 id := names[rem]378 _, ok := c.block.names[id.Value]379 if ok {380 c.error(id.NodeInfo.Line, fmt.Sprintf("cannot redeclare '%s'", id.Value))381 }382 end = c.genRegister()383 c.block.addNameInfo(id.Value, &nameInfo{false, nil, end, kScopeLocal, c.block})384 rem++385 }386 exprdata.regb, start = end, end+1387 values[i].Accept(c, &exprdata)388 } else if i < valueCount {389 values[i].Accept(c, &exprdata)390 start = reg + 1391 }392 // add name info after the value (the variable should not be visible to it's own initializer)393 c.block.addNameInfo(id.Value, &nameInfo{false, nil, reg, kScopeLocal, c.block})394 }395 if end >= start {396 // variables without initializer are set to nil397 c.emitAB(OpLoadnil, start, end, names[0].NodeInfo.Line)398 }399}400func (c *compiler) assignmentHelper(left ast.Node, assignReg int, valueReg int) {401 switch v := left.(type) {402 case *ast.Id:403 var scope scope404 info, ok := c.block.nameInfo(v.Value)405 if !ok {406 scope = kScopeGlobal407 } else {408 scope = info.scope409 }410 switch scope {411 case kScopeLocal:412 c.emitAB(OpMove, info.reg, valueReg, v.NodeInfo.Line)413 case kScopeClosure, kScopeGlobal:414 op := OpSetglobal415 if scope == kScopeClosure {416 op = OpSetFree417 }418 c.emitABx(op, valueReg, c.addConst(String(v.Value)), v.NodeInfo.Line)419 }420 case *ast.Subscript:421 arrData := exprdata{true, assignReg, assignReg}422 v.Left.Accept(c, &arrData)423 arrReg := arrData.regb424 subData := exprdata{true, assignReg, assignReg}425 v.Right.Accept(c, &subData)426 subReg := subData.regb427 c.emitABC(OpSetIndex, arrReg, subReg, valueReg, v.NodeInfo.Line)428 case *ast.Selector:429 objData := exprdata{true, assignReg, assignReg}430 v.Left.Accept(c, &objData)431 objReg := objData.regb432 key := OpConstOffset + c.addConst(String(v.Value))433 c.emitABC(OpSetIndex, objReg, key, valueReg, v.NodeInfo.Line)434 }435}436func (c *compiler) branchConditionHelper(cond, then, else_ ast.Node, reg int) {437 ternaryData := exprdata{true, reg + 1, reg + 1}438 cond.Accept(c, &ternaryData)439 condr := ternaryData.regb440 jmpInstr := c.emitAsBx(OpJmpfalse, condr, 0, c.lastLine)441 thenLabel := c.newLabel()442 ternaryData = exprdata{false, reg, reg}443 then.Accept(c, &ternaryData)444 c.modifyAsBx(jmpInstr, OpJmpfalse, condr, c.labelOffset(thenLabel))445 if else_ != nil {446 successInstr := c.emitAsBx(OpJmp, 0, 0, c.lastLine)447 elseLabel := c.newLabel()448 ternaryData = exprdata{false, reg, reg}449 else_.Accept(c, &ternaryData)450 c.modifyAsBx(successInstr, OpJmp, 0, c.labelOffset(elseLabel))451 }452}453func (c *compiler) functionReturnGuard() {454 last := c.block.bytecode.Code[c.block.bytecode.NumCode-1]455 if OpGetOpcode(last) != OpReturn {456 c.emitAB(OpReturn, 0, 0, c.lastLine)457 }458}459//460// visitor interface461//462func (c *compiler) VisitNil(node *ast.Nil, data interface{}) {463 var rega, regb int464 expr, ok := data.(*exprdata)465 if ok {466 rega, regb = expr.rega, expr.regb467 if rega > regb {468 regb = rega469 }470 } else {471 rega = c.genRegister()472 regb = rega473 }474 c.emitAB(OpLoadnil, rega, regb, node.NodeInfo.Line)475}476func (c *compiler) VisitBool(node *ast.Bool, data interface{}) {477 var reg int478 value := Bool(node.Value)479 expr, ok := data.(*exprdata)480 if ok && expr.propagate {481 expr.regb = OpConstOffset + c.addConst(value)482 return483 } else if ok {484 reg = expr.rega485 } else {486 reg = c.genRegister()487 }488 c.emitABx(OpLoadconst, reg, c.addConst(value), node.NodeInfo.Line)489}490func (c *compiler) VisitNumber(node *ast.Number, data interface{}) {491 var reg int492 value := Number(node.Value)493 expr, ok := data.(*exprdata)494 if ok && expr.propagate {495 expr.regb = OpConstOffset + c.addConst(value)496 return497 } else if ok {498 reg = expr.rega499 } else {500 reg = c.genRegister()501 }502 c.emitABx(OpLoadconst, reg, c.addConst(value), node.NodeInfo.Line)503}504func (c *compiler) VisitString(node *ast.String, data interface{}) {505 var reg int506 value := String(node.Value)507 expr, ok := data.(*exprdata)508 if ok && expr.propagate {509 expr.regb = OpConstOffset + c.addConst(value)510 return511 } else if ok {512 reg = expr.rega513 } else {514 reg = c.genRegister()515 }516 c.emitABx(OpLoadconst, reg, c.addConst(value), node.NodeInfo.Line)517}518func (c *compiler) VisitId(node *ast.Id, data interface{}) {519 var reg int520 var scope scope = -1521 expr, exprok := data.(*exprdata)522 if !exprok {523 reg = c.genRegister()524 } else {525 reg = expr.rega526 }527 info, ok := c.block.nameInfo(node.Value)528 if ok && info.isConst {529 if exprok && expr.propagate {530 expr.regb = OpConstOffset + c.addConst(info.value)531 return532 }533 c.emitABx(OpLoadconst, reg, c.addConst(info.value), node.NodeInfo.Line)534 } else if ok {535 scope = info.scope536 } else {537 // assume global if it can't be found in the lexical scope538 scope = kScopeGlobal539 }540 switch scope {541 case kScopeLocal:542 if exprok && expr.propagate {543 expr.regb = info.reg544 return545 }546 c.emitAB(OpMove, reg, info.reg, node.NodeInfo.Line)547 case kScopeClosure, kScopeGlobal:548 op := OpLoadglobal549 if scope == kScopeClosure {550 op = OpLoadFree551 }552 c.emitABx(op, reg, c.addConst(String(node.Value)), node.NodeInfo.Line)553 if exprok && expr.propagate {554 expr.regb = reg555 }556 }557}558func (c *compiler) VisitArray(node *ast.Array, data interface{}) {559 var reg int560 expr, exprok := data.(*exprdata)561 if exprok {562 reg = expr.rega563 } else {564 reg = c.genRegister()565 }566 length := len(node.Elements)567 c.emitAB(OpArray, reg, 0, node.NodeInfo.Line)568 times := length/kArrayMaxRegisters + 1569 for t := 0; t < times; t++ {570 start, end := t*kArrayMaxRegisters, (t+1)*kArrayMaxRegisters571 end = int(math.Min(float64(end-start), float64(length-start)))572 if end == 0 {573 break574 }575 for i := 0; i < end; i++ {576 el := node.Elements[start+i]577 exprdata := exprdata{false, reg + i + 1, reg + i + 1}578 el.Accept(c, &exprdata)579 }580 c.emitAB(OpAppend, reg, end, node.NodeInfo.Line)581 }582 if exprok && expr.propagate {583 expr.regb = reg584 }585}586func (c *compiler) VisitObjectField(node *ast.ObjectField, data interface{}) {587 expr, exprok := data.(*exprdata)588 assert(exprok, "ObjectField exprok")589 objreg := expr.rega590 key := OpConstOffset + c.addConst(String(node.Key))591 valueData := exprdata{true, objreg + 1, objreg + 1}592 node.Value.Accept(c, &valueData)593 value := valueData.regb594 c.emitABC(OpSetIndex, objreg, key, value, node.NodeInfo.Line)595}596func (c *compiler) VisitObject(node *ast.Object, data interface{}) {597 var reg int598 expr, exprok := data.(*exprdata)599 if exprok {600 reg = expr.rega601 } else {602 reg = c.genRegister()603 }604 c.emitAB(OpObject, reg, 0, node.NodeInfo.Line)605 for _, field := range node.Fields {606 fieldData := exprdata{false, reg, reg}607 field.Accept(c, &fieldData)608 }609 if exprok && expr.propagate {610 expr.regb = reg611 }612}613func (c *compiler) VisitFunction(node *ast.Function, data interface{}) {614 var reg int615 expr, exprok := data.(*exprdata)616 if exprok {617 reg = expr.rega618 } else {619 reg = c.genRegister()620 }621 parent := c.block.bytecode622 bytecode := newBytecode(parent.Source)623 block := newCompilerBlock(bytecode, kBlockContextFunc, c.block)624 c.block = block625 index := int(parent.NumFuncs)626 parent.Funcs = append(parent.Funcs, bytecode)627 parent.NumFuncs++628 // insert 'this' into scope629 c.declareLocalVar("this", c.genRegister())630 // insert arguments into scope631 for _, n := range node.Args {632 switch arg := n.(type) {633 case *ast.Id:634 reg := c.genRegister()635 c.block.addNameInfo(arg.Value, &nameInfo{false, nil, reg, kScopeLocal, c.block})636 }637 }638 node.Body.Accept(c, nil)639 c.functionReturnGuard()640 c.block = c.block.parent641 c.emitABx(OpFunc, reg, index, node.NodeInfo.Line)642 if node.Name != nil {643 switch name := node.Name.(type) {644 case *ast.Id:645 c.declareLocalVar(name.Value, reg)646 default:647 c.assignmentHelper(name, reg+1, reg)648 }649 }650 if exprok && expr.propagate {651 expr.regb = reg652 }653}654func (c *compiler) VisitSelector(node *ast.Selector, data interface{}) {655 var reg int656 expr, exprok := data.(*exprdata)657 if exprok {658 reg = expr.rega659 } else {660 reg = c.genRegister()661 }662 objData := exprdata{true, reg + 1, reg + 1}663 node.Left.Accept(c, &objData)664 objReg := objData.regb665 key := OpConstOffset + c.addConst(String(node.Value))666 c.emitABC(OpGetIndex, reg, objReg, key, node.NodeInfo.Line)667 if exprok && expr.propagate {668 expr.regb = objReg669 }670}671func (c *compiler) VisitSubscript(node *ast.Subscript, data interface{}) {672 var reg int673 expr, exprok := data.(*exprdata)674 if exprok {675 reg = expr.rega676 } else {677 reg = c.genRegister()678 }679 arrData := exprdata{true, reg + 1, reg + 1}680 node.Left.Accept(c, &arrData)681 arrReg := arrData.regb682 _, ok := node.Right.(*ast.Slice)683 if ok {684 // TODO: generate code for slice685 return686 }687 indexData := exprdata{true, reg + 1, reg + 1}688 node.Right.Accept(c, &indexData)689 indexReg := indexData.regb690 c.emitABC(OpGetIndex, reg, arrReg, indexReg, node.NodeInfo.Line)691 if exprok && expr.propagate {692 expr.regb = reg693 }694}695func (c *compiler) VisitSlice(node *ast.Slice, data interface{}) {696}697func (c *compiler) VisitKwArg(node *ast.KwArg, data interface{}) {698}699func (c *compiler) VisitVarArg(node *ast.VarArg, data interface{}) {700}701func (c *compiler) VisitCallExpr(node *ast.CallExpr, data interface{}) {702 var startReg, endReg, resultCount int703 expr, exprok := data.(*exprdata)704 if exprok {705 startReg, endReg = expr.rega, expr.regb706 resultCount = endReg - startReg + 1707 } else {708 startReg = c.genRegister()709 endReg = startReg710 resultCount = 1711 }712 // check if it's a type conversion (string, number, bool)713 v, ok := c.constFold(node)714 if ok {715 c.emitABx(OpLoadconst, startReg, c.addConst(v), node.NodeInfo.Line)716 return717 }718 argCount := len(node.Args)719 var op Opcode720 switch node.Left.(type) {721 case *ast.Selector:722 op = OpCallmethod723 callerData := exprdata{true, startReg, startReg}724 node.Left.Accept(c, &callerData)725 objReg := callerData.regb726 // insert object as first argument727 endReg += 1728 argCount += 1729 c.emitAB(OpMove, endReg, objReg, node.NodeInfo.Line)730 default:731 op = OpCall732 callerData := exprdata{false, startReg, startReg}733 node.Left.Accept(c, &callerData)734 }735 for i, arg := range node.Args {736 reg := endReg + i + 1737 argData := exprdata{false, reg, reg}738 arg.Accept(c, &argData)739 }740 c.emitABC(op, startReg, resultCount, argCount, node.NodeInfo.Line)741}742func (c *compiler) VisitPostfixExpr(node *ast.PostfixExpr, data interface{}) {743 var reg int744 expr, exprok := data.(*exprdata)745 if exprok {746 reg = expr.rega747 } else {748 reg = c.genRegister()749 }750 var op Opcode751 switch node.Op {752 case ast.TokenPlusplus:753 op = OpAdd754 case ast.TokenMinusminus:755 op = OpSub756 }757 leftdata := exprdata{true, reg, reg}758 node.Left.Accept(c, &leftdata)759 left := leftdata.regb760 one := OpConstOffset + c.addConst(Number(1))761 // don't bother moving if we're not in an expression762 if exprok {763 c.emitAB(OpMove, reg, left, node.NodeInfo.Line)764 }765 c.emitABC(op, left, left, one, node.NodeInfo.Line)766}767func (c *compiler) VisitUnaryExpr(node *ast.UnaryExpr, data interface{}) {768 var reg int769 expr, exprok := data.(*exprdata)770 if exprok {771 reg = expr.rega772 } else {773 reg = c.genRegister()774 }775 value, ok := c.constFold(node)776 if ok {777 if exprok && expr.propagate {778 expr.regb = OpConstOffset + c.addConst(value)779 return780 }781 c.emitABx(OpLoadconst, reg, c.addConst(value), node.NodeInfo.Line)782 } else if ast.IsPostfixOp(node.Op) {783 op := OpAdd784 if node.Op == ast.TokenMinusminus {785 op = OpSub786 }787 exprdata := exprdata{true, reg, reg}788 node.Right.Accept(c, &exprdata)789 one := OpConstOffset + c.addConst(Number(1))790 c.emitABC(op, exprdata.regb, exprdata.regb, one, node.NodeInfo.Line)791 // don't bother moving if we're not in an expression792 if exprok {793 c.emitAB(OpMove, reg, exprdata.regb, node.NodeInfo.Line)794 }795 } else {796 var op Opcode797 switch node.Op {798 case ast.TokenMinus:799 op = OpUnm800 case ast.TokenNot, ast.TokenBang:801 op = OpNot802 case ast.TokenTilde:803 op = OpCmpl804 }805 exprdata := exprdata{true, reg, reg}806 node.Right.Accept(c, &exprdata)807 c.emitABx(op, reg, exprdata.regb, node.NodeInfo.Line)808 if exprok && expr.propagate {809 expr.regb = reg810 }811 }812}813func (c *compiler) VisitBinaryExpr(node *ast.BinaryExpr, data interface{}) {814 var reg int815 expr, exprok := data.(*exprdata)816 if exprok {817 reg = expr.rega818 } else {819 reg = c.genRegister()820 }821 value, ok := c.constFold(node)822 if ok {823 if exprok && expr.propagate {824 expr.regb = OpConstOffset + c.addConst(value)825 return826 }827 c.emitABx(OpLoadconst, reg, c.addConst(value), node.NodeInfo.Line)828 } else {829 if isAnd, isOr := node.Op == ast.TokenAmpamp, node.Op == ast.TokenPipepipe; isAnd || isOr {830 var op Opcode831 if isAnd {832 op = OpJmpfalse833 } else {834 op = OpJmptrue835 }836 exprdata := exprdata{expr.propagate, reg, reg}837 node.Left.Accept(c, &exprdata)838 left := exprdata.regb839 jmpInstr := c.emitAsBx(op, left, 0, node.NodeInfo.Line)840 rightLabel := c.newLabel()841 node.Right.Accept(c, &exprdata)842 c.modifyAsBx(jmpInstr, op, left, c.labelOffset(rightLabel))843 return844 }845 var op Opcode846 switch node.Op {847 case ast.TokenPlus:848 op = OpAdd849 case ast.TokenMinus:850 op = OpSub851 case ast.TokenTimes:852 op = OpMul853 case ast.TokenDiv:854 op = OpDiv855 case ast.TokenTimestimes:856 op = OpPow857 case ast.TokenLtlt:858 op = OpShl859 case ast.TokenGtgt:860 op = OpShr861 case ast.TokenAmp:862 op = OpAnd863 case ast.TokenPipe:864 op = OpOr865 case ast.TokenTilde:866 op = OpXor867 case ast.TokenLt, ast.TokenGteq:868 op = OpLt869 case ast.TokenLteq, ast.TokenGt:870 op = OpLe871 case ast.TokenEq:872 op = OpEq873 case ast.TokenBangeq:874 op = OpNe875 }876 exprdata := exprdata{true, reg, 0}877 node.Left.Accept(c, &exprdata)878 left := exprdata.regb879 // temp register for right expression880 exprdata.rega += 1881 node.Right.Accept(c, &exprdata)882 right := exprdata.regb883 if node.Op == ast.TokenGt || node.Op == ast.TokenGteq {884 // invert operands885 c.emitABC(op, reg, right, left, node.NodeInfo.Line)886 } else {887 c.emitABC(op, reg, left, right, node.NodeInfo.Line)888 }889 if exprok && expr.propagate {890 expr.regb = reg891 }892 }893}894func (c *compiler) VisitTernaryExpr(node *ast.TernaryExpr, data interface{}) {895 var reg int896 expr, exprok := data.(*exprdata)897 if exprok {898 reg = expr.rega899 } else {900 reg = c.genRegister()901 }902 c.branchConditionHelper(node.Cond, node.Then, node.Else, reg)903}904func (c *compiler) VisitDeclaration(node *ast.Declaration, data interface{}) {905 valueCount := len(node.Right)906 if node.IsConst {907 for i, id := range node.Left {908 _, ok := c.block.names[id.Value]909 if ok {910 c.error(node.NodeInfo.Line, fmt.Sprintf("cannot redeclare '%s'", id.Value))911 }912 if i >= valueCount {913 c.error(node.NodeInfo.Line, fmt.Sprintf("const '%s' without initializer", id.Value))914 }915 value, ok := c.constFold(node.Right[i])916 if !ok {917 c.error(node.NodeInfo.Line, fmt.Sprintf("const '%s' initializer is not a constant", id.Value))918 }919 c.block.addNameInfo(id.Value, &nameInfo{true, value, 0, kScopeLocal, c.block})920 }921 return922 }923 c.declare(node.Left, node.Right)924}925func (c *compiler) VisitAssignment(node *ast.Assignment, data interface{}) {926 if node.Op == ast.TokenColoneq {927 // short variable declaration928 var names []*ast.Id929 for _, id := range node.Left {930 names = append(names, id.(*ast.Id))931 }932 c.declare(names, node.Right)933 return934 } else if node.Op != ast.TokenEq {935 // compound assignment936 // a += b -> a = a + b937 bin := ast.BinaryExpr{Op: ast.CompoundOp(node.Op), Left: node.Left[0], Right: node.Right[0]}938 fake := ast.Assignment{Op: ast.TokenEq, Left: node.Left, Right: []ast.Node{&bin}}939 fake.Accept(c, nil)940 return941 }942 // regular assignment, if the left-side is an identifier943 // then it has to be declared already944 varCount, valueCount := len(node.Left), len(node.Right)945 _, isCall := node.Right[valueCount-1].(*ast.CallExpr)946 _, isUnpack := node.Right[valueCount-1].(*ast.VarArg)947 start := c.block.register948 current := start949 end := start + varCount - 1950 // evaluate all expressions first with temp registers951 for i, _ := range node.Left {952 reg := start + i953 exprdata := exprdata{false, reg, reg}954 if i == valueCount-1 && (isCall || isUnpack) {955 exprdata.regb, current = end, end956 node.Right[i].Accept(c, &exprdata)957 break958 }959 if i < valueCount {960 node.Right[i].Accept(c, &exprdata)961 current = reg + 1962 }963 }964 // assign the results to the variables965 for i, variable := range node.Left {966 valueReg := start + i967 // don't touch variables without a corresponding value968 if valueReg > current {969 break970 }971 c.assignmentHelper(variable, current+1, valueReg)972 }973}974func (c *compiler) VisitBranchStmt(node *ast.BranchStmt, data interface{}) {975 if !c.insideLoop() {976 c.error(node.NodeInfo.Line, fmt.Sprintf("%s outside loop", node.Type))977 }978 instr := c.emitAsBx(OpJmp, 0, 0, node.NodeInfo.Line)979 switch node.Type {980 case ast.TokenContinue:981 c.block.loop.continues = append(c.block.loop.continues, uint32(instr))982 case ast.TokenBreak:983 c.block.loop.breaks = append(c.block.loop.breaks, uint32(instr))984 }985}986func (c *compiler) VisitReturnStmt(node *ast.ReturnStmt, data interface{}) {987 start := c.block.register988 for _, v := range node.Values {989 reg := c.genRegister()990 data := exprdata{false, reg, reg}991 v.Accept(c, &data)992 }993 c.emitAB(OpReturn, start, len(node.Values), node.NodeInfo.Line)994}995func (c *compiler) VisitPanicStmt(node *ast.PanicStmt, data interface{}) {996}997func (c *compiler) VisitIfStmt(node *ast.IfStmt, data interface{}) {998 _, ok := data.(*exprdata)999 if !ok {1000 c.enterBlock(kBlockContextBranch)1001 defer c.leaveBlock()1002 }1003 if node.Init != nil {1004 node.Init.Accept(c, nil)1005 }1006 c.branchConditionHelper(node.Cond, node.Body, node.Else, c.block.register)1007}1008func (c *compiler) VisitForIteratorStmt(node *ast.ForIteratorStmt, data interface{}) {1009 c.enterBlock(kBlockContextLoop)1010 defer c.leaveBlock()1011 arrReg := c.genRegister()1012 lenReg := c.genRegister()1013 keyReg := c.genRegister()1014 idxReg := c.genRegister()1015 valReg := c.genRegister()1016 colReg := c.genRegister()1017 collectionData := exprdata{false, colReg, colReg}1018 node.Collection.Accept(c, &collectionData)1019 c.emitAB(OpForbegin, arrReg, colReg, node.NodeInfo.Line)1020 c.emitABx(OpLoadconst, idxReg, c.addConst(Number(0)), c.lastLine)1021 if node.Value == nil {1022 c.declareLocalVar(node.Key.Value, valReg)1023 } else {1024 c.declareLocalVar(node.Key.Value, keyReg)1025 c.declareLocalVar(node.Value.Value, valReg)1026 }1027 testLabel := c.newLabel()1028 testReg := c.block.register1029 c.emitABC(OpLt, testReg, idxReg, lenReg, c.lastLine)1030 jmpInstr := c.emitAsBx(OpJmpfalse, testReg, 0, c.lastLine)1031 c.emitABC(OpForiter, keyReg, colReg, arrReg, node.NodeInfo.Line)1032 c.emitABC(OpGetIndex, valReg, colReg, keyReg, c.lastLine)1033 node.Body.Accept(c, nil)1034 c.block.loop.continueTarget = c.newLabel()...
consts.go
Source:consts.go
...59 if _, builtin := comp.builtinConsts[name]; builtin {60 comp.error(pos, "redefining builtin const %v", name)61 }62 info.defines[name] = v63 comp.addConst(infos, pos, name)64 case *ast.Call:65 if comp.target.SyscallNumbers && !strings.HasPrefix(n.CallName, "syz_") {66 comp.addConst(infos, pos, comp.target.SyscallPrefix+n.CallName)67 }68 for _, attr := range n.Attrs {69 if callAttrs[attr.Ident].HasArg {70 comp.addConst(infos, attr.Pos, attr.Args[0].Ident)71 }72 }73 case *ast.Struct:74 for _, attr := range n.Attrs {75 if structOrUnionAttrs(n)[attr.Ident].HasArg {76 comp.addConst(infos, attr.Pos, attr.Args[0].Ident)77 }78 }79 }80 switch decl.(type) {81 case *ast.Call, *ast.Struct, *ast.Resource, *ast.TypeDef:82 comp.extractTypeConsts(infos, decl)83 }84 }85 comp.desc.Walk(ast.Recursive(func(n0 ast.Node) {86 if n, ok := n0.(*ast.Int); ok {87 comp.addConst(infos, n.Pos, n.Ident)88 }89 }))90 return convertConstInfo(infos)91}92func (comp *compiler) extractTypeConsts(infos map[string]*constInfo, n ast.Node) {93 comp.foreachType(n, func(t *ast.Type, desc *typeDesc, args []*ast.Type, _ prog.IntTypeCommon) {94 for i, arg := range args {95 if desc.Args[i].Type.Kind == kindInt {96 if arg.Ident != "" {97 comp.addConst(infos, arg.Pos, arg.Ident)98 }99 for _, col := range arg.Colon {100 if col.Ident != "" {101 comp.addConst(infos, col.Pos, col.Ident)102 }103 }104 }105 }106 })107}108func (comp *compiler) addConst(infos map[string]*constInfo, pos ast.Pos, name string) {109 if _, builtin := comp.builtinConsts[name]; builtin {110 return111 }112 info := getConstInfo(infos, pos)113 info.consts[name] = true114}115type constInfo struct {116 consts map[string]bool117 defines map[string]string118 includeArray []string119 incdirArray []string120}121func getConstInfo(infos map[string]*constInfo, pos ast.Pos) *constInfo {122 info := infos[pos.File]...
addConst
Using AI Code Generation
1import "fmt"2func main() {3 fmt.Println("Hello, playground")4}5import "fmt"6func main() {7 fmt.Println("Hello, playground")8}9import "fmt"10func main() {11 fmt.Println("Hello, playground")12}13import "fmt"14func main() {15 fmt.Println("Hello, playground")16}17import "fmt"18func main() {19 fmt.Println("Hello, playground")20}21import "fmt"22func main() {23 fmt.Println("Hello, playground")24}25import "fmt"26func main() {27 fmt.Println("Hello, playground")28}29import "fmt"30func main() {31 fmt.Println("Hello, playground")32}33import "fmt"34func main() {35 fmt.Println("Hello, playground")36}37import "fmt"38func main() {39 fmt.Println("Hello, playground")40}41import "fmt"42func main() {43 fmt.Println("Hello, playground")44}45import "fmt"46func main() {47 fmt.Println("Hello, playground")48}49import "fmt"50func main() {51 fmt.Println("Hello, playground")52}53import
addConst
Using AI Code Generation
1func main() {2 c := compiler{}3 c.addConst(1)4 c.addConst(2)5 c.addConst(3)6 fmt.Println(c.consts)7}8func main() {9 c := compiler{}10 c.addConst(1)11 c.addConst(2)12 c.addConst(3)13 c.addConst(1)14 c.addConst(2)15 c.addConst(3)16 fmt.Println(c.consts)17}18func main() {19 c := compiler{}20 c.addConst(1)21 c.addConst(2)22 c.addConst(3)23 c.addConst(1)24 c.addConst(2)25 c.addConst(3)26 fmt.Println(c.getConst(5))27}28func main() {29 c := compiler{}30 c.addConst(1)31 c.addConst(2)32 c.addConst(3)33 c.addConst(1)34 c.addConst(2)35 c.addConst(3)36 fmt.Println(c.getConst(2))37}38func main() {39 c := compiler{}40 c.addConst(1)41 c.addConst(2)42 c.addConst(3)43 c.addConst(1)44 c.addConst(2)45 c.addConst(3)46 fmt.Println(c.getConst(1))47}48func main() {49 c := compiler{}50 c.addConst(1)51 c.addConst(2)52 c.addConst(3)53 c.addConst(1)54 c.addConst(2)55 c.addConst(3)56 fmt.Println(c.getConst(3))57}
addConst
Using AI Code Generation
1import "fmt"2func main() {3 fmt.Println("Hello, playground")4 c.addConst(2)5}6import "fmt"7func main() {8 fmt.Println("Hello, playground")9 c.addConst(2)10}11import "fmt"12func main() {13 fmt.Println("Hello, playground")14 c.addConst(2)15}16import "fmt"17func main() {18 fmt.Println("Hello, playground")19 c.addConst(2)20}21import "fmt"22func main() {23 fmt.Println("Hello, playground")24 c.addConst(2)25}26import "fmt"27func main() {28 fmt.Println("Hello, playground")29 c.addConst(2)30}31import "fmt"32func main() {33 fmt.Println("Hello, playground")34 c.addConst(2)35}36import "fmt"37func main() {38 fmt.Println("Hello, playground")39 c.addConst(2)40}41import "fmt"42func main() {43 fmt.Println("Hello, playground")44 c.addConst(2)45}46import "fmt"47func main() {48 fmt.Println("Hello, playground")49 c.addConst(2)50}
addConst
Using AI Code Generation
1import "compiler"2func main() {3 c.addConst(10)4 c.addConst(20)5 c.addConst(30)6 c.addConst(40)7 c.addConst(50)8 c.addConst(60)9 c.addConst(70)10 c.addConst(80)11 c.addConst(90)12 c.addConst(100)13 c.addConst(110)14 c.addConst(120)15 c.addConst(130)16 c.addConst(140)17 c.addConst(150)18 c.addConst(160)19 c.addConst(170)20 c.addConst(180)21 c.addConst(190)22 c.addConst(200)23 c.addConst(210)24 c.addConst(220)25 c.addConst(230)26 c.addConst(240)27 c.addConst(250)28 c.addConst(260)29 c.addConst(270)30 c.addConst(280)31 c.addConst(290)32 c.addConst(300)33 c.addConst(310)34 c.addConst(320)35 c.addConst(330)36 c.addConst(340)37 c.addConst(350)38 c.addConst(360)39 c.addConst(370)40 c.addConst(380)41 c.addConst(390)42 c.addConst(400)43 c.addConst(410)44 c.addConst(420)45 c.addConst(430)46 c.addConst(440)47 c.addConst(450)48 c.addConst(460)49 c.addConst(470)50 c.addConst(480)51 c.addConst(490)52 c.addConst(500)53 c.addConst(510)54 c.addConst(520)55 c.addConst(530)56 c.addConst(540)57 c.addConst(550)58 c.addConst(560)59 c.addConst(570)60 c.addConst(580)61 c.addConst(590)62 c.addConst(600)63 c.addConst(610)64 c.addConst(620)65 c.addConst(630)66 c.addConst(640)67 c.addConst(650)68 c.addConst(
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!!