def dump_bytecode_function(w_func): assert isinstance(w_func, W_BytecodeFunction) fields_w = [None] * 9 fields_w[0] = symbol('BYTECODE-FUNCTION') fields_w[1] = list_to_pair([symbol('NAME'), symbol(w_func.name)]) # code_w = [None] * len(w_func.code) for i in xrange(len(code_w)): code_w[i] = W_Integer(ord(w_func.code[i])) w_code = list_to_pair(code_w) fields_w[2] = list_to_pair([symbol('CODE'), w_code]) fields_w[3] = list_to_pair([symbol('NB-ARGS'), W_Integer(w_func.nb_args), w_boolean(w_func.has_vararg)]) fields_w[4] = list_to_pair([symbol('NB-LOCALS'), W_Integer(w_func.nb_locals)]) upval_descrs_w = [None] * (len(w_func.upval_descrs) >> 1) i = 0 while i < len(w_func.upval_descrs): c0, c1 = w_func.upval_descrs[i], w_func.upval_descrs[i + 1] upval_descrs_w[i >> 1] = list_to_pair([W_Integer(ord(c0)), W_Integer(ord(c1))]) i += 2 # w_upval_descrs = list_to_pair(upval_descrs_w[:]) fields_w[5] = list_to_pair([symbol('UPVAL-DESCRS'), w_upval_descrs]) w_consts = list_to_pair(w_func.consts_w[:]) fields_w[6] = list_to_pair([symbol('CONSTS'), w_consts]) w_names = list_to_pair(w_func.names_w[:]) fields_w[7] = list_to_pair([symbol('NAMES'), w_names]) functions_w = [dump_bytecode_function(w_function) for w_function in w_func.functions_w] w_functions = list_to_pair(functions_w[:]) fields_w[8] = list_to_pair([symbol('FUNCTIONS'), w_functions]) return list_to_pair(fields_w)
def test_fibo(): w_global = ModuleDict() populate_module(w_global) # w_two = W_Integer(2) w_lt = symbol('<') w_one = W_Integer(1) w_sub = symbol('-') w_fibo = symbol('fibo') w_add = symbol('+') consts_w = [w_two, w_one] names_w = [w_lt, w_sub, w_fibo, w_add] code = make_code(Op.LOAD, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 0, # '< Op.CALL, 2, # push (< n 2) Op.JIFNOT, 14, 0, # to recur_case Op.LOAD, 0, # n Op.RET, # return n # recur_case Op.LOAD, 0, # n Op.LOADCONST, 1, # 1 Op.LOADGLOBAL, 1, # '- Op.CALL, 2, # push (- n 1) Op.LOADGLOBAL, 2, # 'fibo Op.CALL, 1, # push (fibo (- n 1)) Op.LOAD, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 1, # '- Op.CALL, 2, # push (- n 2) Op.LOADGLOBAL, 2, # 'fibo Op.CALL, 1, # push (fibo (- n 2)) Op.LOADGLOBAL, 3, # '+ Op.TAILCALL, 2) w_func = W_BytecodeFunction(code, 1, 1, '', consts_w, names_w, [], w_global) maincode = make_code(Op.BUILDCLOSURE, 0, Op.STOREGLOBAL, 0, Op.LOADCONST, 0, Op.LOADGLOBAL, 0, Op.CALL, 1, Op.RET) w_ten = W_Integer(10) w_main = W_BytecodeFunction(maincode, 0, 0, '', [w_ten], [w_fibo], [w_func], w_global) w_retval = execute_function(w_main, []) assert w_retval.to_int() == 55
def test_call(): w_global = ModuleDict() populate_module(w_global) # code = make_code(Op.LOAD, 0, Op.LOAD, 1, Op.LOADGLOBAL, 0, Op.CALL, 2, Op.RET) w_lt = symbol('<') w_func = W_BytecodeFunction(code, 2, 2, '', [], [w_lt], [], w_global, 'lessthan') maincode = make_code(Op.LOADCONST, 0, Op.LOADCONST, 1, Op.BUILDCLOSURE, 0, Op.CALL, 2, Op.RET) w_one = W_Integer(1) w_two = W_Integer(2) w_main = W_BytecodeFunction(maincode, 0, 0, '', [w_one, w_two], [], [w_func], w_global, 'main') w_retval = execute_function(w_main, []) assert w_retval is w_true
def test_mutable_upval(): w_global = ModuleDict() populate_module(w_global) w_one = W_Integer(1) w_two = W_Integer(2) # inner_code = make_code( Op.LOADUPVAL, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 0, # '+ Op.CALL, 2, Op.STOREUPVAL, 0, # n Op.LOADCONST, 1, # void Op.RET) w_inner_func = W_BytecodeFunction(inner_code, 0, 1, '\0', [w_two, w_unspec], [symbol('+')], [], w_global) outer_code = make_code( Op.BUILDUPVAL, 0, Op.LOADCONST, 0, # 1 Op.STOREUPVAL, 0, Op.BUILDCLOSURE, 0, # inner Op.CALL, 0, # inner(), which changes the upval to 3 Op.POP, Op.LOADUPVAL, 0, Op.RET) w_outer_func = W_BytecodeFunction(outer_code, 0, 1, '', [w_one], [], [w_inner_func], None) main_code = make_code( Op.BUILDCLOSURE, 0, Op.CALL, 0, # outer() => 3 Op.RET) w_main = W_BytecodeFunction(main_code, 0, 0, '', [], [], [w_outer_func], None) # w_retval = execute_function(w_main, []) assert w_retval.to_int() == 3
def test_cond(): code = make_code(Op.LOADCONST, 0, Op.LOADCONST, 1, Op.LOADGLOBAL, 0, Op.CALL, 2, Op.RET) w_one = W_Integer(1) w_two = W_Integer(2) w_lt = symbol('<') w_global = ModuleDict() populate_module(w_global) w_func = W_BytecodeFunction(code, 0, 0, '', [w_one, w_two], [w_lt], [], w_global, 'main') w_retval = execute_function(w_func, []) assert w_retval is w_true
def dump_bytecode_function(w_func): assert isinstance(w_func, W_BytecodeFunction) fields_w = [None] * 9 fields_w[0] = symbol('BYTECODE-FUNCTION') fields_w[1] = list_to_pair([symbol('NAME'), symbol(w_func.name)]) # code_w = [None] * len(w_func.code) for i in xrange(len(code_w)): code_w[i] = W_Integer(ord(w_func.code[i])) w_code = list_to_pair(code_w) fields_w[2] = list_to_pair([symbol('CODE'), w_code]) fields_w[3] = list_to_pair([ symbol('NB-ARGS'), W_Integer(w_func.nb_args), w_boolean(w_func.has_vararg) ]) fields_w[4] = list_to_pair( [symbol('NB-LOCALS'), W_Integer(w_func.nb_locals)]) upval_descrs_w = [None] * (len(w_func.upval_descrs) >> 1) i = 0 while i < len(w_func.upval_descrs): c0, c1 = w_func.upval_descrs[i], w_func.upval_descrs[i + 1] upval_descrs_w[i >> 1] = list_to_pair( [W_Integer(ord(c0)), W_Integer(ord(c1))]) i += 2 # w_upval_descrs = list_to_pair(upval_descrs_w[:]) fields_w[5] = list_to_pair([symbol('UPVAL-DESCRS'), w_upval_descrs]) w_consts = list_to_pair(w_func.consts_w[:]) fields_w[6] = list_to_pair([symbol('CONSTS'), w_consts]) w_names = list_to_pair(w_func.names_w[:]) fields_w[7] = list_to_pair([symbol('NAMES'), w_names]) functions_w = [ dump_bytecode_function(w_function) for w_function in w_func.functions_w ] w_functions = list_to_pair(functions_w[:]) fields_w[8] = list_to_pair([symbol('FUNCTIONS'), w_functions]) return list_to_pair(fields_w)
def test_add(): code = make_code(Op.LOADCONST, 0, Op.LOADCONST, 1, Op.LOADGLOBAL, 0, Op.CALL, 2, Op.RET) w_one = W_Integer(1) w_two = W_Integer(2) w_add = symbol('+') w_global = ModuleDict() populate_module(w_global) w_func = W_BytecodeFunction(code, 0, 0, '', [w_one, w_two], [w_add], [], w_global, 'main') w_retval = execute_function(w_func, []) assert w_retval.to_int() == 3
def test_tailcall1(): w_global = ModuleDict() populate_module(w_global) # code = make_code(Op.LOAD, 0, Op.LOAD, 1, Op.LOADGLOBAL, 0, Op.TAILCALL, 2) w_lt = symbol('<') w_func = W_BytecodeFunction(code, 2, 2, '', [], [w_lt], [], w_global, 'tailcaller') maincode = make_code(Op.LOADCONST, 0, Op.LOADCONST, 1, Op.BUILDCLOSURE, 0, Op.CALL, 2, Op.RET) w_one = W_Integer(1) w_two = W_Integer(2) w_main = W_BytecodeFunction(maincode, 0, 0, '', [w_one, w_two], None, [w_func], w_global) w_retval = execute_function(w_main, []) assert w_retval is w_true
def call(self, args_w): assert len(args_w) == len(self.argtypes_w) argchain = ArgChain() buffers = [] for i in xrange(len(args_w)): w_arg = args_w[i] assert isinstance(w_arg, self.argtypes_w[i]) if isinstance(w_arg, W_Integer): argchain.arg(w_arg.ival) elif isinstance(w_arg, W_Symbol): sval = w_arg.sval assert sval is not None charp = rffi.str2charp(sval) buffers.append(charp) argchain.arg(charp) elif isinstance(w_arg, W_String): sval = w_arg.content() assert sval is not None charp = rffi.str2charp(sval) buffers.append(charp) argchain.arg(charp) elif isinstance(w_arg, W_Boolean): argchain.arg(w_arg.to_bool()) else: assert 0, 'unsupported argument type' res = self.funcptr.call(argchain, rffi.LONG) # annotate type to LONG for charp in buffers: rffi.free_charp(charp) # if self.w_restype is W_Integer: w_retval = W_Integer(rffi.cast(rffi.LONG, res)) elif self.w_restype is W_Boolean: w_retval = w_boolean(rffi.cast(rffi.LONG, res)) elif self.w_restype is W_Symbol: # XXX who delete the returned pointer? w_retval = symbol(rffi.charp2str(rffi.cast(rffi.CCHARP, res))) elif self.w_restype is W_String: w_retval = W_String(rffi.charp2str(rffi.cast(rffi.CCHARP, res))) elif self.w_restype is W_Unspecified: w_retval = w_unspec else: assert 0, 'unsupported result type' return w_retval
def test_mutable_upval(): w_global = ModuleDict() populate_module(w_global) w_one = W_Integer(1) w_two = W_Integer(2) # inner_code = make_code(Op.LOADUPVAL, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 0, # '+ Op.CALL, 2, Op.STOREUPVAL, 0, # n Op.LOADCONST, 1, # void Op.RET) w_inner_func = W_BytecodeFunction(inner_code, 0, 1, '\0', [w_two, w_unspec], [symbol('+')], [], w_global) outer_code = make_code(Op.BUILDUPVAL, 0, Op.LOADCONST, 0, # 1 Op.STOREUPVAL, 0, Op.BUILDCLOSURE, 0, # inner Op.CALL, 0, # inner(), which changes the upval to 3 Op.POP, Op.LOADUPVAL, 0, Op.RET) w_outer_func = W_BytecodeFunction(outer_code, 0, 1, '', [w_one], [], [w_inner_func], None) main_code = make_code(Op.BUILDCLOSURE, 0, Op.CALL, 0, # outer() => 3 Op.RET) w_main = W_BytecodeFunction(main_code, 0, 0, '', [], [], [w_outer_func], None) # w_retval = execute_function(w_main, []) assert w_retval.to_int() == 3
def test_fibo(): w_global = ModuleDict() populate_module(w_global) # w_two = W_Integer(2) w_lt = symbol('<') w_one = W_Integer(1) w_sub = symbol('-') w_fibo = symbol('fibo') w_add = symbol('+') consts_w = [w_two, w_one] names_w = [w_lt, w_sub, w_fibo, w_add] code = make_code( Op.LOAD, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 0, # '< Op.CALL, 2, # push (< n 2) Op.JIFNOT, 14, 0, # to recur_case Op.LOAD, 0, # n Op.RET, # return n # recur_case Op.LOAD, 0, # n Op.LOADCONST, 1, # 1 Op.LOADGLOBAL, 1, # '- Op.CALL, 2, # push (- n 1) Op.LOADGLOBAL, 2, # 'fibo Op.CALL, 1, # push (fibo (- n 1)) Op.LOAD, 0, # n Op.LOADCONST, 0, # 2 Op.LOADGLOBAL, 1, # '- Op.CALL, 2, # push (- n 2) Op.LOADGLOBAL, 2, # 'fibo Op.CALL, 1, # push (fibo (- n 2)) Op.LOADGLOBAL, 3, # '+ Op.TAILCALL, 2) w_func = W_BytecodeFunction(code, 1, 1, '', consts_w, names_w, [], w_global) maincode = make_code(Op.BUILDCLOSURE, 0, Op.STOREGLOBAL, 0, Op.LOADCONST, 0, Op.LOADGLOBAL, 0, Op.CALL, 1, Op.RET) w_ten = W_Integer(10) w_main = W_BytecodeFunction(maincode, 0, 0, '', [w_ten], [w_fibo], [w_func], w_global) w_retval = execute_function(w_main, []) assert w_retval.to_int() == 55
if tailp: frame.leave_with_retval(w_closure) else: frame.push(w_closure) class W_DumpBytecodeFunction(W_NativeClosure): _symbol_ = 'dump-bytecode-function' def call(self, args_w): assert len(args_w) == 1 w_arg, = args_w assert isinstance(w_arg, W_BytecodeClosure) assert not w_arg.upvals_w return dump_bytecode_function(w_arg.w_func) name2type = { 'symbol': W_Symbol, 'string': W_String, 'integer': W_Integer, 'void': W_Unspecified, 'boolean': W_Boolean, } for val in globals().values(): if (isinstance(val, type) and issubclass(val, (W_NativeClosure, W_NativeClosureX)) and hasattr(val, '_symbol_')): prelude_registry.append((symbol(val._symbol_), val())) del val
def call(self, args_w): assert len(args_w) == 1 w_str, = args_w assert isinstance(w_str, W_String) return symbol(w_str.content())
def w_tag(s, w_x): return W_Pair(symbol(s), W_Pair(w_x, w_nil))
frame.leave_with_retval(w_closure) else: frame.push(w_closure) class W_DumpBytecodeFunction(W_NativeClosure): _symbol_ = 'dump-bytecode-function' def call(self, args_w): assert len(args_w) == 1 w_arg, = args_w assert isinstance(w_arg, W_BytecodeClosure) assert not w_arg.upvals_w return dump_bytecode_function(w_arg.w_func) name2type = { 'symbol': W_Symbol, 'string': W_String, 'integer': W_Integer, 'void': W_Unspecified, 'boolean': W_Boolean, } for val in globals().values(): if (isinstance(val, type) and issubclass(val, (W_NativeClosure, W_NativeClosureX)) and hasattr(val, '_symbol_')): prelude_registry.append((symbol(val._symbol_), val())) del val
from tvm.asm.assembler import load_bytecode_function from tvm.lang.reader import read_string from tvm.lang.model import symbol from tvm.util import localpath from tvm.lang.env import ModuleDict from tvm.rt.prelude import populate_module from tvm.rt.execution import execute_function with open(localpath(__file__, 'stage2-compiled-lib.ss')) as f: content = f.read() w_lib_expr = read_string(content)[0] lib_module = ModuleDict() populate_module(lib_module) w_lib_function = load_bytecode_function(w_lib_expr, lib_module) execute_function(w_lib_function, []) w_macro_expander = lib_module.getitem(symbol("expand-builtin-macro")).w_func w_code_compiler = lib_module.getitem(symbol("compile-program")).w_func def compile_expr(w_expr, w_module): w_expanded = execute_function(w_macro_expander, [w_expr]) w_compiled = execute_function(w_code_compiler, [w_expanded]) return load_bytecode_function(w_compiled, w_module)