def build_llvm(ast): assert (ast.get_node(ast.root).tag == "program") # Type dictionary used in parsing the AST type_dict = { "int": ir.IntType(8), # Assuming 8 bit ints for testing "double": ir.DoubleType(), "void": ir.VoidType() } ir_funcs = {} # Stores function objects for use when calling functions # Create module module = ir.Module(name="program") # Module object stores all program data # Iterate through children of root for node in ast.children(ast.root): if (node.tag.index("func:") == 0): # Function definition found func_name = node.tag[5:] func_return = "" func_params = [] # Iterate through node children to: # Define type # Define params # Find body func_body = None # Used to keep track of the func_body node for child in ast.children(node.identifier): if (child.tag == "return_type"): func_return = ast.children(child.identifier)[0].tag assert (len(func_return) > 0) elif (child.tag == "params"): for param in ast.children(child.identifier): param_type = param.tag param_name = ast.children(param.identifier)[0].tag func_params.append([param_type, param_name]) elif (child.tag == "func_body"): func_body = child assert (func_body is not None) # Check that we found the func_body # Verify that types are known and update from strings to IR type objects if (func_return in type_dict): func_return = type_dict[func_return] else: raise Exception("Unknown Type: " + func_return) for param in func_params: if (param[0] in type_dict): param[0] = type_dict[param[0]] else: raise Exception("Unknown Type: " + param[0]) # Create function in LLVM func_type = ir.FunctionType( func_return, # Return type tuple([p[0] for p in func_params]) # Tuple of param types ) function = ir.Function(module, func_type, name=func_name) ir_funcs[func_name] = function # Store function object by name # Build function block = function.append_basic_block( name="entry") # Create function block builder = ir.IRBuilder( block) # Create builder object to work within block # FUNCTION IMPLEMENTATION BUILT HERE traversal_stack = [] # Used to traverse tree build node_stack node_stack = [ ] # Used to build function. Nodes pushed in level order, popped in reverse level order traversal_stack.append(func_body) while (len(traversal_stack) > 0): iter_node = traversal_stack.pop( ) # Get next node from traversal_stack node_stack.append(iter_node) # Add current node to node_stack # Add children to the traversal_stack for child in ast.children(iter_node.identifier): traversal_stack.append(child) # Use reverse level order traversal to build function by popping node_stack node_results = { } # Used to keep track of IR results by node ID (intermediate steps) func_locals = { } # Used to keep track of local variable names by node tag # dictionary key (node tag) is the variable's name in the parse tree # dictionary value is the variable's name generated by the IR builder # Begin reverse level order traversal of parse tree bin_ops = [ '=', '+', '-', '*', '/', '%', '&&', '||', '<', '>', "<=", '>=', '==', '+=', '-=', '*=', '/=', '<<', '>>' ] una_ops = ['++', '--'] while (len(node_stack) > 0): iter_node = node_stack.pop() ''' TO DO: - Test unary operations - Flow control - Test variable assignment (=) - Constant types other than int or float? - Global variables? ''' if (iter_node.tag == "func_body"): # First node in subtree is just for finding the children # Can be ignored in function building pass elif (iter_node.tag in bin_ops): # Binary operation # Get operand node identifiers child_l = ast.children(iter_node.identifier)[0].identifier child_r = ast.children(iter_node.identifier)[1].identifier # Get IR representations of operand nodes operand_l = node_results[child_l] operand_r = node_results[child_r] result = None if (iter_node.tag in ['+=', '-=', '*=', '/=', '%=', '=']): # Local variables only exist in the builder and not the final IR # Values are stored in the func_locals dictionary # Key = variable name as seen in iter_node.tag # Value = IR generated result from right hand of assignment var_name = ast.children(iter_node.identifier)[0].tag if (iter_node.tag in ['+=', '-=', '*=', '/=', '%=']): # Get current value of left operand if (var_name in func_locals): operand_l = func_locals[var_name] elif (var_name in [p[1] for p in func_params]): operand_l = function.args[[ p[1] for p in func_params ].index(var_name)] else: assert (False) # Evaluate right side operand if (iter_node.tag == '+='): operand_r = builder.fadd(operand_l, operand_r) elif (iter_node.tag == '-='): operand_r = builder.fsub(operand_l, operand_r) elif (iter_node.tag == '*='): operand_r = builder.fmul(operand_l, operand_r) elif (iter_node.tag == '/='): operand_r = builder.fdiv(operand_l, operand_r) elif (iter_node.tag == '%='): operand_r = builder.frem(operand_l, operand_r) # Assign new value where appropriate if (var_name in func_locals): # Assigning new value to existing local variable func_locals[var_name] = operand_r elif (var_name in [p[1] for p in func_params]): # Assigning new value to function parameter # Create "copy" of parameter as local variable func_locals[var_name] = operand_r else: # Defining new local variable func_locals[var_name] = operand_r elif (iter_node.tag == '+'): result = builder.fadd(operand_l, operand_r) elif (iter_node.tag == '-'): result = builder.fsub(operand_l, operand_r) elif (iter_node.tag == '*'): result = builder.fmul(operand_l, operand_r) elif (iter_node.tag == '/'): result = builder.fdiv(operand_l, operand_r) elif (iter_node.tag == '%'): result = builder.frem(operand_l, operand_r) elif (iter_node.tag == '&&'): # Must be implmemented using other operators # (x && y) is equivialent to ((x * y) != 0) step_1 = builder.fmul(operand_l, operand_r) step_2 = ir.Constant(type_dict["int"], 0) result = builder.icmp_signed('!=', step_1, step_2) elif (iter_node.tag == '||'): # Must be implmemented using other operators # (x || y) is equivialent to ((x + y)+(x * y) != 0) step_1 = builder.fadd(operand_l, operand_r) step_2 = builder.fmul(operand_l, operand_r) step_3 = builder.fadd(step_1, step_2) step_4 = ir.Constant(type_dict["int"], 0) result = builder.icmp_signed('!=', step_3, step_4) elif (iter_node.tag in ['<', '>', '<=', '>=', '==', '!=']): result = builder.icmp_signed(iter_node.tag, operand_l, operand_r) # This is the signed comparison. # There's also an unsigned comparison if we care about that elif (iter_node.tag == '<<'): result = builder.shl(operand_l, operand_r) elif (iter_node.tag == '>>'): # Using arithmetic right shift (C/C++ norm) instead of logical shift result = builder.ashr(operand_l, operand_r) assert ( result is not None ) # Verify that one of the above cases was satisfied node_results[ iter_node.identifier] = result # Store IR result elif (iter_node.tag in una_ops): # Unary operation # Get operand node identifiers child = ast.children(iter_node.identifier)[0].identifier # Get IR representations of operand nodes operand = node_results[child] var_name = ast.children(iter_node.identifier)[0].tag result = None # Construct arithmetic statement if (iter_node.tag in ['++', '--']): print( "Unary Ops: ++ and -- modify value but act like assignment" ) # Get current value of left operand if (var_name in func_locals): operand = func_locals[var_name] elif (var_name in [p[1] for p in func_params]): operand = function.args[[ p[1] for p in func_params ].index(var_name)] else: assert (False) if (iter_node.tag == '++'): result = builder.fadd( operand, ir.Constant(type_dict["int"], 1)) elif (iter_node.tag == '--'): result = builder.fsub( operand, ir.Constant(type_dict["int"], 1)) assert (result is not None) # Assign new value where appropriate if (var_name in func_locals): # Assigning new value to existing local variable func_locals[var_name] = operand_r elif (var_name in [p[1] for p in func_params]): # Assigning new value to function parameter # Create "copy" of parameter as local variable func_locals[var_name] = operand_r else: # Defining new local variable func_locals[var_name] = operand_r assert ( result is not None ) # Verify that one of the above cases was satisfied node_results[ iter_node.identifier] = result # Store IR result elif (iter_node.tag == 'return'): if (len(ast.children(iter_node.identifier)) == 0): # Void return assert (func_return == type_dict["void"]) builder.ret_void() else: # Returning an expression child_id = ast.children( iter_node.identifier)[0].identifier result = node_results[child_id] builder.ret(result) else: # Node is either a constant, variable ID, or function call if (iter_node.tag in ir_funcs): # Function call arg_list = [] for child in ast.children(iter_node.identifier): arg_list.append(node_results[child.identifier]) builder.call(ir_funcs[iter_node.tag], arg_list) else: # Constant or variable assert (len(ast.children(iter_node.identifier)) == 0) var_type = "" is_numeral = uf.IsInt( iter_node.tag) # if true, then int if (is_numeral): var_type = "int" else: try: float(iter_node.tag) var_type = "float" is_numeral = True except: pass if (is_numeral): # Constant assert (len(var_type) > 0) assert (type_dict[var_type] is not None) constant = 0 if (var_type == "int"): constant = int(iter_node.tag) elif (var_type == "float"): constant = float(iter_node.tag) else: print("Unaccounted for type") result = ir.Constant(type_dict[var_type], constant) else: # Variable if (iter_node.tag not in [p[1] for p in func_params]): # Local variable # NOTE: Check locals first because arguments # that are changed by assignment are copied to # local variables, so thats where the most up # to date value will be stroed result = func_locals[iter_node.tag] else: # Function argument result = function.args[[ p[1] for p in func_params ].index(iter_node.tag)] node_results[iter_node.identifier] = result elif (True): print("Handle case for global variables") # Return LLVM module return module
def generate_kernel_wrapper(self, library, fndesc, kernel_name, debug, filename, linenum): """ Generate the kernel wrapper in the given ``library``. The function being wrapped is described by ``fndesc``. The wrapper function is returned. """ argtypes = fndesc.argtypes arginfo = self.get_arg_packer(argtypes) argtys = list(arginfo.argument_types) wrapfnty = ir.FunctionType(ir.VoidType(), argtys) wrapper_module = self.create_module("cuda.kernel.wrapper") fnty = ir.FunctionType( ir.IntType(32), [self.call_conv.get_return_type(types.pyobject)] + argtys) func = ir.Function(wrapper_module, fnty, fndesc.llvm_func_name) prefixed = itanium_mangler.prepend_namespace(func.name, ns='cudapy') wrapfn = ir.Function(wrapper_module, wrapfnty, prefixed) builder = ir.IRBuilder(wrapfn.append_basic_block('')) if debug: debuginfo = self.DIBuilder( module=wrapper_module, filepath=filename, cgctx=self, ) debuginfo.mark_subprogram( wrapfn, kernel_name, fndesc.args, argtypes, linenum, ) debuginfo.mark_location(builder, linenum) # Define error handling variable def define_error_gv(postfix): name = wrapfn.name + postfix gv = cgutils.add_global_variable(wrapper_module, ir.IntType(32), name) gv.initializer = ir.Constant(gv.type.pointee, None) return gv gv_exc = define_error_gv("__errcode__") gv_tid = [] gv_ctaid = [] for i in 'xyz': gv_tid.append(define_error_gv("__tid%s__" % i)) gv_ctaid.append(define_error_gv("__ctaid%s__" % i)) callargs = arginfo.from_arguments(builder, wrapfn.args) status, _ = self.call_conv.call_function(builder, func, types.void, argtypes, callargs) if debug: # Check error status with cgutils.if_likely(builder, status.is_ok): builder.ret_void() with builder.if_then(builder.not_(status.is_python_exc)): # User exception raised old = ir.Constant(gv_exc.type.pointee, None) # Use atomic cmpxchg to prevent rewriting the error status # Only the first error is recorded if nvvm.NVVM().is_nvvm70: xchg = builder.cmpxchg(gv_exc, old, status.code, 'monotonic', 'monotonic') changed = builder.extract_value(xchg, 1) else: casfnty = ir.FunctionType( old.type, [gv_exc.type, old.type, old.type]) cas_hack = "___numba_atomic_i32_cas_hack" casfn = ir.Function(wrapper_module, casfnty, name=cas_hack) xchg = builder.call(casfn, [gv_exc, old, status.code]) changed = builder.icmp_unsigned('==', xchg, old) # If the xchange is successful, save the thread ID. sreg = nvvmutils.SRegBuilder(builder) with builder.if_then(changed): for dim, ptr, in zip("xyz", gv_tid): val = sreg.tid(dim) builder.store(val, ptr) for dim, ptr, in zip("xyz", gv_ctaid): val = sreg.ctaid(dim) builder.store(val, ptr) builder.ret_void() nvvm.set_cuda_kernel(wrapfn) library.add_ir_module(wrapper_module) if debug: debuginfo.finalize() library.finalize() wrapfn = library.get_function(wrapfn.name) return wrapfn
def _declare_print(self): voidptr_type = ir.IntType(8).as_pointer() printf_type = ir.FunctionType(ir.IntType(32), [voidptr_type], var_arg=True) ir.Function(self.module, printf_type, name='printf')
def _seed_impl(context, builder, sig, args, state_ptr): seed_value, = args fnty = ir.FunctionType(ir.VoidType(), (rnd_state_ptr_t, int32_t)) fn = builder.function.module.get_or_insert_function(fnty, "numba_rnd_init") builder.call(fn, (state_ptr, seed_value)) return context.get_constant(types.none, None)
def define_bool_to_str(self, dyn_array_ptr): # START func_type = ir.FunctionType(type_map[VOID], [dyn_array_ptr, type_map[BOOL]]) func = ir.Function(self.module, func_type, 'bool_to_str') entry_block = func.append_basic_block('entry') builder = ir.IRBuilder(entry_block) self.builder = builder exit_block = func.append_basic_block('exit') array_ptr = builder.alloca(dyn_array_ptr) builder.store(func.args[0], array_ptr) # BODY equalszero = builder.icmp_signed(EQUALS, func.args[1], ir.Constant(type_map[BOOL], 0)) dyn_array_append = self.module.get_global('i64_array_append') with builder.if_else(equalszero) as (then, otherwise): with then: builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 102)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 97)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 108)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 115)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 101)]) with otherwise: builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 116)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 114)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 117)]) builder.call( dyn_array_append, [builder.load(array_ptr), ir.Constant(type_map[INT], 101)]) builder.branch(exit_block) # CLOSE builder.position_at_end(exit_block) builder.ret_void()
def dict_empty_int32(context, builder, fromty, toty, val): fnty = lir.FunctionType(lir.IntType(1), [lir.IntType(8).as_pointer()]) fn = builder.module.get_or_insert_function( fnty, name="dict_int32_int32_not_empty") return builder.call(fn, (val, ))
def function(self, module=None, name='my_func'): module = module or self.module() fnty = ir.FunctionType(int32, (int32, int32, dbl, ir.PointerType(int32))) return ir.Function(self.module(), fnty, name)
import llvmlite.ir as ir
def ll_type(self): args = [a.ll_type() for a in self.arg_types] return ll.FunctionType(self.ret_type.ll_type(), args)
import faulthandler faulthandler.enable() except ImportError: pass llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() i8 = ll.IntType(8) i32 = ll.IntType(32) i64 = ll.IntType(64) MEMORY_SIZE = 1 << 16 COMPILED_FN_TYPE = ll.FunctionType(ll.VoidType(), []) MEMORY_TYPE = ll.ArrayType(i8, MEMORY_SIZE) ZERO_i8 = ll.Constant(i8, 0) ZERO_i32 = ll.Constant(i8, 0) ONE_i8 = ll.Constant(i8, 1) ONE_i32 = ll.Constant(i32, 1) MEMORY_MASK_i32 = ll.Constant(i32, MEMORY_SIZE - 1) def getc(): return sys.stdin.read(1) def putc(c): sys.stdout.write(chr(c & 0x7f))
def compile_bf(prog): """ Compiles the given BF program text into a llvm.ModuleRef object. The module will contain 3 globals: - the main function, void bfmain() - the memory, int8_t memory[] - the memory index, int32_t index """ module = ll.Module() func = ll.Function(module, ll.FunctionType(ll.VoidType(), []), 'bfmain') builder = ll.IRBuilder() g_memory = ll.GlobalVariable(module, MEMORY_TYPE, 'memory') g_index = ll.GlobalVariable(module, i32, 'index') # Initialize the memory and index pointer to 0. g_memory.initializer = ll.Constant(MEMORY_TYPE, None) g_index.initializer = ll.Constant(i32, None) # Create the "putc" function. putc_type = ll.FunctionType(ll.VoidType(), [i8]) getc_type = ll.FunctionType(i8, []) f_putc = create_thunk(module, putc_type, PUTC_WRAPPER, 'putc') f_getc = create_thunk(module, getc_type, GETC_WRAPPER, 'getc') # The block_stack tracks the current block and remaining blocks. The top # block is what we currently compile into, the one below it is the block # that follows the next ] (if we're in a loop). block_stack = [func.append_basic_block('entry')] loop_stack = [] builder.position_at_end(block_stack[-1]) def current_index_ptr(): index = builder.load(g_index) # The extra dereference here with ZERO is required because g_memory is # itself a pointer, so this becomes &g_memory[0][index]. Yeah, it's # weird. # Ref: https://llvm.org/docs/GetElementPtr.html return builder.gep(g_memory, [ZERO_i32, index]) line = 1 col = 1 for ch in prog: col += 1 if ch == '\n': col = 1 line += 1 elif ch == '.': ptr = current_index_ptr() value = builder.load(ptr) builder.call(f_putc, [value]) elif ch == ',': res = builder.call(f_getc, []) ptr = current_index_ptr() builder.store(res, ptr) elif ch == '>': # builder.call(f_putc, [ll.Constant(i8, ord('>'))]) index = builder.load(g_index) index = builder.add(index, ONE_i32) index = builder.and_(index, MEMORY_MASK_i32) builder.store(index, g_index) elif ch == '<': # builder.call(f_putc, [ll.Constant(i8, ord('<'))]) index = builder.load(g_index) index = builder.sub(index, ONE_i32) index = builder.and_(index, MEMORY_MASK_i32) builder.store(index, g_index) elif ch == '+': # builder.call(f_putc, [ll.Constant(i8, ord('+'))]) ptr = current_index_ptr() value = builder.load(ptr) value = builder.add(value, ONE_i8) builder.store(value, ptr) elif ch == '-': # builder.call(f_putc, [ll.Constant(i8, ord('-'))]) ptr = current_index_ptr() value = builder.load(ptr) value = builder.sub(value, ONE_i8) builder.store(value, ptr) elif ch == '[': # start a loop # builder.call(f_putc, [ll.Constant(i8, ord('['))]) loop_block = func.append_basic_block() tail_block = func.append_basic_block() # If memory[index] != 0, enter loop, otherwise skip. ptr = current_index_ptr() value = builder.load(ptr) nonzero = builder.icmp_unsigned('!=', value, ZERO_i8) builder.cbranch(nonzero, loop_block, tail_block) # Update our block stack. The current block is finished. block_stack.pop() block_stack.append(tail_block) block_stack.append(loop_block) loop_stack.append(loop_block) builder.position_at_end(block_stack[-1]) elif ch == ']': # end a loop # builder.call(f_putc, [ll.Constant(i8, ord(']'))]) if len(block_stack) <= 1: raise ValueError('{}:{}: unmatched ]'.format(line, col)) # If memory[index] != 0, repeat current loop, otherwise break. ptr = current_index_ptr() value = builder.load(ptr) nonzero = builder.icmp_unsigned('!=', value, ZERO_i8) builder.cbranch(nonzero, loop_stack[-1], block_stack[-2]) # Update our block stack. The current block is finished. block_stack.pop() loop_stack.pop() builder.position_at_end(block_stack[-1]) else: continue if len(block_stack) != 1: raise ValueError('{}:{}: unmatched ['.format(line, col)) # Finish the function. builder.ret_void() assembly = str(module) # print(assembly) return llvm.parse_assembly(assembly)
def _codegen_Prototype(self, node): funcname = node.name # Create a function type vartypes = [] vartypes_with_defaults = [] append_to = vartypes for x in node.argnames: s = x.vartype if x.initializer is not None: append_to = vartypes_with_defaults append_to.append(s) # TODO: it isn't yet possible to have an implicitly # typed function that just uses the return type of the body # we might be able to do this by way of a special call # to this function # note that Extern functions MUST be typed if node.vartype is None: node.vartype = self.vartypes._DEFAULT_TYPE functype = ir.FunctionType(node.vartype, vartypes + vartypes_with_defaults) public_name = funcname opt_args = None linkage = None # TODO: identify anonymous functions with a property # not by way of their nomenclature if node.extern is False and not funcname.startswith( '_ANONYMOUS.') and funcname != 'main': linkage = 'private' if len(vartypes) > 0: funcname = public_name + mangle_args(vartypes) else: funcname = public_name + '@' required_args = funcname if len(vartypes_with_defaults) > 0: opt_args = mangle_optional_args(vartypes_with_defaults) funcname += opt_args # If a function with this name already exists in the module... if funcname in self.module.globals: # We only allow the case in which a declaration exists and now the # function is defined (or redeclared) with the same number of args. func = existing_func = self.module.globals[funcname] if not isinstance(existing_func, ir.Function): raise CodegenError( f'Function/universal name collision {funcname}', node.position) # If we're redefining a forward declaration, # erase the existing function body if not existing_func.is_declaration: existing_func.blocks = [] if len(existing_func.function_type.args) != len(functype.args): raise CodegenError( f'Redefinition of function "{public_name}" with different number of arguments', node.position) else: # Otherwise create a new function func = ir.Function(self.module, functype, funcname) # Name the arguments for i, arg in enumerate(func.args): arg.name = node.argnames[i].name if opt_args is not None: self.opt_args_funcs[required_args] = func # Set defaults (if any) for x, n in enumerate(node.argnames): if n.initializer is not None: func.args[x].default_value = self._codegen( n.initializer, False) if node.varargs: func.ftype.var_arg = True func.public_name = public_name func.returns = [] ############################################################## # Set LLVM function attributes ############################################################## # First, extract a copy of the function decorators # and use that to set up other attributes decorators = [n.name for n in self.func_decorators] varfunc = 'varfunc' in decorators for a, b in decorator_collisions: if a in decorators and b in decorators: raise CodegenError( f'Function cannot be decorated with both "@{a}" and "@{b}"', node.position) # Calling convention. # This is the default with no varargs if node.varargs is None: if not node.extern: func.calling_convention = 'fastcc' # Linkage. # Default is 'private' if it's not extern, an anonymous function, or main if linkage: func.linkage = linkage # Address is not relevant by default func.unnamed_addr = True # Enable optnone for main() or anything # designated as a target for a function pointer. if funcname == 'main' or varfunc: func.attributes.add('optnone') func.attributes.add('noinline') # Inlining. Operator functions are inlined by default. if ( # function is manually inlined ('inline' in decorators) or # function is an operator, not @varfunc, # and not @noinline (node.isoperator and not varfunc and 'noinline' not in decorators )): func.attributes.add('alwaysinline') # function is @noinline # or function is @varfunc if 'noinline' in decorators: func.attributes.add('noinline') # End inlining. # External calls, by default, no recursion if node.extern: func.attributes.add('norecurse') func.linkage = 'dllimport' # By default, no lazy binding func.attributes.add('nonlazybind') # By default, no stack unwinding func.attributes.add('nounwind') func.decorators = decorators return func
int soma = (x + y); int subtracao = (x - y); int multiplicacao = (x * y); int divisao = (x / y); int modulo = (x % y); int shiftDireita = (x >> 1); int shiftEsquerda = (x << 1); return 0; } ''' # Cria o módulo. module = ir.Module('meu_modulo.bc') module.triple = binding.get_default_triple() main_ftype = ir.FunctionType(ir.IntType(32), ()) main_func = ir.Function(module, main_ftype, 'main') entry_block = main_func.append_basic_block('entry') exit_block = main_func.append_basic_block('exit') builder = ir.IRBuilder(entry_block) return_val = builder.alloca(ir.IntType(32), name='ret_val') builder.store(value=ir.Constant(ir.IntType(32), 0), ptr=return_val, align=4) x = builder.alloca(ir.IntType(32), name='x') builder.store(value=ir.Constant(ir.IntType(32), 2), ptr=x, align=4) y = builder.alloca(ir.IntType(32), name='y') builder.store(value=ir.Constant(ir.IntType(32), 1), ptr=y, align=4)
listVariables = {"global": []} listaFuncs = {} llvm.initialize() llvm.initialize_all_targets() llvm.initialize_native_target() llvm.initialize_native_asmprinter() module = ir.Module('module.bc') module.triple = "x86_64-pc-linux-gnu" #llvm.get_default_triple() target = llvm.Target.from_triple(module.triple) target_machine = target.create_target_machine() module.data_layout = target_machine.target_data escrevaInteiro = ir.Function(module,ir.FunctionType(ir.VoidType(), [ir.IntType(32)]),name="escrevaInteiro") escrevaFlutuante = ir.Function(module,ir.FunctionType(ir.VoidType(),[ir.FloatType()]),name="escrevaFlutuante") leiaInteiro = ir.Function(module,ir.FunctionType(ir.IntType(32),[]),name="leiaInteiro") leiaFlutuante = ir.Function(module,ir.FunctionType(ir.FloatType(),[]),name="leiaFlutuante") def splite_tree(node): if len(node.children) >= 1: listOfParents.append(node) for i in node.children: splite_tree(i) else: listOfTerminals.append(node) def splite_node_tree(node): tempListOfParents.clear() tempListOfTerminals.clear()
def impl_dict_int32_int32(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(8).as_pointer(), []) fn = builder.module.get_or_insert_function(fnty, name="dict_int32_int32_init") return builder.call(fn, [])
typeA = ir.ArrayType(ir.IntType(64), 1024) arrayA = ir.GlobalVariable(module, typeA, "A") # arrayA.initializer = ir.IntType(64) arrayA.linkage = "common" # arrayA.initializer = ir.Constant(ir.IntType(64), 0) arrayA.align = 16 # Cria um valor zero para colocar no retorno. Zero64 = ir.Constant(ir.IntType(64), 0) # Declara o tipo do retorno da função main. mainFnReturnType = ir.IntType(64) # Cria a função main. t_func_main = ir.FunctionType(mainFnReturnType, ()) # Declara a função main. main = ir.Function(module, t_func_main, name='main') # Declara o bloco de entrada. entryBlock = main.append_basic_block('entry') endBasicBlock = main.append_basic_block('exit') # Adiciona o bloco de entrada. builder = ir.IRBuilder(entryBlock) # Cria o valor de retorno e inicializa com zero. returnVal = builder.alloca(ir.IntType(64), name='retorno') builder.store(Zero64, returnVal)
def lower_dict_max_int32(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(32), [lir.IntType(8).as_pointer()]) fn = builder.module.get_or_insert_function(fnty, name="dict_int32_int32_max") return builder.call(fn, args)
def dist_get_time(context, builder, sig, args): fnty = lir.FunctionType(lir.DoubleType(), []) fn = builder.module.get_or_insert_function(fnty, name="hpat_get_time") return builder.call(fn, [])
import sys from collections import namedtuple import llvmlite.ir as ir import llvmlite.binding as llvm from ctypes import CFUNCTYPE # main (and only) module module = ir.Module() # main (and only) function func_t = ir.FunctionType(ir.VoidType(), []) func = ir.Function(module, func_t, "func") # entry point of func bb_entry = func.append_basic_block('entry') irbuilder = ir.IRBuilder(bb_entry) # memory size NUM_CELLS = 30000 # Types cell_t = ir.IntType(8) pcell_t = cell_t.as_pointer() memory_t = ir.ArrayType(cell_t, NUM_CELLS) int32_t = ir.IntType(32) # Constants zero = cell_t(0) one = cell_t(1)
def lower_dist_wait(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(32), [lir.IntType(32), lir.IntType(1)]) fn = builder.module.get_or_insert_function(fnty, name="hpat_dist_wait") return builder.call(fn, args)
def pq_size_lower(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(64), [lir.IntType(8).as_pointer(), lir.IntType(64)]) fn = builder.module.get_or_insert_function(fnty, name="pq_get_size") return builder.call(fn, args)
def dist_get_size(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(32), []) fn = builder.module.get_or_insert_function(fnty, name="hpat_dist_get_size") return builder.call(fn, [])
def dynamic_array_set(self, dyn_array_ptr, array_type): # START dyn_array_set_type = ir.FunctionType( type_map[VOID], [dyn_array_ptr, type_map[INT], llvm_type_map[array_type]]) dyn_array_set = ir.Function(self.module, dyn_array_set_type, '{}_array_set'.format(array_type)) dyn_array_set_entry = dyn_array_set.append_basic_block('entry') builder = ir.IRBuilder(dyn_array_set_entry) self.builder = builder dyn_array_set_exit = dyn_array_set.append_basic_block('exit') dyn_array_set_index_out_of_bounds = dyn_array_set.append_basic_block( 'index_out_of_bounds') dyn_array_set_is_index_less_than_zero = dyn_array_set.append_basic_block( 'is_index_less_than_zero') dyn_array_set_negative_index = dyn_array_set.append_basic_block( 'negative_index') dyn_array_set_block = dyn_array_set.append_basic_block('set') builder.position_at_end(dyn_array_set_entry) array_ptr = builder.alloca(dyn_array_ptr) builder.store(dyn_array_set.args[0], array_ptr) index_ptr = builder.alloca(type_map[INT]) builder.store(dyn_array_set.args[1], index_ptr) value_ptr = builder.alloca(llvm_type_map[array_type]) builder.store(dyn_array_set.args[2], value_ptr) # BODY index_val = builder.load(index_ptr) size_ptr = builder.gep(builder.load(array_ptr), [zero_32, zero_32], inbounds=True) size_val = builder.load(size_ptr) compare_index_to_size = builder.icmp_signed(GREATER_THAN_OR_EQUAL_TO, index_val, size_val) builder.cbranch(compare_index_to_size, dyn_array_set_index_out_of_bounds, dyn_array_set_is_index_less_than_zero) builder.position_at_end(dyn_array_set_index_out_of_bounds) self.print_string('Array index out of bounds') builder.call(self.module.get_global('exit'), [one_32]) builder.unreachable() builder.position_at_end(dyn_array_set_is_index_less_than_zero) compare_index_to_zero = builder.icmp_signed(LESS_THAN, index_val, zero) builder.cbranch(compare_index_to_zero, dyn_array_set_negative_index, dyn_array_set_block) builder.position_at_end(dyn_array_set_negative_index) add = builder.add(size_val, index_val) builder.store(add, index_ptr) builder.branch(dyn_array_set_block) builder.position_at_end(dyn_array_set_block) data_ptr = builder.gep(builder.load(array_ptr), [zero_32, two_32], inbounds=True) add_1 = builder.add(one, index_val) builder.store(add_1, index_ptr) index_val = builder.load(index_ptr) data_element_ptr = builder.gep(builder.load(data_ptr), [index_val], inbounds=True) builder.store(builder.load(value_ptr), data_element_ptr) builder.branch(dyn_array_set_exit) # CLOSE builder.position_at_end(dyn_array_set_exit) builder.ret_void()
def lower_open_bag(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(8).as_pointer(), [lir.IntType(8).as_pointer()]) fn = builder.module.get_or_insert_function(fnty, name="open_bag") return builder.call(fn, args)
def function(res, args, var_arg=False): return ir.FunctionType(res, args, var_arg=var_arg)
def lower_get_msg_count(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(64), [lir.IntType(8).as_pointer()]) fn = builder.module.get_or_insert_function(fnty, name="get_msg_count") return builder.call(fn, args)
def _declare_print_function(self): # Declare Printf function voidptr_ty = ir.IntType(8).as_pointer() printf_ty = ir.FunctionType(ir.IntType(32), [voidptr_ty], var_arg=True) printf = ir.Function(self.module, printf_ty, name="printf") self.printf = printf
def _randrange_impl(context, builder, start, stop, step, state): state_ptr = get_state_ptr(context, builder, state) ty = stop.type zero = ir.Constant(ty, 0) one = ir.Constant(ty, 1) nptr = cgutils.alloca_once(builder, ty, name="n") # n = stop - start builder.store(builder.sub(stop, start), nptr) with builder.if_then(builder.icmp_signed("<", step, zero)): # n = (n + step + 1) // step w = builder.add(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) with builder.if_then(builder.icmp_signed(">", step, one)): # n = (n + step - 1) // step w = builder.sub(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) n = builder.load(nptr) with cgutils.if_unlikely(builder, builder.icmp_signed("<=", n, zero)): # n <= 0 msg = "empty range for randrange()" context.call_conv.return_user_exc(builder, ValueError, (msg, )) fnty = ir.FunctionType(ty, [ty, cgutils.true_bit.type]) fn = builder.function.module.get_or_insert_function( fnty, "llvm.ctlz.%s" % ty) # Since the upper bound is exclusive, we need to subtract one before # calculating the number of bits. This leads to a special case when # n == 1; there's only one possible result, so we don't need bits from # the PRNG. This case is handled separately towards the end of this # function. CPython's implementation is simpler and just runs another # iteration of the while loop when the resulting number is too large # instead of subtracting one, to avoid needing to handle a special # case. Thus, we only perform this subtraction for the NumPy case. nm1 = builder.sub(n, one) if state == "np" else n nbits = builder.trunc(builder.call(fn, [nm1, cgutils.true_bit]), int32_t) nbits = builder.sub(ir.Constant(int32_t, ty.width), nbits) rptr = cgutils.alloca_once(builder, ty, name="r") def get_num(): bbwhile = builder.append_basic_block("while") bbend = builder.append_basic_block("while.end") builder.branch(bbwhile) builder.position_at_end(bbwhile) r = get_next_int(context, builder, state_ptr, nbits, state == "np") r = builder.trunc(r, ty) too_large = builder.icmp_signed(">=", r, n) builder.cbranch(too_large, bbwhile, bbend) builder.position_at_end(bbend) builder.store(r, rptr) if state == "np": # Handle n == 1 case, per previous comment. with builder.if_else(builder.icmp_signed("==", n, one)) as (is_one, is_not_one): with is_one: builder.store(zero, rptr) with is_not_one: get_num() else: get_num() return builder.add(start, builder.mul(builder.load(rptr), step))
llvm.initialize() llvm.initialize_all_targets() llvm.initialize_native_target() llvm.initialize_native_asmprinter() modulo = ir.Module('module.bc') modulo.triple = llvm.get_default_triple() target = llvm.Target.from_triple(modulo.triple) target_machine = target.create_target_machine() modulo.data_layout = target_machine.target_data escrevaInteiro = ir.Function(modulo, ir.FunctionType(ir.VoidType(), [ir.IntType(32)]), name="escrevaInteiro") escrevaFlutuante = ir.Function(modulo, ir.FunctionType(ir.VoidType(), [ir.FloatType()]), name="escrevaFlutuante") leiaInteiro = ir.Function(modulo, ir.FunctionType(ir.IntType(32), []), name="leiaInteiro") leiaFlutuante = ir.Function(modulo, ir.FunctionType(ir.FloatType(), []), name="leiaFlutuante") # Dicionario de variaveis globais info = {"variaveis_globais": []}
def h5_size(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(64), [h5file_lir_type, lir.IntType(32)]) fn = builder.module.get_or_insert_function(fnty, name="hpat_h5_size") return builder.call(fn, [args[0], args[1]])