Permalink
Please sign in to comment.
Browse files
Demo of Python/OPy bytecode decoding in C++.
opy$ ./test.sh compile-fib This compiles bytecode with OPy and dumps it to a file. Then it builds ovm/ovm_main.cc, which decodes the bytecode and prints the instruction names. The instruction names are taken from a header file generated from the new file lib/opcode_gen.py. Also: - Document OHeap a little bit. (The OSH demo has a compile error now.) - Change to Python 3 print() in some files.
- Loading branch information...
Showing
with
159 additions
and 3 deletions.
- +29 −0 asdl/README.md
- +2 −1 opy/gold/class_vs_closure.py
- +1 −1 opy/gold/generator_exception.py
- +48 −0 opy/lib/opcode_gen.py
- +14 −1 opy/opy_main.py
- +19 −0 opy/test.sh
- +46 −0 ovm/ovm_main.cc
| @@ -0,0 +1,48 @@ | ||
| #!/usr/bin/python | ||
| from __future__ import print_function | ||
| """ | ||
| opcode_gen.py | ||
| """ | ||
| import sys | ||
| from lib import opcode | ||
| def log(msg, *args): | ||
| if args: | ||
| msg = msg % args | ||
| print(msg, file=sys.stderr) | ||
| def main(argv): | ||
| opcode_nums = set(opcode.opmap.itervalues()) | ||
| # Print opcodes in numerical order. They're not contiguous integers. | ||
| for num in sorted(opcode_nums): | ||
| # SLICE+1 -> SLICE_1 | ||
| name = opcode.opname[num].replace('+', '_') | ||
| print('#define %s %d' % (name, num)) | ||
| print('') | ||
| print('#define HAVE_ARGUMENT %d' % opcode.HAVE_ARGUMENT) | ||
| #log('%s', opcode.opname) | ||
| print('') | ||
| print('const char* const kOpcodeNames[] = {') | ||
| n = max(opcode_nums) | ||
| for i in xrange(n+1): | ||
| if i in opcode_nums: | ||
| print('"%s",' % opcode.opname[i]) | ||
| else: | ||
| print('"",') # empty value | ||
| print('};') | ||
| if __name__ == '__main__': | ||
| try: | ||
| main(sys.argv) | ||
| except RuntimeError as e: | ||
| print('FATAL: %s' % e, file=sys.stderr) | ||
| sys.exit(1) |
| @@ -0,0 +1,46 @@ | ||
| #include <string> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include "opcode.h" | ||
| int main(int argc, char **argv) { | ||
| if (argc == 0) { | ||
| printf("Expected filename\n"); | ||
| return 1; | ||
| } | ||
| FILE *f = fopen(argv[1], "rb"); | ||
| if (!f) { | ||
| printf("Error opening %s", argv[1]); | ||
| return 1; | ||
| } | ||
| fseek(f, 0, SEEK_END); | ||
| size_t num_bytes = ftell(f); | ||
| fseek(f, 0, SEEK_SET); //same as rewind(f); | ||
| uint8_t* bytecode = static_cast<uint8_t*>(malloc(num_bytes)); | ||
| fread(bytecode, num_bytes, 1, f); | ||
| fclose(f); | ||
| printf("Read %zu bytes\n", num_bytes); | ||
| int i = 0; | ||
| int extended_arg = 0; | ||
| int n = 0; | ||
| while (i < num_bytes) { | ||
| uint8_t op = bytecode[i]; | ||
| i++; | ||
| printf("%s\n", kOpcodeNames[op]); | ||
| if (op > HAVE_ARGUMENT) { | ||
| int oparg = bytecode[i] + bytecode[i+1]*256 + extended_arg; | ||
| printf(" arg %d\n", oparg); | ||
| i += 2; | ||
| } | ||
| n++; | ||
| } | ||
| printf("Read %d instructions\n", n); | ||
| } |
0 comments on commit
1afd2dd