def f_fabs(mod): '''libc: absolute value of floating-point number''' ret = Type.double() args = [Type.double()] type_ = Type.function(ret, args) return mod.get_or_insert_function(type_, "fabs")
def f_pow(mod): '''libc: power function''' ret = Type.double() args = [Type.double(), Type.double()] type_ = Type.function(ret, args) return mod.get_or_insert_function(type_, "pow")
def CodeGen(self): # Make the function type, eg. double(double,double). funct_type = Type.function(Type.double(), [Type.double()] * len(self.args), False) function = Function.new(g_llvm_module, funct_type, self.name) # If the name conflicted, there was already something with the same name. # If it has a body, don't allow redefinition or reextern. if function.name != self.name: function.delete() function = g_llvm_module.get_function_named(self.name) # If the function already has a body, reject this. if not function.is_declaration: raise RuntimeError('Redefinition of function.') # If the function took a different number of args, reject. if len(function.args) != len(self.args): raise RuntimeError('Redeclaration of a function with different number of args.') # Set names for all arguments and add them to the variables symbol table. for arg, arg_name in zip(function.args, self.args): arg.name = arg_name return function
def code_gen(self): condition = self.condition.code_gen() condition_bool = g_llvm_builder.fcmp(FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcmd') function = g_llvm_builder.basic_block.function then_block = function.append_basic_block('then') else_block = function.append_basic_block('else') merge_block = function.append_basic_block('ifcond') g_llvm_builder.cbranch(condition_bool, then_block, else_block) g_llvm_builder.position_at_end(then_block) then_value = self.then_branch.code_gen() g_llvm_builder.branch(merge_block) then_block = g_llvm_builder.basic_block g_llvm_builder.position_at_end(else_block) else_value = self.else_branch.code_gen() g_llvm_builder.branch(merge_block) else_block = g_llvm_builder.basic_block g_llvm_builder.position_at_end(merge_block) phi = g_llvm_builder.phi(Type.double(), 'iftmp') phi.add_incoming(then_value, then_block) phi.add_incoming(else_value, else_block) return phi
def CodeGen(self): # Make the function type, ex: double(double, double). function_type = Type.function(Type.double(), [Type.double()] * len(self.args), False) function = Function.new(g_llvm_module, function_type, self.name) # If the name conflicts, already something with the same name # If it has a body, don't allow redefinition or re-extern if function.name != self.name: function.delete() function = g_llvm_module.get_function_named(self.name) # If the function already has a body, reject it if not function.is_declaration: raise RuntimeError('Redefinition of function.') # THIS IS ESSENTIALLY FUNCTION OVERLOADING, MAYBE CHANGE IN FUTURE # If function took different number of args, reject it if len(callee.args) != len(self.args): raise RuntimeError('Redeclaration of function with different' + ' number of args') # Set names for all args and add them to var symbol table for arg, arg_name in zip(function.args, self.args): arg.name = arg_name # add args to variable symbol table g_named_values[arg_name] = arg return function
def f_sqrt(mod): '''libc: square root function''' ret = Type.double() args = [Type.double()] type_ = Type.function(ret, args) return mod.get_or_insert_function(type_, "sqrt")
def atan2_f64_impl(context, builder, sig, args): assert len(args) == 2 mod = cgutils.get_module(builder) fnty = Type.function(Type.double(), [Type.double(), Type.double()]) # Workaround atan2() issues under Windows fname = "atan2_fixed" if sys.platform == "win32" else "atan2" fn = mod.get_or_insert_function(fnty, name=fname) return builder.call(fn, args)
def round_impl_f64(context, builder, sig, args): module = cgutils.get_module(builder) fnty = Type.function(Type.double(), [Type.double()]) if utils.IS_PY3: fn = module.get_or_insert_function(fnty, name="numba.round") else: fn = module.get_or_insert_function(fnty, name="round") assert fn.is_declaration return builder.call(fn, args)
def _template(self, mattrs): mod, func = self._build_test_module() ee = self._build_engine(mod, mattrs=mattrs) arg = le.GenericValue.real(Type.double(), 1.234) retval = ee.run_function(func, [arg]) golden = math.sin(1.234) answer = retval.as_real(Type.double()) self.assertTrue(abs(answer - golden) / golden < 1e-5)
def implementer(context, builder, sig, args): [val] = args input_type = sig.args[0] if input_type.signed: fpval = builder.sitofp(val, Type.double()) else: fpval = builder.uitofp(val, Type.double()) sig = signature(types.float64, types.float64) return wrapped_impl(context, builder, sig, [fpval])
def code_gen(self): value = self.right.code_gen() if self.operator.word == '-': if value.type == Type.int(32) or value.type == Type.int(8): return Constant.int(value.type, '0').sub(value) elif value.type == Type.double(): return Constant.real(value.type, '0').fsub(value) else: if value.type == Type.int(32) or value.type == Type.int(8) or Type.int(1): return Constant.int(value.type, '0').icmp(IPRED_EQ, value) elif value.type == Type.double(): return Constant.real(value.type, '0').fcmp(RPRED_UEQ, value)
def body(self, x): mod = self.function.module ret = Type.double() args = [Type.double()] type_ = Type.function(ret, args) func = mod.get_or_insert_function(type_, "round") value = self.builder.call(func, [x.value]) value = CTemp(self, value) self.ret(value.cast(Type.int(32)))
def code_gen(self): value = self.right.code_gen() if self.operator.word == '-': if value.type == Type.int(32) or value.type == Type.int(8): return Constant.int(value.type, '0').sub(value) elif value.type == Type.double(): return Constant.real(value.type, '0').fsub(value) else: if value.type == Type.int(32) or value.type == Type.int( 8) or Type.int(1): return Constant.int(value.type, '0').icmp(IPRED_EQ, value) elif value.type == Type.double(): return Constant.real(value.type, '0').fcmp(RPRED_UEQ, value)
def is_scalar_zero(builder, value): nullval = Constant.null(value.type) if value.type in (Type.float(), Type.double()): isnull = builder.fcmp(lc.FCMP_OEQ, nullval, value) else: isnull = builder.icmp(lc.ICMP_EQ, nullval, value) return isnull
def code(self, context): if self.operator == '=': if not isinstance(self.left, Variable): raise SyntaxError("Destination of '=' must be a variable.") value = self.right.code(context) # RHS code generation variable = context.scope[self.left.name] # Look up the name context.builder.store(value, variable) # Store value, return it return value left = self.left.code(context) right = self.right.code(context) if self.operator == '+': return context.builder.fadd(left, right, 'addtmp') elif self.operator == '-': return context.builder.fsub(left, right, 'subtmp') elif self.operator == '*': return context.builder.fmul(left, right, 'multmp') elif self.operator == '<': ret = context.builder.fcmp(FCMP_ULT, left, right, 'cmptmp') # Convert bool 0 or 1 to double 0.0 or 1.0. return context.builder.uitofp(ret, Type.double(), 'booltmp') else: func = context.module.get_function_named(self.name) return context.builder.call(func, [left, right], 'binop')
def CodeGen(self): # A special case for '=' because we don't want to emit the LHS as an # expression. if self.operator == '=': # Assignment requires the LHS to be an identifier. if not isinstance(self.left, VariableExpressionNode): raise RuntimeError('Destination of "=" must be a variable.') # Codegen the RHS. value = self.right.CodeGen() # Look up the name. variable = g_named_values[self.left.name] # Store the value and return it. g_llvm_builder.store(value, variable) return value left = self.left.CodeGen() right = self.right.CodeGen() if self.operator == '+': return g_llvm_builder.fadd(left, right, 'addtmp') elif self.operator == '-': return g_llvm_builder.fsub(left, right, 'subtmp') elif self.operator == '*': return g_llvm_builder.fmul(left, right, 'multmp') elif self.operator == '<': result = g_llvm_builder.fcmp(FCMP_ULT, left, right, 'cmptmp') # Convert bool 0 or 1 to double 0.0 or 1.0. return g_llvm_builder.uitofp(result, Type.double(), 'booltmp') else: function = g_llvm_module.get_function_named('binary' + self.operator) return g_llvm_builder.call(function, [left, right], 'binop')
def CodeGen(self): print >> stderr, "codegening let node" old_bindings = {} function = G_LLVM_BUILDER.basic_block.function for var_name, var_expression in self.variables.iteritems(): if var_expression is not None: var_value = var_expression.CodeGen() else: var_value = Constant.real(Type.double(), 0) alloca = create_entry_block_alloca(function, var_name) G_LLVM_BUILDER.store(var_value, alloca) old_bindings[var_name] = G_NAMED_VALUES.get(var_name, None) G_NAMED_VALUES[var_name] = alloca body = self.body.CodeGen() for var_name in self.variables: if old_bindings[var_name] is not None: G_NAMED_VALUES[var_name] = old_bindings[var_name] else: del G_NAMED_VALUES[var_name] return body
def code_gen(self): if self.context.parent_context is None: if self.var_name_token.word in self.context.type_table: raise cmexception.RedefineException(self.var_name_token, 'Global Variable') else: t = Helper.get_type(self.typo.word) gv = GlobalVariable.new(g_llvm_module, t, self.var_name_token.word) self.context.type_table[self.var_name_token.word] = t self.context.value_table[self.var_name_token.word] = gv if self.typo.word == 'int': gv.initializer = Constant.int(Type.int(32), 0) elif self.typo.word == 'double': gv.initializer = Constant.real(Type.double(), 0) elif self.typo.word == 'char': gv.initializer = Constant.int(Type.int(8), 0) else: gv.initializer = Constant.stringz("") else: if not self.var_name_token.word in self.context.type_table: t = Helper.get_type(self.typo.word) var_address = g_llvm_builder.alloca( t, name=self.var_name_token.word) self.context.type_table[self.var_name_token.word] = t self.context.value_table[ self.var_name_token.word] = var_address else: raise cmexception.RedefineException(self.var_name_token)
def code_gen(self): if self.context.parent_context is None: if self.var_name_token.word in self.context.type_table: raise cmexception.RedefineException(self.var_name_token, 'Global Variable') else: t = Helper.get_type(self.typo.word) gv = GlobalVariable.new(g_llvm_module, t, self.var_name_token.word) self.context.type_table[self.var_name_token.word] = t self.context.value_table[self.var_name_token.word] = gv if self.typo.word == 'int': gv.initializer = Constant.int(Type.int(32), 0) elif self.typo.word == 'double': gv.initializer = Constant.real(Type.double(), 0) elif self.typo.word == 'char': gv.initializer = Constant.int(Type.int(8), 0) else: gv.initializer = Constant.stringz("") else: if not self.var_name_token.word in self.context.type_table: t = Helper.get_type(self.typo.word) var_address = g_llvm_builder.alloca(t, name=self.var_name_token.word) self.context.type_table[self.var_name_token.word] = t self.context.value_table[self.var_name_token.word] = var_address else: raise cmexception.RedefineException(self.var_name_token)
def CodeGen(self): print >> stderr, "codegening for node" function = G_LLVM_BUILDER.basic_block.function alloca = create_entry_block_alloca(function, self.loop_variable) start_value = self.start.CodeGen() G_LLVM_BUILDER.store(start_value, alloca) loop_block = function.append_basic_block('loop') G_LLVM_BUILDER.branch(loop_block) G_LLVM_BUILDER.position_at_end(loop_block) old_value = G_NAMED_VALUES.get(self.loop_variable, None) G_NAMED_VALUES[self.loop_variable] = alloca self.body.CodeGen() if self.step: step_value = self.step.CodeGen() else: step_value = Constant.real(Type.double(), 1) end_condition = self.end.CodeGen() cur_value = G_LLVM_BUILDER.load(alloca, self.loop_variable) next_value = G_LLVM_BUILDER.fadd(cur_value, step_value, 'nextvar') G_LLVM_BUILDER.store(next_value, alloca) end_condition_bool = G_LLVM_BUILDER.fcmp( FCMP_ONE, end_condition, Constant.real(Type.double(), 0), 'loopcond') after_block = function.append_basic_block('afterloop') G_LLVM_BUILDER.cbranch(end_condition_bool, loop_block, after_block) G_LLVM_BUILDER.position_at_end(after_block) if old_value: G_NAMED_VALUES[self.loop_variable] = old_value else: del G_NAMED_VALUES[self.loop_variable] return Constant.real(Type.double(), 0)
def testValueFromString(self): ty = Type.double() a = Value.const_real(ty, 1.0) b = Value.const_real(ty, "1.0") x, _ = a.get_double_value() y, _ = b.get_double_value() self.assertEqual(x, y)
def is_scalar_neg(builder, value): """is _value_ negative?. Assumes _value_ is signed""" nullval = Constant.null(value.type) if value.type in (Type.float(), Type.double()): isneg = builder.fcmp(lc.FCMP_OLT, value, nullval) else: isneg = builder.icmp(lc.ICMP_SLT, value, nullval) return isneg
def code_gen(self): d = Type.double() i32 = Type.int(32) i1 = Type.int(1) op = self.operator.word left = self.left.code_gen() right = self.right.code_gen() if op == '||' or op == '&&': if left.type != right.type: if left.type == d or right.type == d: left = Helper.auto_cast(g_llvm_builder, left, d) right = Helper.auto_cast(g_llvm_builder, right, d) else: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) if left.type == d: if g_llvm_builder is None: return left.fcmp(RPRED_UEQ, right) else: return g_llvm_builder.fcmp(RPRED_UEQ, left, right) else: if g_llvm_builder is None: return left.icmp(IPRED_EQ, right) else: return g_llvm_builder.icmp(IPRED_EQ, left, right) method = Helper.choose_method(left, op, right) if method[0] == 'f': left = Helper.auto_cast(g_llvm_builder, left, d) right = Helper.auto_cast(g_llvm_builder, right, d) elif method == 'and_' or method == 'or_': if left.type == d or right.type == d: raise cmexception.InvalidOperandException( self.operator, str(left.type), str(right.type)) else: if left.type != right.type: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) else: if left.type != right.type: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) if op == '<' or op == '>' or op == '<=' or op == '>=' or op == '==' or op == '!=': flag = Helper.choose_flag(op, left) if g_llvm_builder is None: return getattr(left, method)(flag, right) else: return getattr(g_llvm_builder, method)(flag, left, right) else: if g_llvm_builder is None: return getattr(left, method)(right) else: return getattr(g_llvm_builder, method)(left, right)
def testFAdd(self): ty = Type.double() a = Value.const_real(ty, 1.0) b = Value.const_real(ty, 1.0) bldr = Builder.create() c = bldr.fadd(a, b, "tmp1") x, l = c.get_double_value() self.assertTrue(x - 2.0 < 0.01 and 2.0 - x > -0.01)
def code_gen(self): d = Type.double() i32 = Type.int(32) i1 = Type.int(1) op = self.operator.word left = self.left.code_gen() right = self.right.code_gen() if op == '||' or op == '&&': if left.type != right.type: if left.type == d or right.type == d: left = Helper.auto_cast(g_llvm_builder, left, d) right = Helper.auto_cast(g_llvm_builder, right, d) else: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) if left.type == d: if g_llvm_builder is None: return left.fcmp(RPRED_UEQ, right) else: return g_llvm_builder.fcmp(RPRED_UEQ, left, right) else: if g_llvm_builder is None: return left.icmp(IPRED_EQ, right) else: return g_llvm_builder.icmp(IPRED_EQ, left, right) method = Helper.choose_method(left, op, right) if method[0] == 'f': left = Helper.auto_cast(g_llvm_builder, left, d) right = Helper.auto_cast(g_llvm_builder, right, d) elif method == 'and_' or method == 'or_': if left.type == d or right.type == d: raise cmexception.InvalidOperandException(self.operator, str(left.type), str(right.type)) else: if left.type != right.type: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) else: if left.type != right.type: left = Helper.auto_cast(g_llvm_builder, left, i32) right = Helper.auto_cast(g_llvm_builder, right, i32) if op == '<' or op == '>' or op == '<=' or op == '>=' or op == '==' or op == '!=': flag = Helper.choose_flag(op, left) if g_llvm_builder is None: return getattr(left, method)(flag, right) else: return getattr(g_llvm_builder, method)(flag, left, right) else: if g_llvm_builder is None: return getattr(left, method)(right) else: return getattr(g_llvm_builder, method)(left, right)
def gen_code(self, module, builder, variables): funct_type = Type.function(Type.double(), [Type.double()] * len(self.args), False) function = Function.new(module, funct_type, self.name) variables = {} for arg, arg_name in zip(function.args, self.args): arg.name = arg_name variables[arg_name] = arg block = function.append_basic_block('entry') builder = Builder.new(block) return_value = self.body.gen_code(module, builder, variables) builder.ret(return_value) function.verify() return function
def get_array_type(typo, length): if typo == 'int': return Type.array(Type.int(32), length) elif typo == 'double': return Type.array(Type.double(), length) elif typo == 'String': ch = Type.int(8) return Type.array(Type.pointer(ch), length) elif typo == 'char': return Type.array(Type.int(8), length)
def template(self, iop, fop): inttys = [Type.int(32), Type.int(64)] flttys = [Type.float(), Type.double()] if iop: for ty in inttys: self.func_template(ty, iop) if fop: for ty in flttys: self.func_template(ty, fop)
def choose_method(left, op, right): method_table = { 'i': {'+': 'add', '-': 'sub', '*': 'mul', '/': 'sdiv', '%': 'srem', '<<': 'shl', '>>': 'lshr', '<': 'icmp', '>': 'icmp', '<=': 'icmp', '>=': 'icmp', '==': 'icmp', '!=': 'icmp' }, 'f': {'+': 'fadd', '-': 'fsub', '*': 'fmul', '/': 'fdiv', '%': 'frem', '<': 'fcmp', '>': 'fcmp', '<=': 'fcmp', '>=': 'fcmp', '==': 'fcmp', '!=': 'fcmp' } } if op == '|': return 'or_' if op == '&': return 'and_' if left.type == Type.double() or right.type == Type.double(): return method_table['f'][op] return method_table['i'][op]
def CodeGen(self): condition = self.condition.CodeGen() # Convert condition to a bool by comparing equal to 0.0. condition_bool = g_llvm_builder.fcmp( FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond') function = g_llvm_builder.basic_block.function # Create blocks for the then and else cases. Insert the 'then' block # at the end of the function. then_block = function.append_basic_block('then') else_block = function.append_basic_block('else') merge_block = function.append_basic_block('ifcond') g_llvm_builder.cbranch(condition_bool, then_block, else_block) # Emit then value. g_llvm_builder.position_at_end(then_block) then_value = self.then_branch.CodeGen() g_llvm_builder.branch(merge_block) # Codegen of 'Then' can change the current block; update then_block # for the PHI node. then_block = g_llvm_builder.basic_block # Emit else block. g_llvm_builder.position_at_end(else_block) else_value = self.else_branch.CodeGen() g_llvm_builder.branch(merge_block) # Codegen of 'Else' can change the current block, update else_block # for the PHI node. else_block = g_llvm_builder.basic_block # Emit merge block. g_llvm_builder.position_at_end(merge_block) phi = g_llvm_builder.phi(Type.double(), 'iftmp') phi.add_incoming(then_value, then_block) phi.add_incoming(else_value, else_block) return phi
def handle_top_level_expression(self): try: function = self.parse_top_level_expr().code_gen() result = ast.g_llvm_executor.run_function(function, []) print('Evaluated to:', result.as_real(Type.double())) except Exception, e: print('Error:', e) try: self.next() except: pass
def HandleTopLevelExpression(self): try: function = self.ParseTopLevelExpr().CodeGen() result = g_llvm_executor.run_function(function, []) print 'Evaluated to:', result.as_real(Type.double()) except Exception, e: raise#print 'Error:', e try: self.Next() # Skip for error recovery. except: pass
def get_type(typo): if typo == 'int' or typo == LexmeType.Integer: return Type.int(32) elif typo == 'double' or typo == LexmeType.Double: return Type.double() elif typo == 'String' or typo == LexmeType.String: ch = Type.int(8) return Type.pointer(ch) elif typo == 'char' or typo == LexmeType.Char: return Type.int(8) elif typo == 'void': return Type.void()
def is_scalar_zero(builder, value): """ Return a predicate representing whether *value* is equal to zero. """ assert not is_pointer(value.type) assert not is_struct(value.type) nullval = Constant.null(value.type) if value.type in (Type.float(), Type.double()): isnull = builder.fcmp(lc.FCMP_OEQ, nullval, value) else: isnull = builder.icmp(lc.ICMP_EQ, nullval, value) return isnull
def gen_code(self, module, builder, variables): condition = self.condition.gen_code(module, builder, variables) condition_bool = builder.fcmp(FCMP_ONE, condition, Constant.real(Type.double(), 0), 'ifcond') function = builder.basic_block.function then_block = function.append_basic_block('then') else_block = function.append_basic_block('else') merge_block = function.append_basic_block('ifcond') builder.cbranch(condition_bool, then_block, else_block) builder.position_at_end(then_block) then_value = self.then_branch.gen_code(module, builder, variables) builder.branch(merge_block) then_block = builder.basic_block builder.position_at_end(else_block) else_value = self.else_branch.gen_code(module, builder, variables) builder.branch(merge_block) else_block = builder.basic_block builder.position_at_end(merge_block) phi = builder.phi(Type.double(), 'iftmp') phi.add_incoming(then_value, then_block) phi.add_incoming(else_value, else_block) return phi
def is_not_scalar_zero(builder, value): """ Return a predicate representin whether a *value* is not equal to zero. not exactly "not is_scalar_zero" because of nans """ assert not is_pointer(value.type) assert not is_struct(value.type) nullval = Constant.null(value.type) if value.type in (Type.float(), Type.double()): isnull = builder.fcmp(lc.FCMP_UNE, nullval, value) else: isnull = builder.icmp(lc.ICMP_NE, nullval, value) return isnull
def get_type_string(ty): i8 = Type.int(8) i32 = Type.int(32) d = Type.double() string = Type.pointer(i8) if ty == i8: return 'char' elif ty == i32: return 'int' elif ty == d: return 'double' elif ty == string: return 'String'
def choose_method(left, op, right): method_table = { 'i': { '+': 'add', '-': 'sub', '*': 'mul', '/': 'sdiv', '%': 'srem', '<<': 'shl', '>>': 'lshr', '<': 'icmp', '>': 'icmp', '<=': 'icmp', '>=': 'icmp', '==': 'icmp', '!=': 'icmp' }, 'f': { '+': 'fadd', '-': 'fsub', '*': 'fmul', '/': 'fdiv', '%': 'frem', '<': 'fcmp', '>': 'fcmp', '<=': 'fcmp', '>=': 'fcmp', '==': 'fcmp', '!=': 'fcmp' } } if op == '|': return 'or_' if op == '&': return 'and_' if left.type == Type.double() or right.type == Type.double(): return method_table['f'][op] return method_table['i'][op]
def force_cast(builder, value, target_type): if value.type != target_type: d = Type.double() i32 = Type.int(32) i8 = Type.int(8) i1 = Type.int(1) if target_type == d: if value.type != d: if builder: value = builder.sitofp(value, d) else: value = value.sitofp(d) elif target_type == i32: if value.type == d: if builder: value = builder.fptosi(value, i32) else: value = value.fptosi(i32) elif value.type == i1: if builder: value = builder.zext(value, i32) else: value = value.zext(i32) else: if builder: value = builder.sext(value, i32) else: value = value.sext(i32) elif target_type == i8: if value.type == d: if builder: value = builder.fptrunc(value, i8) else: value = value.fptrunc(i8) elif value.type == i32: if builder: value = builder.trunc(value, i8) else: value = value.trunc(i8) elif value.type == i1: if builder: value = builder.zext(value, i8) else: value = value.zext(i8) elif target_type == Type.pointer(Type.int(8)): return None return value
def __init__(self, context, builder): """ Note: Maybe called multiple times when lowering a function """ fix_python_api() self.context = context self.builder = builder self.module = builder.basic_block.function.module # Initialize types self.pyobj = self.context.get_argument_type(types.pyobject) self.long = Type.int(ctypes.sizeof(ctypes.c_long) * 8) self.ulonglong = Type.int(ctypes.sizeof(ctypes.c_ulonglong) * 8) self.longlong = self.ulonglong self.double = Type.double() self.py_ssize_t = self.context.get_value_type(types.intp) self.cstring = Type.pointer(Type.int(8))
def printf(builder, format_string, *values): str_const = Constant.stringz(format_string) global_str_const = get_module(builder).add_global_variable( str_const.type, '') global_str_const.initializer = str_const idx = [Constant.int(Type.int(32), 0), Constant.int(Type.int(32), 0)] str_addr = global_str_const.gep(idx) args = [] for v in values: if isinstance(v, int): args.append(Constant.int(Type.int(), v)) elif isinstance(v, float): args.append(Constant.real(Type.double(), v)) functype = Type.function(Type.int(32), [Type.pointer(Type.int(8))], True) fn = get_module(builder).add_function(functype, 'printf') builder.call(fn, [str_addr] + args)
def CodeGen(self): left = self.left.CodeGen() right = self.right.CodeGen() # builder.f<operation> is llvm's builtin floating point operations # TODO: Lookup the string args at the end of each instruction below if self.operator == '+': return g_llvm_builder.fadd(left, right, 'addtmp') elif self.operator == '-': return g_llvm_builder.fsub(left, right, 'subtmp') elif self.operator == '*': return g_llvm_build.fmul(left, right, 'multmp') # This should be changed later on when ints are supported to return 0/1 elif self.operator == '<': result = g_llvm_build.fcmpl(FCMP_ULT, left, right, 'cmptmp') # Convert bool 0/1 to 0.0/1.0 return g_llvm_builder.uitofp(result, Type.double(), 'booltmp') else: raise RuntimeError('Unknown binary operator.')
def llvm_type(type): ty = type.__class__ if ty == Boolean: return Type.int(1) elif ty == Integral: return Type.int(type.bits) elif type == Float32: return Type.float() elif type == Float64: return Type.double() elif ty == Struct: return Type.struct([llvm_type(ftype) for ftype in type.types]) elif ty == Pointer: return Type.pointer(llvm_type(type.base)) elif ty == Function: return Type.function(llvm_type(type.restype), [llvm_type(argtype) for argtype in type.argtypes]) elif ty == Void: return Type.void() else: raise TypeError("Cannot convert type %s" % (type,))
def func_template(self, ty, op): m = Module.new('dofjaa') fnty = Type.function(ty, [ty, ty]) fn = m.add_function(fnty, 'foo') bldr = Builder.new(fn.append_basic_block('')) bldr.ret(getattr(bldr, op)(*fn.args)) engine = EngineBuilder.new(m).mcjit(True).create() ptr = engine.get_pointer_to_function(fn) from ctypes import c_uint32, c_uint64, c_float, c_double, CFUNCTYPE maptypes = { Type.int(32): c_uint32, Type.int(64): c_uint64, Type.float(): c_float, Type.double(): c_double, } cty = maptypes[ty] prototype = CFUNCTYPE(*[cty] * 3) callee = prototype(ptr) callee(12, 23)
def _build_test_module(self): mod = Module.new('test') float = Type.double() mysinty = Type.function(float, [float]) mysin = mod.add_function(mysinty, "mysin") block = mysin.append_basic_block("entry") b = Builder.new(block) sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) cos = Function.intrinsic(mod, lc.INTR_COS, [float]) mysin.args[0].name = "x" x = mysin.args[0] one = Constant.real(float, "1") cosx = b.call(cos, [x], "cosx") cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub sin = b.call(sqrt, [onemc2], "sin") b.ret(sin) return mod, mysin
def llvm_type(type, memo=None): if memo is None: memo = {} if hashable(type) and type in memo: return memo[type] ty = type.__class__ if ty == Boolean: result = Type.int(1) elif ty == Integral: result = Type.int(type.bits) elif type == Float32: result = Type.float() elif type == Float64: result = Type.double() elif ty == Array: result = Type.array(llvm_type(type.base, memo), type.count) elif ty == Vector: result = Type.vector(llvm_type(type.base, memo), type.count) elif ty == Struct: result = handle_struct(type, memo) elif ty == Pointer: if type.base.is_void: return Type.pointer(Type.int(8)) result = Type.pointer(llvm_type(type.base, memo)) elif ty == Function: result = Type.function( llvm_type(type.restype, memo), [llvm_type(argtype, memo) for argtype in type.argtypes], var_arg=type.varargs) elif ty == VoidT: result = Type.void() else: raise TypeError("Cannot convert type %s" % (type,)) memo[type] = result return result
def ref_impl(context, builder, sig, args): [val] = args mod = cgutils.get_module(builder) fnty = Type.function(Type.double(), [Type.double()]) fn = mod.get_or_insert_function(fnty, name=n) return builder.call(fn, (val,))
def pformat_ast(node, include_attrs=False, **kws): return pprint.pformat(ast2tree(node, include_attrs), **kws) def dump(node): return pformat_ast(node) ### == LLVM Codegen == pointer = Type.pointer int_type = Type.int() float_type = Type.float() double_type = Type.double() bool_type = Type.int(1) void_type = Type.void() void_ptr = pointer(Type.int(8)) def array_type(elt_type): return Type.struct( [ pointer(elt_type), # data int_type, # dimensions pointer(int_type), # shape ], name='ndarray_' + str(elt_type))
types.pyobject: Type.pointer(Type.int(8)), types.boolean: Type.int(8), types.uint8: Type.int(8), types.uint16: Type.int(16), types.uint32: Type.int(32), types.uint64: Type.int(64), types.int8: Type.int(8), types.int16: Type.int(16), types.int32: Type.int(32), types.int64: Type.int(64), types.float32: Type.float(), types.float64: Type.double(), } STRUCT_TYPES = { types.complex64: builtins.Complex64, types.complex128: builtins.Complex128, types.range_state32_type: builtins.RangeState32, types.range_iter32_type: builtins.RangeIter32, types.range_state64_type: builtins.RangeState64, types.range_iter64_type: builtins.RangeIter64, types.slice3_type: builtins.Slice, } Status = namedtuple("Status", ("code", "ok", "err", "exc", "none")) RETCODE_OK = Constant.int_signextend(Type.int(), 0)
# | }; | # | }; | # +----------------------------+ # #------------------------------------------------------------------------ # Definitions #------------------------------------------------------------------------ void = Type.void() char = Type.int(8) short = Type.int(16) int = Type.int(32) int64 = Type.int(64) float = Type.float() double = Type.double() int8 = Type.int(8) int8p = Type.pointer(int8) # fountain of free variables free = lambda: iter(letters) def const(n): return Constant.int(int, n) spine = namedtuple('spine', 'name, params, values') value = namedtuple('value', 'name, params') #------------------------------------------------------------------------