github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/code/instructions.go (about) 1 package code 2 3 // Combine encodes r1 <- op(r2, r3) 4 func Combine(op BinOp, r1, r2, r3 Reg) Opcode { 5 return mkType1(op, r1, r2, r3) 6 } 7 8 // Transform encodes r1 <- op(r2) 9 func Transform(op UnOp, r1, r2 Reg) Opcode { 10 return mkType4a(Off, op, r1, r2) 11 } 12 13 // LoadConst encodes r <- Ki 14 func LoadConst(r Reg, i KIndex) Opcode { 15 return mkType3(Off, OpK, r, i) 16 } 17 18 // LoadClosure encodes r <- clos(Ki) 19 func LoadClosure(r1 Reg, i KIndex) Opcode { 20 return mkType3(Off, OpClosureK, r1, i) 21 } 22 23 // LoadInt16 encodes r <- n 24 func LoadInt16(r Reg, n int16) Opcode { 25 return mkType3(Off, OpInt16, r, Lit16(n)) 26 } 27 28 // LoadSmallInt attempts to load a small integer (atm it has to be representable 29 // as an int16). 30 func LoadSmallInt(r Reg, n int) (Opcode, bool) { 31 sn := int16(n) 32 if int(sn) != n { 33 return 0, false 34 } 35 return LoadInt16(r, sn), true 36 } 37 38 // LoadStr0 encodes r <- "" 39 func LoadStr0(r Reg) Opcode { 40 return mkType4b(Off, OpStr0, r, 0) 41 } 42 43 // LoadStr1 encodes r <- "x" 44 func LoadStr1(r Reg, b []byte) Opcode { 45 return mkType4b(Off, OpStr1, r, Lit8FromStr1(b)) 46 } 47 48 // LoadStr2 encodes r <- "xy" 49 func LoadStr2(r Reg, b []byte) Opcode { 50 return mkType3(Off, OpStr2, r, Lit16FromStr2(b)) 51 } 52 53 // LoadShortString attempts to encode loading a short string. Returns the 54 // opcode and true if it did. 55 func LoadShortString(r Reg, b []byte) (Opcode, bool) { 56 // This code is commented out because it turns out that it causes many 57 // allocations, slowing down the runtime considerably in some cases. 58 // 59 // switch len(b) {case 0: 60 // return LoadStr0(r), true 61 // case 1: 62 // return LoadStr1(r, b), true 63 // case 2: 64 // return LoadStr2(r, b), true 65 // } 66 return 0, false 67 } 68 69 // LoadBool encodes r <- true or r <- false. 70 func LoadBool(r Reg, b bool) Opcode { 71 return mkType4b(Off, OpBool, r, Lit8FromBool(b)) 72 } 73 74 // LoadEmptyTable encodes r <- {} 75 func LoadEmptyTable(r Reg) Opcode { 76 return mkType4b(Off, OpTable, r, 0) 77 } 78 79 // LoadNil encodes r <- nil 80 func LoadNil(r Reg) Opcode { 81 return mkType4b(Off, OpNil, r, 0) 82 } 83 84 // LoadLookup encodes r1 <- r2[r3] 85 func LoadLookup(r1, r2, r3 Reg) Opcode { 86 return mkType2(Off, r1, r2, r3) 87 } 88 89 // SetIndex encodes r2[r3] <- r1 90 func SetIndex(r1, r2, r3 Reg) Opcode { 91 return mkType2(On, r1, r2, r3) 92 } 93 94 // Push encodes push r1, r2 95 // 96 // r1 must contain a continuation. 97 func Push(r1, r2 Reg) Opcode { 98 return mkType4a(On, OpId, r1, r2) 99 } 100 101 // PushEtc encodes pushetc r1, ...r2 102 // 103 // r1 must contain a continuation, r2 an etc. 104 func PushEtc(r1, r2 Reg) Opcode { 105 return mkType4a(On, OpEtcId, r1, r2) 106 } 107 108 // Jump encodes an unconditional jump 109 // 110 // jump j 111 func Jump(j Offset) Opcode { 112 return mkType5(Off, OpJump, Reg{}, j) 113 } 114 115 // JumpIf encodes a conditional jump. 116 // 117 // jump j if r 118 func JumpIf(j Offset, r Reg) Opcode { 119 return mkType5(On, OpJumpIf, r, j) 120 } 121 122 // JumpIfNot encodes a conditional jump. 123 // 124 // jump j if not r 125 func JumpIfNot(j Offset, r Reg) Opcode { 126 return mkType5(Off, OpJumpIf, r, j) 127 } 128 129 // Call encodes call r 130 // 131 // r must contain a continuation that is ready to be called. 132 func Call(r Reg) Opcode { 133 return mkType5(Off, OpCall, r, Offset(0)) 134 } 135 136 // TailCall encodes tailcall r 137 // 138 // r must contain a continuation that is ready to be called. 139 func TailCall(r Reg) Opcode { 140 return mkType5(On, OpCall, r, Offset(0)) 141 } 142 143 // ClTrunc encodes cltrunc h 144 // 145 // It truncates the close stack to the given height. Each value on the close 146 // stack which is removed should either be nil or false, or be a value with a 147 // "__close" metamethod, in which case this metamethod is called. This opcode 148 // is introduced to support Lua 5.4's "to-be-closed" variables. 149 func ClTrunc(h uint16) Opcode { 150 return mkType5(Off, OpClStack, Reg{}, ClStackOffset(h)) 151 } 152 153 // ClPush encodes clpush r 154 // 155 // r should contain either nil, false, or a value with a "__close" metamethod. 156 // This opcode is introduced to support Lua 5.4's "to-be-closed" variables. 157 func ClPush(r Reg) Opcode { 158 return mkType5(On, OpClStack, r, ClStackOffset(0)) 159 } 160 161 // Upval encodes upval r1, r2 162 // 163 // r1 must contain a closure. This appends the value of r2 to the list of 164 // upvalues of r1. 165 func Upval(r1, r2 Reg) Opcode { 166 return mkType4a(Off, OpUpvalue, r1, r2) 167 } 168 169 // Cont encodes r1 <- cont(r2) 170 // 171 // r2 must contain a closure, r1 then contains a new continuation for that 172 // closure, whose next continuation is the cc. 173 func Cont(r1, r2 Reg) Opcode { 174 return mkType4a(Off, OpCont, r1, r2) 175 } 176 177 // TailCont encodes r1 <- tailcont(r2) 178 // 179 // r2 must contain a closure, r1 then contains a new continuatino for that 180 // closure, whose next continuation is the cc's next continuation. 181 func TailCont(r1, r2 Reg) Opcode { 182 return mkType4a(Off, OpTailCont, r1, r2) 183 } 184 185 // Clear encodes clear r 186 // 187 // This clears the register. If the register contains a cell, the cell is 188 // removed, so this is different from r <- nil 189 func Clear(r Reg) Opcode { 190 return mkType4b(Off, OpClear, r, 0) 191 } 192 193 // Receive encodes recv r 194 // 195 // recv r is the pendant of push. 196 func Receive(r Reg) Opcode { 197 return mkType0(Off, r) 198 } 199 200 // ReceiveEtc encodes recv ...r 201 // 202 // accumulates pushes into r (as an Etc) 203 func ReceiveEtc(r Reg) Opcode { 204 return mkType0(On, r) 205 } 206 207 // LoadEtcLookup encodes r1 <- etclookup(r2, i) 208 // 209 // loads the (i + 1)-th element of r2 (as an etc vector) into r1. 210 func LoadEtcLookup(r1, r2 Reg, i int) Opcode { 211 return mkType6(Off, r1, r2, Index8FromInt(i)) 212 } 213 214 // FillTable encodes fill r1, i, r2 215 // 216 // This fills the table r1 with all values from r2 (as an etc vector) starting 217 // from index i. 218 func FillTable(r1, r2 Reg, i int) Opcode { 219 return mkType6(On, r1, r2, Index8FromInt(i)) 220 } 221 222 // PrepForLoop makes sure rStart, rStep, rStop are all numbers and converts 223 // rStart and rStep to the same numeric type. If the for loop should already 224 // stop then rStart is set to nil 225 func PrepForLoop(rStart, rStop, rStep Reg) Opcode { 226 return mkType7(Off, rStart, rStop, rStep) 227 } 228 229 // AdvForLoop increments rStart by rStep, making sure that it doesn't wrap 230 // around if it is an integer. If it wraps around then the loop should stop. If 231 // the loop should stop, rStart is set to nil 232 func AdvForLoop(rStart, rStop, rStep Reg) Opcode { 233 return mkType7(On, rStart, rStop, rStep) 234 }