1// Copyright 2017 Istio Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package il 16 17// Opcode is the type for the opcodes in the il. 18type Opcode uint32 19 20// OpcodeArg represents the type of the arguments that opcodes have. 21type OpcodeArg int 22 23// opcodeInfo holds metadata about an opcode. 24type opcodeInfo struct { 25 // The human-readable name of the opcode. 26 name string 27 28 // The string keyword matching this opcode. 29 keyword string 30 31 // The set of arguments that is expected by this opcode. 32 args []OpcodeArg 33} 34 35const ( 36 // Halt stops the VM with an error. 37 Halt Opcode = 0 38 39 // Nop does nothing. 40 Nop Opcode = 1 41 42 // Err raises an error. 43 Err Opcode = 2 44 45 // Errz pops a boolean value from stack and check its value. if the value is false, then it 46 // raises an error. 47 Errz Opcode = 3 48 49 // Errnz pops a boolean value from stack and check its value. if the value is true, then it 50 // raises an error. 51 Errnz Opcode = 4 52 53 // PopS pops a string from the stack. 54 PopS Opcode = 10 55 56 // PopB pops a bool from the stack. 57 PopB Opcode = 11 58 59 // PopI pops an integer from the stack. 60 PopI Opcode = 12 61 62 // PopD pops a double from the stack. 63 PopD Opcode = 13 64 65 // DupS pops a string value from the stack and pushes it back into the stack twice. 66 DupS Opcode = 14 67 68 // DupB pops a boolean value from the stack and pushes it back into the stack twice. 69 DupB Opcode = 15 70 71 // DupI pops an integer value from the stack and pushes it back into the stack twice. 72 DupI Opcode = 16 73 74 // DupD pops a double value from the stack and pushes it back into the stack twice. 75 DupD Opcode = 17 76 77 // RLoadS pops a string from the stack and stores in the target register. 78 RLoadS Opcode = 20 79 80 // RLoadB pops a bool from the stack and stores in the target register. 81 RLoadB Opcode = 21 82 83 // RLoadI pops an integer from the stack and stores in the target register. 84 RLoadI Opcode = 22 85 86 // RLoadD pops a double from the stack and stores in the target register. 87 RLoadD Opcode = 23 88 89 // ALoadS loads its string argument into the target register. 90 ALoadS Opcode = 30 91 92 // ALoadB loads its boolean argument into the target register. 93 ALoadB Opcode = 31 94 95 // ALoadI loads its integer argument into the target register. 96 ALoadI Opcode = 32 97 98 // ALoadD loads its double argument into the target register. 99 ALoadD Opcode = 33 100 101 // APushS pushes its string argument to the stack. 102 APushS Opcode = 40 103 104 // APushB pushes its boolean argument to the stack. 105 APushB Opcode = 41 106 107 // APushI pushes its integer argument to the stack. 108 APushI Opcode = 42 109 110 // APushD pushes its double argument to the stack. 111 APushD Opcode = 43 112 113 // RPushS reads a string value from the target register and pushes it into stack. 114 RPushS Opcode = 50 115 116 // RPushB reads a boolean value from the target register and pushes it into stack. 117 RPushB Opcode = 51 118 119 // RPushI reads an integer value from the target register and pushes it into stack. 120 RPushI Opcode = 52 121 122 // RPushD reads a double value from the target register and pushes it into stack. 123 RPushD Opcode = 53 124 125 // EqS pops two string values from the stack and compare for equality. If the strings are 126 // equal then it pushes 1 into the stack, otherwise it pushes 0. 127 EqS Opcode = 60 128 129 // EqB pops two bool values from the stack and compare for equality. If equal, then it 130 // pushes 1 into the stack, otherwise it pushes 0. 131 EqB Opcode = 61 132 133 // EqI pops two integer values from the stack and compare for equality. If equal, then it 134 // pushes 1 into the stack, otherwise it pushes 0. 135 EqI Opcode = 62 136 137 // EqD pops two double values from the stack and compare for equality. If equal, then it 138 // pushes 1 into the stack, otherwise it pushes 0. 139 EqD Opcode = 63 140 141 // AEqS pops a string value from the stack and compare it against its argument for equality. 142 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 143 AEqS Opcode = 70 144 145 // AEqB pops a bool value from the stack and compare it against its argument for equality. 146 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 147 AEqB Opcode = 71 148 149 // AEqI pops an integer value from the stack and compare it against its argument for equality 150 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 151 AEqI Opcode = 72 152 153 // AEqD pops a double value from the stack and compare it against its argument for equality 154 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 155 AEqD Opcode = 73 156 157 // Xor pops two boolean values from the stack, performs logical exclusive-or, then pushes the 158 // result back into stack. 159 Xor Opcode = 80 160 161 // And pops two boolean values from the stack, performs logical and, then pushes the 162 // result back into stack. 163 And Opcode = 81 164 165 // Or pops two boolean values from the stack, performs logical or, then pushes the 166 // result back into stack. 167 Or Opcode = 82 168 169 // AXor pops a boolean value from the stack and performs logical exclusive-or with its 170 // argument, then pushes the result back into stack. 171 AXor Opcode = 83 172 173 // AAnd pops a boolean value from the stack and performs logical and with its 174 // argument, then pushes the result back into stack. 175 AAnd Opcode = 84 176 177 // AOr pops a boolean value from the stack and performs logical or with its 178 // argument, then pushes the result back into stack. 179 AOr Opcode = 85 180 181 // Not pops a boolean value from the stack and performs logical not, 182 // then pushes the result back into stack. 183 Not Opcode = 86 184 185 // ResolveS lookups up a string attribute value in the bag, with the given name. 186 // If successful, pushes the resolved string into stack, otherwise raises error. 187 ResolveS Opcode = 90 188 189 // ResolveB lookups up a bool attribute value in the bag, with the given name. 190 // If successful, pushes the resolved bool into stack, otherwise raises error. 191 ResolveB Opcode = 91 192 193 // ResolveI lookups up an integer attribute value in the bag, with the given name. 194 // If successful, pushes the resolved integer into stack, otherwise raises error. 195 ResolveI Opcode = 92 196 197 // ResolveD lookups up a double attribute value in the bag, with the given name. 198 // If successful, pushes the resolved double into stack, otherwise raises error. 199 ResolveD Opcode = 93 200 201 // ResolveF lookups up a interface{} attribute value in the bag, with the given name. 202 // If successful, pushes the resolved interface{} into stack, otherwise raises error. 203 ResolveF Opcode = 94 204 205 // TResolveS lookups up a string attribute value in the bag, with the given name. 206 // If successful, pushes the resolved string value, then 1 into the stack, 207 // otherwise pushes 0. 208 TResolveS Opcode = 100 209 210 // TResolveB lookups up a bool attribute value in the bag, with the given name. 211 // If successful, pushes the resolved bool value, then 1 into the stack, 212 // otherwise pushes 0. 213 TResolveB Opcode = 101 214 215 // TResolveI lookups up an integer attribute value in the bag, with the given name. 216 // If successful, pushes the resolved integer value, then 1 into the stack, 217 // otherwise pushes 0. 218 TResolveI Opcode = 102 219 220 // TResolveD lookups up a double attribute value in the bag, with the given name. 221 // If successful, pushes the resolved double value, then 1 into the stack, 222 // otherwise pushes 0. 223 TResolveD Opcode = 103 224 225 // TResolveF lookups up a interface{} attribute value in the bag, with the given name. 226 // If successful, pushes the resolved interface{} value, then 1 into the stack, 227 // otherwise pushes 0. 228 TResolveF Opcode = 104 229 230 // AddI pops two integer values from the stack, adds their value and pushes the result 231 // back into stack. The operation follows Go's integer addition semantics. 232 AddI Opcode = 110 233 234 // AddD pops two double values from the stack, adds their value and pushes the result 235 // back into stack. The operation follows Go's float addition semantics. 236 AddD Opcode = 111 237 238 // SubI pops two integer values from the stack, and subtracts the second popped value 239 // from the first one, then pushes the result back into stack. 240 // The operation follows Go's integer subtraction semantics. 241 SubI Opcode = 112 242 243 // SubD pops two double values from the stack, and subtracts the second popped value 244 // from the first one, then pushes the result back into stack. 245 // The operation follows Go's float subtraction semantics. 246 SubD Opcode = 113 247 248 // AAddI pops an integer value from the stack, adds the popped value and its argument, 249 // and pushes the result back into stack. The operation follows Go's integer addition 250 // semantics. 251 AAddI Opcode = 114 252 253 // AAddD pops a double value from the stack, adds the popped value and its argument, 254 // and pushes the result back into stack. The operation follows Go's double addition 255 // semantics. 256 AAddD Opcode = 115 257 258 // ASubI pops an integer value from the stack, subtracts its argument from the popped value, 259 // then pushes the result back into stack. The operation follows Go's integer subtraction 260 // semantics. 261 ASubI Opcode = 116 262 263 // ASubD pops a double value from the stack, subtracts its argument from the popped value, 264 // then pushes the result back into stack. The operation follows Go's double subtraction 265 // semantics. 266 ASubD Opcode = 117 267 268 // Jmp jumps to the given instruction address. 269 Jmp Opcode = 200 270 271 // Jz pops a bool value from the stack. If the value is zero, then jumps to the given 272 // instruction address. 273 Jz Opcode = 201 274 275 // Jnz pops a bool value from the stack. If the value is not 0, then jumps to the given 276 // instruction address. 277 Jnz Opcode = 202 278 279 // Call invokes the target function. 280 Call Opcode = 203 281 282 // Ret returns from the current function. 283 Ret Opcode = 204 284 285 // Lookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 286 // using the string as the name. If a value is found, then the value is pushed into the 287 // stack. Otherwise raises an error. 288 Lookup Opcode = 210 289 290 // TLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 291 // using the string as the name. If a value is found, then the value is pushed into the 292 // stack, then 1. Otherwise 0 is pushed to into the stack. 293 TLookup Opcode = 211 294 295 // ALookup pops a stringmap from the stack and perform a lookup on the stringmap using the string 296 // parameter as the name. If a value is found, then the value is pushed into the stack 297 // Otherwise raises an error. 298 ALookup Opcode = 212 299 300 // NLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 301 // using the string as the name. If a value is found, then the value is pushed into the 302 // stack. Otherwise empty string is pushed onto the stack. 303 NLookup Opcode = 213 304 305 // ANLookup pops a stringmap from the stack and perform a lookup on the stringmap using the string 306 // parameter as the name. If a value is found, then the value is pushed into the stack 307 // Otherwise empty string is pushed onto the stack. 308 ANLookup Opcode = 214 309 310 // AddS pops two string values from the stack, adds their value and pushes the result 311 // back into stack. The operation follows Go's string concatenation semantics. 312 AddS Opcode = 215 313 314 // SizeS pops a string value from the stack, and pushes its length back into stack. 315 SizeS Opcode = 216 316 317 // LtS pops two string values from the stack and compare for order. 318 // If less then it pushes 1 into the stack, otherwise it pushes 0. 319 LtS Opcode = 217 320 321 // LtI pops two integer values from the stack and compare for order. 322 // If less then it pushes 1 into the stack, otherwise it pushes 0. 323 LtI Opcode = 218 324 325 // LtD pops two float values from the stack and compare for order. 326 // If less then it pushes 1 into the stack, otherwise it pushes 0. 327 LtD Opcode = 219 328 329 // ALtS pops a string value from the stack and compare it against its argument for order. 330 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 331 ALtS Opcode = 220 332 333 // ALtI pops an integer value from the stack and compare it against its argument for order. 334 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 335 ALtI Opcode = 221 336 337 // ALtD pops a float value from the stack and compare it against its argument for order. 338 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 339 ALtD Opcode = 222 340 341 // LeS pops two string values from the stack and compare for order. 342 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 343 LeS Opcode = 223 344 345 // LeI pops two integer values from the stack and compare for order. 346 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 347 LeI Opcode = 224 348 349 // LeD pops two float values from the stack and compare for order. 350 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 351 LeD Opcode = 225 352 353 // ALeS pops a string value from the stack and compare it against its argument for order. 354 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 355 ALeS Opcode = 226 356 357 // ALeI pops an integer value from the stack and compare it against its argument for order. 358 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 359 ALeI Opcode = 227 360 361 // ALeD pops a float value from the stack and compare it against its argument for order. 362 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 363 ALeD Opcode = 228 364 365 // GtS pops two string values from the stack and compare for order. 366 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 367 GtS Opcode = 229 368 369 // GtI pops two integer values from the stack and compare for order. 370 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 371 GtI Opcode = 230 372 373 // GtD pops two float values from the stack and compare for order. 374 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 375 GtD Opcode = 231 376 377 // AGtS pops a string value from the stack and compare it against its argument for order. 378 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 379 AGtS Opcode = 232 380 381 // AGtI pops an integer value from the stack and compare it against its argument for order. 382 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 383 AGtI Opcode = 233 384 385 // AGtD pops a float value from the stack and compare it against its argument for order. 386 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 387 AGtD Opcode = 234 388 389 // GeS pops two string values from the stack and compare for order. 390 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 391 GeS Opcode = 235 392 393 // GeI pops two integer values from the stack and compare for order. 394 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 395 GeI Opcode = 236 396 397 // GeD pops two float values from the stack and compare for order. 398 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 399 GeD Opcode = 237 400 401 // AGeS pops a string value from the stack and compare it against its argument for order. 402 // If the value on the stack is greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 403 AGeS Opcode = 238 404 405 // AGeI pops an integer value from the stack and compare it against its argument for equality. 406 // If greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 407 AGeI Opcode = 239 408 409 // AGeD pops a float value from the stack and compare it against its argument for equality. 410 // If greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 411 AGeD Opcode = 240 412) 413 414const ( 415 // OpcodeArgRegister represents an argument that references a register. 416 OpcodeArgRegister OpcodeArg = 0 417 418 // OpcodeArgString represents an argument that is a string. 419 OpcodeArgString OpcodeArg = 1 420 421 // OpcodeArgInt represents an argument that is an integer. 422 OpcodeArgInt OpcodeArg = 2 423 424 // OpcodeArgDouble represents an argument that is a double. 425 OpcodeArgDouble OpcodeArg = 3 426 427 // OpcodeArgBool represents an argument that is a boolean. 428 OpcodeArgBool OpcodeArg = 4 429 430 // OpcodeArgFunction represents an argument that is a function. 431 OpcodeArgFunction OpcodeArg = 5 432 433 // OpcodeArgAddress represents an argument that is an address. 434 OpcodeArgAddress OpcodeArg = 6 435) 436 437var argSizes = map[OpcodeArg]uint32{ 438 OpcodeArgRegister: 1, 439 OpcodeArgString: 1, 440 OpcodeArgBool: 1, 441 OpcodeArgFunction: 1, 442 OpcodeArgAddress: 1, 443 OpcodeArgDouble: 2, 444 OpcodeArgInt: 2, 445} 446 447var opCodeInfos = map[Opcode]opcodeInfo{ 448 449 // Halt stops the VM with an error. 450 Halt: {name: "Halt", keyword: "halt"}, 451 452 // Nop does nothing. 453 Nop: {name: "Nop", keyword: "nop"}, 454 455 // Err raises an error. 456 Err: {name: "Err", keyword: "err", args: []OpcodeArg{ 457 // Text of the error. 458 OpcodeArgString, 459 }}, 460 461 // Errz pops a boolean value from stack and check its value. if the value is false, then it 462 // raises an error. 463 Errz: {name: "Errz", keyword: "errz", args: []OpcodeArg{ 464 // Text of the error message. 465 OpcodeArgString, 466 }}, 467 468 // Errnz pops a boolean value from stack and check its value. if the value is true, then it 469 // raises an error. 470 Errnz: {name: "Errnz", keyword: "errnz", args: []OpcodeArg{ 471 // Text of the error message. 472 OpcodeArgString, 473 }}, 474 475 // PopS pops a string from the stack. 476 PopS: {name: "PopS", keyword: "pop_s"}, 477 478 // PopB pops a bool from the stack. 479 PopB: {name: "PopB", keyword: "pop_b"}, 480 481 // PopI pops an integer from the stack. 482 PopI: {name: "PopI", keyword: "pop_i"}, 483 484 // PopD pops a double from the stack. 485 PopD: {name: "PopD", keyword: "pop_d"}, 486 487 // DupS pops a string value from the stack and pushes it back into the stack twice. 488 DupS: {name: "DupS", keyword: "dup_s"}, 489 490 // DupB pops a boolean value from the stack and pushes it back into the stack twice. 491 DupB: {name: "DupB", keyword: "dup_b"}, 492 493 // DupI pops an integer value from the stack and pushes it back into the stack twice. 494 DupI: {name: "DupI", keyword: "dup_i"}, 495 496 // DupD pops a double value from the stack and pushes it back into the stack twice. 497 DupD: {name: "DupD", keyword: "dup_d"}, 498 499 // RLoadS pops a string from the stack and stores in the target register. 500 RLoadS: {name: "RLoadS", keyword: "rload_s", args: []OpcodeArg{ 501 // The target register. 502 OpcodeArgRegister, 503 }}, 504 505 // RLoadB pops a bool from the stack and stores in the target register. 506 RLoadB: {name: "RLoadB", keyword: "rload_b", args: []OpcodeArg{ 507 // The target register. 508 OpcodeArgRegister, 509 }}, 510 511 // RLoadI pops an integer from the stack and stores in the target register. 512 RLoadI: {name: "RLoadI", keyword: "rload_i", args: []OpcodeArg{ 513 // The target register. 514 OpcodeArgRegister, 515 }}, 516 517 // RLoadD pops a double from the stack and stores in the target register. 518 RLoadD: {name: "RLoadD", keyword: "rload_d", args: []OpcodeArg{ 519 // The target register. 520 OpcodeArgRegister, 521 }}, 522 523 // ALoadS loads its string argument into the target register. 524 ALoadS: {name: "ALoadS", keyword: "aload_s", args: []OpcodeArg{ 525 // The target register. 526 OpcodeArgRegister, 527 // The string to load. 528 OpcodeArgString, 529 }}, 530 531 // ALoadB loads its boolean argument into the target register. 532 ALoadB: {name: "ALoadB", keyword: "aload_b", args: []OpcodeArg{ 533 // The target register. 534 OpcodeArgRegister, 535 // The bool to load. 536 OpcodeArgBool, 537 }}, 538 539 // ALoadI loads its integer argument into the target register. 540 ALoadI: {name: "ALoadI", keyword: "aload_i", args: []OpcodeArg{ 541 // The target register. 542 OpcodeArgRegister, 543 // The integer to load. 544 OpcodeArgInt, 545 }}, 546 547 // ALoadD loads its double argument into the target register. 548 ALoadD: {name: "ALoadD", keyword: "aload_d", args: []OpcodeArg{ 549 // The target register. 550 OpcodeArgRegister, 551 // The double to load. 552 OpcodeArgDouble, 553 }}, 554 555 // APushS pushes its string argument to the stack. 556 APushS: {name: "APushS", keyword: "apush_s", args: []OpcodeArg{ 557 // The string to push. 558 OpcodeArgString, 559 }}, 560 561 // APushB pushes its boolean argument to the stack. 562 APushB: {name: "APushB", keyword: "apush_b", args: []OpcodeArg{ 563 // The boolean to push. 564 OpcodeArgBool, 565 }}, 566 567 // APushI pushes its integer argument to the stack. 568 APushI: {name: "APushI", keyword: "apush_i", args: []OpcodeArg{ 569 // The integer to push. 570 OpcodeArgInt, 571 }}, 572 573 // APushD pushes its double argument to the stack. 574 APushD: {name: "APushD", keyword: "apush_d", args: []OpcodeArg{ 575 // The double to push. 576 OpcodeArgDouble, 577 }}, 578 579 // RPushS reads a string value from the target register and pushes it into stack. 580 RPushS: {name: "RPushS", keyword: "rpush_s", args: []OpcodeArg{ 581 // The target register. 582 OpcodeArgRegister, 583 }}, 584 585 // RPushB reads a boolean value from the target register and pushes it into stack. 586 RPushB: {name: "RPushB", keyword: "rpush_b", args: []OpcodeArg{ 587 // The target register. 588 OpcodeArgRegister, 589 }}, 590 591 // RPushI reads an integer value from the target register and pushes it into stack. 592 RPushI: {name: "RPushI", keyword: "rpush_i", args: []OpcodeArg{ 593 // The target register. 594 OpcodeArgRegister, 595 }}, 596 597 // RPushD reads a double value from the target register and pushes it into stack. 598 RPushD: {name: "RPushD", keyword: "rpush_d", args: []OpcodeArg{ 599 // The target register. 600 OpcodeArgRegister, 601 }}, 602 603 // EqS pops two string values from the stack and compare for equality. If the strings are 604 // equal then it pushes 1 into the stack, otherwise it pushes 0. 605 EqS: {name: "EqS", keyword: "eq_s"}, 606 607 // EqB pops two bool values from the stack and compare for equality. If the bools are 608 // equal then it pushes 1 into the stack, otherwise it pushes 0. 609 EqB: {name: "EqB", keyword: "eq_b"}, 610 611 // EqI pops two integer values from the stack and compare for equality. If the integers are 612 // equal then it pushes 1 into the stack, otherwise it pushes 0. 613 EqI: {name: "EqI", keyword: "eq_i"}, 614 615 // EqD pops two double values from the stack and compare for equality. If the doubles are 616 // equal then it pushes 1 into the stack, otherwise it pushes 0. 617 EqD: {name: "EqD", keyword: "eq_d"}, 618 619 // AEqS pops a string value from the stack and compare it against its argument for equality. 620 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 621 AEqS: {name: "AEqS", keyword: "aeq_s", args: []OpcodeArg{ 622 // The string value for comparison. 623 OpcodeArgString, 624 }}, 625 626 // AEqB pops a bool value from the stack and compare it against its argument for equality. 627 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 628 AEqB: {name: "AEqB", keyword: "aeq_b", args: []OpcodeArg{ 629 // The bool value for comparison. 630 OpcodeArgBool, 631 }}, 632 633 // AEqI pops an integer value from the stack and compare it against its argument for equality. 634 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 635 AEqI: {name: "AEqI", keyword: "aeq_i", args: []OpcodeArg{ 636 // The integer value for comparison. 637 OpcodeArgInt, 638 }}, 639 640 // AEqD pops a double value from the stack and compare it against its argument for equality. 641 // If equal, then it pushes 1 into the stack, otherwise it pushes 0. 642 AEqD: {name: "AEqD", keyword: "aeq_d", args: []OpcodeArg{ 643 // The double value for comparison. 644 OpcodeArgDouble, 645 }}, 646 647 // Xor pops two boolean values from the stack, performs logical exclusive-or, then pushes the 648 // result back into stack. 649 Xor: {name: "Xor", keyword: "xor"}, 650 651 // And pops two boolean values from the stack, performs logical and, then pushes the 652 // result back into stack. 653 And: {name: "And", keyword: "and"}, 654 655 // Or pops two boolean values from the stack, performs logical or, then pushes the 656 // result back into stack. 657 Or: {name: "Or", keyword: "or"}, 658 659 // AXor pops a boolean value from the stack and performs logical exclusive-or with its 660 // argument, then pushes the result back into stack. 661 AXor: {name: "AXor", keyword: "axor", args: []OpcodeArg{ 662 // The boolean value to xor. 663 OpcodeArgBool, 664 }}, 665 666 // AAnd pops a boolean value from the stack and performs logical and with its 667 // argument, then pushes the result back into stack. 668 AAnd: {name: "AAnd", keyword: "aand", args: []OpcodeArg{ 669 // The boolean value to and. 670 OpcodeArgBool, 671 }}, 672 673 // AOr pops a boolean value from the stack and performs logical or with its 674 // argument, then pushes the result back into stack. 675 AOr: {name: "AOr", keyword: "aor", args: []OpcodeArg{ 676 // The boolean value to or. 677 OpcodeArgBool, 678 }}, 679 680 // Not pops a boolean value from the stack and performs logical not, 681 // then pushes the result back into stack. 682 Not: {name: "Not", keyword: "not"}, 683 684 // ResolveS lookups up a string attribute value in the bag, with the given name. 685 // If successful, pushes the resolved string into stack, otherwise raises error. 686 ResolveS: {name: "ResolveS", keyword: "resolve_s", args: []OpcodeArg{ 687 // The name of the attribute. 688 OpcodeArgString, 689 }}, 690 691 // ResolveB lookups up a bool attribute value in the bag, with the given name. 692 // If successful, pushes the resolved bool into stack, otherwise raises error. 693 ResolveB: {name: "ResolveB", keyword: "resolve_b", args: []OpcodeArg{ 694 // The name of the attribute. 695 OpcodeArgString, 696 }}, 697 698 // ResolveI lookups up an integer attribute value in the bag, with the given name. 699 // If successful, pushes the resolved integer into stack, otherwise raises error. 700 ResolveI: {name: "ResolveI", keyword: "resolve_i", args: []OpcodeArg{ 701 // The name of the attribute. 702 OpcodeArgString, 703 }}, 704 705 // ResolveD lookups up a double attribute value in the bag, with the given name. 706 // If successful, pushes the resolved double into stack, otherwise raises error. 707 ResolveD: {name: "ResolveD", keyword: "resolve_d", args: []OpcodeArg{ 708 // The name of the attribute. 709 OpcodeArgString, 710 }}, 711 712 // ResolveF lookups up an interface attribute value in the bag, with the given name. 713 // If successful, pushes the resolved interface{} into stack, otherwise raises error. 714 ResolveF: {name: "ResolveF", keyword: "resolve_f", args: []OpcodeArg{ 715 // The name of the attribute. 716 OpcodeArgString, 717 }}, 718 719 // TResolveS lookups up a string attribute value in the bag, with the given name. 720 // If successful, pushes the resolved string value, then 1 into the stack, 721 // otherwise pushes 0. 722 TResolveS: {name: "TResolveS", keyword: "tresolve_s", args: []OpcodeArg{ 723 // The name of the attribute. 724 OpcodeArgString, 725 }}, 726 727 // TResolveB lookups up a ool attribute value in the bag, with the given name. 728 // If successful, pushes the resolved bool value, then 1 into the stack, 729 // otherwise pushes 0. 730 TResolveB: {name: "TResolveB", keyword: "tresolve_b", args: []OpcodeArg{ 731 // The name of the attribute. 732 OpcodeArgString, 733 }}, 734 735 // TResolveI lookups up an integer attribute value in the bag, with the given name. 736 // If successful, pushes the resolved integer value, then 1 into the stack, 737 // otherwise pushes 0. 738 TResolveI: {name: "TResolveI", keyword: "tresolve_i", args: []OpcodeArg{ 739 // The name of the attribute. 740 OpcodeArgString, 741 }}, 742 743 // TResolveD lookups up a double attribute value in the bag, with the given name. 744 // If successful, pushes the resolved double value, then 1 into the stack, 745 // otherwise pushes 0. 746 TResolveD: {name: "TResolveD", keyword: "tresolve_d", args: []OpcodeArg{ 747 // The name of the attribute. 748 OpcodeArgString, 749 }}, 750 751 // TResolveF lookups up a interface{} attribute value in the bag, with the given name. 752 // If successful, pushes the resolved interface{] value, then 1 into the stack, 753 // otherwise pushes 0. 754 TResolveF: {name: "TResolveF", keyword: "tresolve_f", args: []OpcodeArg{ 755 // The name of the attribute. 756 OpcodeArgString, 757 }}, 758 759 // AddI pops two integer values from the stack, adds their value and pushes the result 760 // back into stack. The operation follows Go's integer addition semantics. 761 AddI: {name: "AddI", keyword: "add_i"}, 762 763 // AddD pops two double values from the stack, adds their value and pushes the result 764 // back into stack. The operation follows Go's float addition semantics. 765 AddD: {name: "AddD", keyword: "add_d"}, 766 767 // AddS pops two string values from the stack, adds their value and pushes the result 768 // back into stack. The operation follows Go's string concatenation semantics. 769 AddS: {name: "AddS", keyword: "add_s"}, 770 771 // SubI pops two integer values from the stack, and subtracts the second popped value 772 // from the first one, then pushes the result back into stack. 773 // The operation follows Go's integer subtraction semantics. 774 SubI: {name: "SubI", keyword: "sub_i"}, 775 776 // SubD pops two double values from the stack, and subtracts the second popped value 777 // from the first one, then pushes the result back into stack. 778 // The operation follows Go's float subtraction semantics. 779 SubD: {name: "SubD", keyword: "sub_d"}, 780 781 // AAddI pops an integer value from the stack, adds the popped value and its argument, 782 // and pushes the result back into stack. The operation follows Go's integer addition 783 // semantics. 784 AAddI: {name: "AAddI", keyword: "aadd_i", args: []OpcodeArg{ 785 // Value to add 786 OpcodeArgInt, 787 }}, 788 789 // AAddD pops a double value from the stack, adds the popped value and its argument, 790 // and pushes the result back into stack. The operation follows Go's double addition 791 // semantics. 792 AAddD: {name: "AAddD", keyword: "aadd_d", args: []OpcodeArg{ 793 // Value to add 794 OpcodeArgDouble, 795 }}, 796 797 // ASubI pops an integer value from the stack, subtracts its argument from the popped value, 798 // then pushes the result back into stack. The operation follows Go's integer subtraction 799 // semantics. 800 ASubI: {name: "ASubI", keyword: "asub_i", args: []OpcodeArg{ 801 // Value to subtract 802 OpcodeArgInt, 803 }}, 804 805 // ASubD pops a double value from the stack, subtracts its argument from the popped value, 806 // then pushes the result back into stack. The operation follows Go's double subtraction 807 // semantics. 808 ASubD: {name: "ASubD", keyword: "asub_d", args: []OpcodeArg{ 809 // Value to subtract 810 OpcodeArgDouble, 811 }}, 812 813 // Jmp jumps to the given instruction address. 814 Jmp: {name: "Jmp", keyword: "jmp", args: []OpcodeArg{ 815 // The address to jump to. 816 OpcodeArgAddress, 817 }}, 818 819 // Jz pops a bool value from the stack. If the value is 0, then jumps to the given 820 // instruction address. 821 Jz: {name: "Jz", keyword: "jz", args: []OpcodeArg{ 822 // The address to jump to. 823 OpcodeArgAddress, 824 }}, 825 826 // Jnz pops a bool value from the stack. If the value is not 0, then jumps to the given 827 // instruction address. 828 Jnz: {name: "Jnz", keyword: "jnz", args: []OpcodeArg{ 829 // The address to jump to. 830 OpcodeArgAddress, 831 }}, 832 833 // Call invokes the target function. 834 Call: {name: "Call", keyword: "call", args: []OpcodeArg{ 835 // The name of the target function. 836 OpcodeArgFunction, 837 }}, 838 839 // Ret returns from the current function. 840 Ret: {name: "Ret", keyword: "ret"}, 841 842 // Lookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 843 // using the string as the name. If a value is found, then the value is pushed into the 844 // stack. Otherwise raises an error. 845 Lookup: {name: "Lookup", keyword: "lookup"}, 846 847 // NLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 848 // using the string as the name. If a value is found, then the value is pushed into the 849 // stack. Otherwise empty string is pushed ono the stack. 850 NLookup: {name: "NLookup", keyword: "nlookup"}, 851 852 // TLookup pops a string, then a stringmap from the stack and perform a lookup on the stringmap 853 // using the string as the name. If a value is found, then the value is pushed into the 854 // stack, then 1. Otherwise 0 is pushed to into the stack. 855 TLookup: {name: "TLookup", keyword: "tlookup"}, 856 857 // ALookup pops a stringmap from the stack and perform a lookup on the stringmap using the string 858 // parameter as the name. If a value is found, then the value is pushed into the stack 859 // Otherwise raises an error. 860 ALookup: {name: "ALookup", keyword: "alookup", args: []OpcodeArg{ 861 // The name of the attribute. 862 OpcodeArgString, 863 }}, 864 865 // ANLookup pops a stringmap from the stack and perform a lookup on the stringmap using the string 866 // parameter as the name. If a value is found, then the value is pushed into the stack 867 // Otherwise empty string is pushed onto the stack. 868 ANLookup: {name: "ANLookup", keyword: "anlookup", args: []OpcodeArg{ 869 // The name of the attribute. 870 OpcodeArgString, 871 }}, 872 873 // SizeS pops a string and pushes it length. 874 SizeS: {name: "SizeS", keyword: "size_s"}, 875 876 // LtS pops two string values from the stack and compare for order. 877 // If less then it pushes 1 into the stack, otherwise it pushes 0. 878 LtS: {name: "LtS", keyword: "lt_s"}, 879 880 // LtI pops two integer values from the stack and compare for order. 881 // If less then it pushes 1 into the stack, otherwise it pushes 0. 882 LtI: {name: "LtI", keyword: "lt_i"}, 883 884 // LtD pops two float values from the stack and compare for order. 885 // If less then it pushes 1 into the stack, otherwise it pushes 0. 886 LtD: {name: "LtD", keyword: "lt_d"}, 887 888 // ALtS pops a string value from the stack and compare it against its argument for order. 889 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 890 ALtS: {name: "ALtS", keyword: "alt_s", args: []OpcodeArg{ 891 // The string value for comparison. 892 OpcodeArgString, 893 }}, 894 895 // ALtI pops an integer value from the stack and compare it against its argument for order. 896 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 897 ALtI: {name: "ALtI", keyword: "alt_i", args: []OpcodeArg{ 898 // The integer value for comparison. 899 OpcodeArgInt, 900 }}, 901 902 // ALtD pops a float value from the stack and compare it against its argument for order. 903 // If the value on the stack is less, then it pushes 1 into the stack, otherwise it pushes 0. 904 ALtD: {name: "ALtD", keyword: "alt_d", args: []OpcodeArg{ 905 // The integer value for comparison. 906 OpcodeArgDouble, 907 }}, 908 909 // LeS pops two string values from the stack and compare for order. 910 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 911 LeS: {name: "LeS", keyword: "le_s"}, 912 913 // LeI pops two integer values from the stack and compare for order. 914 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 915 LeI: {name: "LeI", keyword: "le_i"}, 916 917 // LeD pops two float values from the stack and compare for order. 918 // If less or equals then it pushes 1 into the stack, otherwise it pushes 0. 919 LeD: {name: "LeD", keyword: "le_d"}, 920 921 // ALeS pops a string value from the stack and compare it against its argument for order. 922 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 923 ALeS: {name: "ALeS", keyword: "ale_s", args: []OpcodeArg{ 924 // The string value for comparison. 925 OpcodeArgString, 926 }}, 927 928 // ALeI pops an integer value from the stack and compare it against its argument for order. 929 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 930 ALeI: {name: "ALeI", keyword: "ale_i", args: []OpcodeArg{ 931 // The integer value for comparison. 932 OpcodeArgInt, 933 }}, 934 935 // ALeD pops a float value from the stack and compare it against its argument for order. 936 // If the value on the stack is less or equal, then it pushes 1 into the stack, otherwise it pushes 0. 937 ALeD: {name: "ALeD", keyword: "ale_d", args: []OpcodeArg{ 938 // The integer value for comparison. 939 OpcodeArgDouble, 940 }}, 941 942 // GtS pops two string values from the stack and compare for order. 943 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 944 GtS: {name: "GtS", keyword: "gt_s"}, 945 946 // GtI pops two integer values from the stack and compare for order. 947 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 948 GtI: {name: "GtI", keyword: "gt_i"}, 949 950 // GtD pops two float values from the stack and compare for order. 951 // If greater then it pushes 1 into the stack, otherwise it pushes 0. 952 GtD: {name: "GtD", keyword: "gt_d"}, 953 954 // AGtS pops a string value from the stack and compare it against its argument for order. 955 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 956 AGtS: {name: "AGtS", keyword: "agt_s", args: []OpcodeArg{ 957 // The string value for comparison. 958 OpcodeArgString, 959 }}, 960 961 // AGtI pops an integer value from the stack and compare it against its argument for order. 962 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 963 AGtI: {name: "AGtI", keyword: "agt_i", args: []OpcodeArg{ 964 // The integer value for comparison. 965 OpcodeArgInt, 966 }}, 967 968 // AGtD pops a float value from the stack and compare it against its argument for order. 969 // If the value on the stack is greater, then it pushes 1 into the stack, otherwise it pushes 0. 970 AGtD: {name: "AGtD", keyword: "agt_d", args: []OpcodeArg{ 971 // The integer value for comparison. 972 OpcodeArgDouble, 973 }}, 974 975 // GeS pops two string values from the stack and compare for order. 976 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 977 GeS: {name: "GeS", keyword: "ge_s"}, 978 979 // GeI pops two integer values from the stack and compare for order. 980 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 981 GeI: {name: "GeI", keyword: "ge_i"}, 982 983 // GeD pops two float values from the stack and compare for order. 984 // If greater or equal then it pushes 1 into the stack, otherwise it pushes 0. 985 GeD: {name: "GeD", keyword: "ge_d"}, 986 987 // AGeS pops a string value from the stack and compare it against its argument for order. 988 // If the value on the stack is greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 989 AGeS: {name: "AGeS", keyword: "age_s", args: []OpcodeArg{ 990 // The string value for comparison. 991 OpcodeArgString, 992 }}, 993 994 // AGeI pops an integer value from the stack and compare it against its argument for equality. 995 // If greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 996 AGeI: {name: "AGeI", keyword: "age_i", args: []OpcodeArg{ 997 // The integer value for comparison. 998 OpcodeArgInt, 999 }}, 1000 1001 // AGeD pops a float value from the stack and compare it against its argument for equality. 1002 // If greater or equal, then it pushes 1 into the stack, otherwise it pushes 0. 1003 AGeD: {name: "AGeD", keyword: "age_d", args: []OpcodeArg{ 1004 // The integer value for comparison. 1005 OpcodeArgDouble, 1006 }}, 1007} 1008 1009var opcodesByKeyword = func() map[string]Opcode { 1010 r := make(map[string]Opcode) 1011 for o, i := range opCodeInfos { 1012 r[i.keyword] = o 1013 } 1014 return r 1015}() 1016 1017// GetOpcode finds and returns the opcode that matches the keyword text that is supplied. 1018func GetOpcode(text string) (Opcode, bool) { 1019 o, f := opcodesByKeyword[text] 1020 return o, f 1021} 1022 1023func (o Opcode) String() string { 1024 return opCodeInfos[o].name 1025} 1026 1027// Size returns the total size the instruction and its arguments occupy, in uint32s. 1028func (o Opcode) Size() uint32 { 1029 var s uint32 = 1 1030 for _, a := range opCodeInfos[o].args { 1031 s += a.Size() 1032 } 1033 return s 1034} 1035 1036// Keyword returns the keyword corresponding to the opcode. 1037func (o Opcode) Keyword() string { 1038 return opCodeInfos[o].keyword 1039} 1040 1041// Args return the metadata about the arguments to the opcode. 1042func (o Opcode) Args() []OpcodeArg { 1043 return opCodeInfos[o].args 1044} 1045 1046// Size returns the number of uint32 byte codes that the argument occupies. 1047func (o OpcodeArg) Size() uint32 { 1048 return argSizes[o] 1049} 1050