def insert_pointer(module: ir.Module, scope_stack: list, builder: ir.IRBuilder, type_list: list, val_name: tuple, val_value=None): val_type = type_map[type_list[-1]] for pointer in val_name[1]: if pointer == '*': val_type = val_type.as_pointer() if builder is None: val = ir.GlobalVariable(module, val_type, module.get_unique_name(val_name[2][1])) if val_value: val.initializer = val_value else: val = builder.alloca(val_type, name=module.get_unique_name(val_name[2][1])) if val_value: opt_store(builder, val_value, val) scope_stack[-1][val_name[2][1]] = { 'type': 'struct_ptr' if isinstance(type_map[type_list[-1]], ir.IdentifiedStructType) else 'val_ptr', 'val_type': type_list[-1], 'value': val } return val
def compile(self, module: ll.Module, builder: ll.IRBuilder): inputs = [] for i in range(self.num_inputs): path = self.get_pin(f'in{i}') inputs.append(module.get_global(path)) output = module.get_global(self.get_pin('out')) output_v = ll.Constant(INT_TYPE, 0) if self.kind == 'and': output_v = builder.not_(output_v) for inp in inputs: v = builder.load(inp) if self.kind == 'and': output_v = builder.and_(output_v, v) elif self.kind == 'or': output_v = builder.or_(output_v, v) elif self.kind == 'xor': output_v = builder.xor(output_v, v) if self.negated: output_v = builder.not_(output_v) builder.store(output_v, output)
def compile(self, module: ll.Module, builder: ll.IRBuilder): pin_in = self.get_pin('in') pin_out = self.get_pin('out') pin_in = module.get_global(pin_in) pin_out = module.get_global(pin_out) v = builder.load(pin_in) v = builder.not_(v) builder.store(v, pin_out)
def _get_ll_pointer_type(self, target_data, context=None): """ Convert this type object to an LLVM type. """ from llvmlite.ir import Module, GlobalVariable from llvmlite.binding import parse_assembly if context is None: m = Module() else: m = Module(context=context) foo = GlobalVariable(m, self, name="foo") with parse_assembly(str(m)) as llmod: return llmod.get_global_variable(foo.name).type
def __init__(self): # Perform the basic LLVM initialization. You need the following parts: # # 1. A top-level Module object # 2. A Function instance in which to insert code # 3. A Builder instance to generate instructions # # Note: For project 5, we don't have any user-defined # functions so we're just going to emit all LLVM code into a top # level function void main() { ... }. This will get changed later. self.module = Module('module') self.function = Function(self.module, FunctionType(void_type, []), name='main') self.block = self.function.append_basic_block('entry') self.builder = IRBuilder(self.block) # Dictionary that holds all of the global variable/function declarations. # Any declaration in the Gone source code is going to get an entry here self.vars = {} # Dictionary that holds all of the temporary registers created in # the intermediate code. self.temps = {} # Initialize the runtime library functions (see below) self.declare_runtime_library()
def Codegen(ast: ProgramNode, printIR: bool = True): """Genera l'LLVM IR dall'AST in input. Args: ast: L'albero di sintassi astratto. printIR (bool): Un boolean che indica se fare un print dell'IR generato (default `False`) Returns: L'IR generato sotto forma di `str` Raises: StdlibNotFoundError: Se la standard lib non puo' essere trovata """ llvm.initialize() llvm.initialize_native_target() llvm.initialize_native_asmprinter() # Decide l'estensione della stdlib ext = None if platform.system() == 'Windows': ext = 'dll' elif platform.system() == 'Darwin': ext = 'dylib' elif platform.system() == 'Linux': ext = 'so' path = pathlib.Path(__file__).parent.absolute() try: llvm.load_library_permanently( str(path) + "/../../bin/tiny_hi_core.{}".format(ext)) except Exception: print("StdlibNotFoundError: Cannot find the standard library (tiny_hi_core.{})".format(ext)) return (None, None) module = Module() builder = IRBuilder() context = Context(module) entry = None llmod = None try: entry = ast.entry_point() ast.codegen(builder, context) strmod = str(module) if printIR: print(strmod) llmod = llvm.parse_assembly(strmod) except Exception as e: print("Codegen Failed") print("{}: {}".format(type(e).__name__, e)) finally: return (llmod, entry)
def insert_array(module: ir.Module, scope_stack: list, builder: ir.IRBuilder, type: list, num, val_name: tuple, val_value=None): array_type = ir.ArrayType(type_map[type[-1]], num.constant) if builder is None: val = ir.GlobalVariable(module, array_type, module.get_unique_name(val_name[1])) if val_value: val.initializer = val_value else: val = builder.alloca(array_type, name=module.get_unique_name(val_name[1])) # if val_value: # opt_store(builder, val_value, val) scope_stack[-1][val_name[1]] = {'type': 'array', 'value': val} return val
def compile(self, module: ll.Module, builder: ll.IRBuilder): for cname in self._toposort(): cdesc = self.children[cname] cdesc.compile(module, builder) for pin1 in self._conns.get(cname, dict()): for desc2, pin2 in self._conns[cname][pin1]: p1 = self.get_desc(cname).get_pin(pin1) p2 = self.get_desc(desc2).get_pin(pin2) p1 = module.get_global(p1) p2 = module.get_global(p2) v = builder.load(p1) builder.store(v, p2)
def __init__(self): self.module = Module('hello') self._print_int = Function(self.module, FunctionType(void_type, [int_type]), name='_print_int') self.function = Function(self.module, FunctionType(int_type, []), name='main') self.block = self.function.append_basic_block('entry') self.builder = IRBuilder(self.block) self.stack = [] self.vars = {}
def __init__(self): # Perform the basic LLVM initialization. You need the following parts: # # 1. A top-level Module object # 2. A dictionary of global declarations # 3. Initialization of runtime functions (for printing) # self.module = Module('module') # Dictionary that holds all of the global variable/function declarations. # Any declaration in the Wabbit source code is going to get an entry here self.globals = {} # Initialize the runtime library functions (see below) self.declare_runtime_library()
def __init__(self): # Perform the basic LLVM initialization. You need the following parts: # # 1. A top-level Module object # 2. A Function instance in which to insert code # 3. A Builder instance to generate instructions # # Note: For project 5, we don't have any user-defined # functions so we're just going to emit all LLVM code into a top # level function void main() { ... }. This will get changed later. self.module = Module('module') self.globals = {} # Initialize the runtime library functions (see below) self.declare_runtime_library()
def __init__(self, symbol_table) -> None: # Module is an LLVM construct that contains functions and global variables. # In many ways, it is the top-level structure that the LLVM IR uses to contain # code. It will own the memory for all of the IR that we generate, which is why # the codegen() method returns a raw Value*, rather than a unique_ptr<Value>. self.module = Module() # The Builder object is a helper object that makes it easy to generate LLVM # instructions. Instances of the IRBuilder class template keep track of the # current place to insert instructions and has methods to create new instructions. self.builder = None self.symbol_table = symbol_table self.expr_counter = 0 self.str_counter = 0 self.bool_counter = 0 self.printf_counter = 0 self.func_name = "" self.GLOBAL_MEMORY = {}
def insert_string(module: ir.Module, scope_stack: list, builder: ir.IRBuilder, raw_data: str, prt=False): try: global_string = scope_stack[0][raw_data] except KeyError: data = eval('%s' % raw_data) data += '\00' data = data.encode() str_type = ir.ArrayType(char_type, len(data)) const_string = ir.Constant(str_type, bytearray(data)) global_string = ir.GlobalVariable(module, str_type, module.get_unique_name(raw_data)) global_string.initializer = const_string scope_stack[0][raw_data] = global_string if prt: return builder.gep(global_string, [int_type(0), int_type(0)], True) else: return global_string
# hellollvm.py from llvmlite.ir import ( Module, Function, FunctionType, IntType, Constant, IRBuilder ) mod = Module('hello') hello_func = Function(mod, FunctionType(IntType(32), []), name='hello') block = hello_func.append_basic_block('entry') builder = IRBuilder(block) builder.ret(Constant(IntType(32), 37)) # A user-defined function from llvmlite.ir import DoubleType ty_double = DoubleType() dsquared_func = Function(mod, FunctionType(ty_double, [ty_double, ty_double]), name='dsquared') block = dsquared_func.append_basic_block('entry') builder = IRBuilder(block) # Get the function args x, y = dsquared_func.args # Compute temporary values for x*x and y*y xsquared = builder.fmul(x, x) ysquared = builder.fmul(y, y)
# cmp.py # # A sample of executing an integer < in LLVM from llvmlite.ir import (Module, Function, FunctionType, IntType, IRBuilder) mod = Module('example') # Define a function: # # func lessthan(x int, y int) bool { # return x < y; # } # # Note: The result of boolean operations is a 1-bit integer func = Function(mod, FunctionType(IntType(1), [IntType(32), IntType(32)]), name='lessthan') block = func.append_basic_block("entry") builder = IRBuilder(block) # The icmp_signed() instruction is used for all comparisons on # integers. For floating point, use fcmp_ordered(). The compare operation # takes an operator expressed as a string such as '<', '>', '==', # etc. result = builder.icmp_signed('<', func.args[0], func.args[1]) builder.ret(result)
def __init__(self): self.module = Module('module') self.globals = {} self.blocks = {} self.declare_runtime_library()