def test_get_type_error(self): ctxt = gccjit.Context() with self.assertRaises(gccjit.Error) as cm: ctxt.get_type(-1) self.assertEqual(cm.exception.msg, (b'gcc_jit_context_get_type:' b' unrecognized value for enum gcc_jit_types: -1'))
def test_union(self): ctxt = gccjit.Context() int_type = ctxt.get_type(gccjit.TypeKind.INT) float_type = ctxt.get_type(gccjit.TypeKind.FLOAT) as_int = ctxt.new_field(int_type, b'as_int') as_float = ctxt.new_field(float_type, b'as_float') u = ctxt.new_union(b'u', [as_int, as_float]) self.assertEqual(str(u), 'union u')
def test_opaque_struct(self): ctxt = gccjit.Context() foo = ctxt.new_struct(b'foo') foo_ptr = foo.get_pointer() self.assertEqual(str(foo_ptr), 'struct foo *') foo.set_fields([ ctxt.new_field(foo_ptr, b'prev'), ctxt.new_field(foo_ptr, b'next') ])
def test_rvalue_from_ptr(self): ctxt = gccjit.Context() type_ = ctxt.get_type(gccjit.TypeKind.CONST_CHAR_PTR) null_ptr = ctxt.new_rvalue_from_ptr(type_, 0) self.assertEqual(str(null_ptr), '(const char *)NULL') type_ = ctxt.get_type(gccjit.TypeKind.VOID_PTR) nonnull_ptr = ctxt.new_rvalue_from_ptr(type_, id(self)) self.assertEqual(str(nonnull_ptr), '(void *)0x%x' % id(self))
def test_new_block_error(self): ctxt = gccjit.Context() int_type = ctxt.get_type(gccjit.TypeKind.INT) func = ctxt.new_function(gccjit.FunctionKind.IMPORTED, int_type, b"foo", []) with self.assertRaises(gccjit.Error) as cm: func.new_block() self.assertEqual(cm.exception.msg, (b'gcc_jit_function_new_block:' b' cannot add block to an imported function'))
def test_imported_function(self): """ void some_fn (const char *name) { static char buffer[1024]; snprintf(buffer, sizeof(buffer), "hello %s\n", name); } """ ctxt = gccjit.Context() void_type = ctxt.get_type(gccjit.TypeKind.VOID) const_char_p = ctxt.get_type(gccjit.TypeKind.CONST_CHAR_PTR) char_type = ctxt.get_type(gccjit.TypeKind.CHAR) char_p = char_type.get_pointer() int_type = ctxt.get_type(gccjit.TypeKind.INT) size_type = ctxt.get_type(gccjit.TypeKind.SIZE_T) buf_type = ctxt.new_array_type(char_type, 1024) # extern int snprintf(char *str, size_t size, const char *format, ...); snprintf = ctxt.new_function( gccjit.FunctionKind.IMPORTED, int_type, b'snprintf', [ ctxt.new_param(char_p, b's'), ctxt.new_param(size_type, b'n'), ctxt.new_param(const_char_p, b'format') ], is_variadic=True) # void some_fn (const char *name) { param_name = ctxt.new_param(const_char_p, b'name') func = ctxt.new_function(gccjit.FunctionKind.EXPORTED, void_type, b'some_fn', [param_name]) # static char buffer[1024]; buffer = func.new_local(buf_type, b'buffer') # snprintf(buffer, sizeof(buffer), "hello %s\n", name); args = [ ctxt.new_cast(buffer.get_address(), char_p), ctxt.new_rvalue_from_int(size_type, 1024), ctxt.new_string_literal(b'hello %s\n'), param_name ] block = func.new_block(b'entry') call = ctxt.new_call(snprintf, args) self.assertEqual(call.get_type(), int_type) block.add_eval(call) block.end_with_void_return() result = ctxt.compile() py_func_type = ctypes.CFUNCTYPE(None, ctypes.c_char_p) py_func = py_func_type(result.get_code(b'some_fn')) py_func(b'blah')
def test_new_function_error(self): ctxt = gccjit.Context() int_type = ctxt.get_type(gccjit.TypeKind.INT) with self.assertRaises(gccjit.Error) as cm: ctxt.new_function(gccjit.FunctionKind.IMPORTED, int_type, b"contains a space", []) self.assertEqual( cm.exception.msg, (b'gcc_jit_context_new_function:' b' name "contains a space" contains invalid character:' b" ' '"))
def test_set_logfile(self): from examples.sum_of_squares import populate_ctxt ctxt = gccjit.Context() with tempfile.NamedTemporaryFile(suffix=".txt") as f: ctxt.set_logfile(f) populate_ctxt(ctxt) ctxt.compile() with open(f.name) as f: logtxt = f.read() self.assertIn('JIT: ', logtxt) self.assertIn('entering: gcc_jit_context_get_type', logtxt)
def test_dump_reproducer(self): from examples.sum_of_squares import populate_ctxt ctxt = gccjit.Context() populate_ctxt(ctxt) with tempfile.NamedTemporaryFile(delete=False, suffix=".c") as f: ctxt.dump_reproducer_to_file(f.name.encode('utf-8')) try: with open(f.name) as f: gensrc = f.read() self.assertIn('#include <libgccjit.h>', gensrc) finally: os.unlink(f.name)
def test_call_through_function_ptr(self): ctxt = gccjit.Context() void_type = ctxt.get_type(gccjit.TypeKind.VOID) int_type = ctxt.get_type(gccjit.TypeKind.INT) fn_ptr_type = ctxt.new_function_ptr_type( void_type, [int_type, int_type, int_type]) self.assertEqual(str(fn_ptr_type), 'void (*) (int, int, int)') fn_ptr = ctxt.new_param(fn_ptr_type, b"fn") a = ctxt.new_param(int_type, b"a") b = ctxt.new_param(int_type, b"b") c = ctxt.new_param(int_type, b"c") call = ctxt.new_call_through_ptr(fn_ptr, [a, b, c]) self.assertEqual(str(call), 'fn (a, b, c)')
def __init__(self): self.ctxt = gccjit.Context() if 1: self.ctxt.set_int_option(gccjit.IntOption.OPTIMIZATION_LEVEL, 3); self.ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_GIMPLE, 0); self.ctxt.set_bool_option(gccjit.BoolOption.DUMP_GENERATED_CODE, 0); self.ctxt.set_bool_option(gccjit.BoolOption.DEBUGINFO, 1); self.ctxt.set_bool_option(gccjit.BoolOption.DUMP_EVERYTHING, 0); self.ctxt.set_bool_option(gccjit.BoolOption.KEEP_INTERMEDIATES, 0); self.void_type = self.ctxt.get_type(gccjit.TypeKind.VOID) self.int_type = self.ctxt.get_type(gccjit.TypeKind.INT) self.byte_type = self.ctxt.get_type(gccjit.TypeKind.UNSIGNED_CHAR) self.array_type = self.ctxt.new_array_type(self.byte_type, 30000) self.func_getchar = ( self.ctxt.new_function(gccjit.FunctionKind.IMPORTED, self.int_type, b"getchar", [])) self.func_putchar = ( self.ctxt.new_function(gccjit.FunctionKind.IMPORTED, self.void_type, b"putchar", [self.ctxt.new_param(self.int_type, b"c")])) self.func = self.ctxt.new_function(gccjit.FunctionKind.EXPORTED, self.void_type, b'func', []) self.curblock = self.func.new_block(b"initial") self.int_zero = self.ctxt.zero(self.int_type) self.int_one = self.ctxt.one(self.int_type) self.byte_zero = self.ctxt.zero(self.byte_type) self.byte_one = self.ctxt.one(self.byte_type) self.data_cells = self.ctxt.new_global(gccjit.GlobalKind.INTERNAL, self.array_type, b"data_cells") self.idx = self.func.new_local(self.int_type, b"idx") self.open_parens = [] self.curblock.add_comment(b"idx = 0;") self.curblock.add_assignment(self.idx, self.int_zero)
def create_fn(): # Create a compilation context: ctxt = gccjit.Context() if 0: ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_TREE, True) ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_GIMPLE, True) ctxt.set_bool_option(gccjit.BoolOption.DUMP_EVERYTHING, True) ctxt.set_bool_option(gccjit.BoolOption.KEEP_INTERMEDIATES, True) if 0: ctxt.set_int_option(gccjit.IntOption.OPTIMIZATION_LEVEL, 3) populate_ctxt(ctxt) jit_result = ctxt.compile() return jit_result
def __init__(self, types, globals_): self.ctxt = gccjit.Context() if 0: self.ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_GIMPLE, True) self.ctxt.set_bool_option(gccjit.BoolOption.DUMP_EVERYTHING, True) self.ctxt.set_bool_option(gccjit.BoolOption.KEEP_INTERMEDIATES, True) self.types = types self.globals_ = globals_ self.functions = {} # Create types self.typedict = {} self.fielddict = {} # Walk types._events, playing it back for (kind, irtype) in types._events: if kind == 'new_type': self.typedict[irtype] = self._make_type(irtype) elif kind == 'setup_fields': self._set_fields(irtype) else: raise ValueError( 'unknown event (%r, %r) whilst playing back type-creation' % (kind, irtype)) # Now create global functions: self.fndict = {} for fn in self.globals_.functions: if isinstance(fn, IrFunction): params = [] for param in fn.params: assert isinstance(param, Param) params.append( self.ctxt.new_param(self.typedict[param.type_], param.name.encode())) self.fndict[fn] = self.ctxt.new_function( gccjit.FunctionKind.IMPORTED, self.typedict[fn.returntype], fn.fnname.encode(), params)
def create_fn(): # Create a compilation context: ctxt = gccjit.Context() # Turn these on to get various kinds of debugging: if 0: ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_TREE, True) ctxt.set_bool_option(gccjit.BoolOption.DUMP_INITIAL_GIMPLE, True) ctxt.set_bool_option(gccjit.BoolOption.DUMP_GENERATED_CODE, True) # Adjust this to control optimization level of the generated code: if 0: ctxt.set_int_option(gccjit.IntOption.OPTIMIZATION_LEVEL, 3) int_type = ctxt.get_type(gccjit.TypeKind.INT) # Create parameter "i": param_i = ctxt.new_param(int_type, b'i') # Create the function: fn = ctxt.new_function(gccjit.FunctionKind.EXPORTED, int_type, b"square", [param_i]) # Create a basic block within the function: block = fn.new_block(b'entry') # This basic block is relatively simple: block.end_with_return( ctxt.new_binary_op(gccjit.BinaryOp.MULT, int_type, param_i, param_i)) # Having populated the context, compile it. jit_result = ctxt.compile() # This is what you get back from ctxt.compile(): assert isinstance(jit_result, gccjit.Result) return jit_result
def test_dereference(self): ctxt = gccjit.Context() type_ = ctxt.get_type(gccjit.TypeKind.CONST_CHAR_PTR) nonnull_ptr = ctxt.new_rvalue_from_ptr(type_, id(self)) self.assertEqual(str(nonnull_ptr.dereference()), '*(const char *)0x%x' % id(self))
def __init__(self): self.ctx = gccjit.Context() self.main_fn, self.argc, self.argv = gccjit.make_main(self.ctx) self.main_block = self.main_fn.new_block(b"entry") self.debug_mode = False