def code_gen(self): condition = self.expr.code_gen() if str(condition.type) == 'double': condition_value = g_llvm_builder.fcmp( RPRED_UNE, condition, Constant.real(condition.type, 0)) else: condition_value = g_llvm_builder.icmp( IPRED_NE, condition, Constant.int(condition.type, 0)) function = g_llvm_builder.basic_block.function #pre_header_block = g_llvm_builder.basic_block loop_block = function.append_basic_block('while') afterloop_block = function.append_basic_block('afterwhile') g_llvm_builder.cbranch(condition_value, loop_block, afterloop_block) g_llvm_builder.position_at_end(loop_block) for stmt in self.stmts: stmt.code_gen() condition = self.expr.code_gen() if str(condition.type) == 'double': condition_value = g_llvm_builder.fcmp( RPRED_UNE, condition, Constant.real(condition.type, 0)) else: condition_value = g_llvm_builder.icmp( IPRED_NE, condition, Constant.int(condition.type, 0)) g_llvm_builder.cbranch(condition_value, loop_block, afterloop_block) g_llvm_builder.position_at_end(afterloop_block)
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 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 generate(self,*args): assert len(args) == 2 # numerator and denominator builder=self.builder context=self.context tyinputs = self.outer_sig.args tyout = self.outer_sig.return_type tyout_llvm = context.get_data_type(tyout) inner_sig = typing.signature(self.loop_out_types[0], *self.loop_in_types) fn = context.get_function(operator, inner_sig) num, den = args iszero = cgutils.is_scalar_zero(builder, den) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if ((tyinputs[0] in types.real_domain or tyinputs[1] in types.real_domain) or not numpy_support.int_divbyzero_returns_zero) or \ operator=='/': # If num is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(types.float64) shouldretnan = cgutils.is_scalar_zero(builder, num) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) tempres = builder.select(shouldretnan, nan, inf) res_then = context.cast(builder, tempres, types.float64, tyout) elif tyout in types.signed_domain and \ not numpy_support.int_divbyzero_returns_zero: res_then = Constant.int(tyout_llvm, 0x1 << (den.type.width-1)) else: res_then = Constant.null(tyout_llvm) bb_then = builder.basic_block with orelse: # Normal cast_args = [self.context.cast(self.builder, val, inty, outty) for val, inty, outty in zip(args, self.outer_sig.args, self.loop_in_types)] tempres = fn(builder, cast_args) res_else = context.cast(builder, tempres, self.loop_out_types[0], tyout) bb_else = builder.basic_block out = builder.phi(tyout_llvm) out.add_incoming(res_then, bb_then) out.add_incoming(res_else, bb_else) return out
def code_gen(self): function_prototype_and_context = self.prototype.code_gen(True) function_prototype = function_prototype_and_context[0] context = function_prototype_and_context[1] block = function_prototype.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) for i in range(len(self.prototype.args)): context.value_table[self.prototype.args[i][0]] = function_prototype.args[i] if self.body: for stmt in self.body: stmt.code_gen() key = self.prototype.func_name_token.word + '()' expected_return_type = self.context.type_table[key].return_type void_type = Type.void() if expected_return_type == void_type: g_llvm_builder.ret_void() else: if str(expected_return_type) == 'double': g_llvm_builder.ret(Constant.real(expected_return_type, 0)) else: g_llvm_builder.ret(Constant.int(expected_return_type, 0)) # Validate the generated code, checking for consistency. try: function_prototype.verify() g_llvm_pass_manager.run(function_prototype) except: print function_prototype.delete()
def get_constant(self, ty, val): assert not self.is_struct_type(ty) lty = self.get_value_type(ty) if ty == types.none: assert val is None return self.get_dummy_value() elif ty == types.boolean: return Constant.int(Type.int(1), int(val)) elif ty in types.signed_domain: return Constant.int_signextend(lty, val) elif ty in types.unsigned_domain: return Constant.int(lty, val) elif ty in types.real_domain: return Constant.real(lty, val) elif isinstance(ty, types.UniTuple): consts = [self.get_constant(ty.dtype, v) for v in val] return Constant.array(consts[0].type, consts) raise NotImplementedError(ty)
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 op_LOAD_CONST(self, value, target): if isinstance(value, bool): self.stack[target] = Constant.int(bool_type, value) elif isinstance(value, int): self.stack[target] = Constant.int(int_type, value) elif isinstance(value, (float, long)): self.stack[target] = Constant.real(float_type, value) elif isinstance(value, str): # create null terminated string n = 0 content = Constant.stringz(value) # create a unique global constant name, keep hashing # until we find one while True: try: name = CONSTANT_NAMING % (abs(hash(value)) ^ n) break except LLVMException: n += 1 pass globalstr = self.module.add_global_variable(content.type, name) globalstr.initializer = content globalstr.linkage = lc.LINKAGE_LINKONCE_ODR self.stack[target] = globalstr.bitcast(pointer(content.type.element)) else: raise NotImplementedError
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 op_LOAD_CONST(self, value, target): if isinstance(value, bool): self.stack[target] = Constant.int(bool_type, value) elif isinstance(value, int): self.stack[target] = Constant.int(int_type, value) elif isinstance(value, (float, long)): self.stack[target] = Constant.real(float_type, value) elif isinstance(value, str): # create null terminated string n = 0 content = Constant.stringz(value) # create a unique global constant name, keep hashing # until we find one while True: try: name = CONSTANT_NAMING % (abs(hash(value)) ^ n) break except LLVMException: n += 1 pass globalstr = self.module.add_global_variable(content.type, name) globalstr.initializer = content globalstr.linkage = lc.LINKAGE_LINKONCE_ODR self.stack[target] = globalstr.bitcast( pointer(content.type.element)) else: raise NotImplementedError
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 code_gen(self): function_prototype_and_context = self.prototype.code_gen(True) function_prototype = function_prototype_and_context[0] context = function_prototype_and_context[1] block = function_prototype.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) for i in range(len(self.prototype.args)): context.value_table[self.prototype.args[i] [0]] = function_prototype.args[i] if self.body: for stmt in self.body: stmt.code_gen() key = self.prototype.func_name_token.word + '()' expected_return_type = self.context.type_table[key].return_type void_type = Type.void() if expected_return_type == void_type: g_llvm_builder.ret_void() else: if str(expected_return_type) == 'double': g_llvm_builder.ret(Constant.real(expected_return_type, 0)) else: g_llvm_builder.ret(Constant.int(expected_return_type, 0)) # Validate the generated code, checking for consistency. try: function_prototype.verify() g_llvm_pass_manager.run(function_prototype) except: print function_prototype.delete()
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): condition = self.condition.code_gen() if str(condition.type) == 'double': condition_value = g_llvm_builder.fcmp( RPRED_UNE, condition, Constant.real(condition.type, 0)) else: condition_value = g_llvm_builder.icmp( IPRED_NE, condition, Constant.int(condition.type, 0)) function = g_llvm_builder.basic_block.function if_block = function.append_basic_block('if') else_block = function.append_basic_block('else') merge_block = function.append_basic_block('merge') g_llvm_builder.cbranch(condition_value, if_block, else_block) g_llvm_builder.position_at_end(if_block) self.if_node.code_gen() g_llvm_builder.branch(merge_block) g_llvm_builder.position_at_end(else_block) if self.else_node is not None: self.else_node.code_gen() g_llvm_builder.branch(merge_block) g_llvm_builder.position_at_end(merge_block)
def test_mysin(self): if sys.platform == 'win32' and BITS == 32: # float32 support is known to fail on 32-bit Windows return # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) mod = Module.new('test') float = Type.float() 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) #logging.debug(mod) # ; ModuleID = 'test' # # define void @showme() { # entry: # call i32 @llvm.bswap.i32( i32 42 ) ; <i32>:0 [#uses # } # # declare i32 @llvm.bswap.i32(i32) nounwind readnone # # define float @mysin(float %x) { # entry: # %cosx = call float @llvm.cos.f32( float %x ) ; <float # %cos2 = call float @llvm.powi.f32( float %cosx, i32 2 ) # %onemc2 = sub float 1.000000e+00, %cos2 ; <float> [#uses # %sin = call float @llvm.sqrt.f32( float %onemc2 ) # ret float %sin # } # # declare float @llvm.sqrt.f32(float) nounwind readnone # # declare float @llvm.powi.f32(float, i32) nounwind readnone # # declare float @llvm.cos.f32(float) nounwind readnone # let's run the function ee = le.ExecutionEngine.new(mod) arg = le.GenericValue.real(Type.float(), 1.234) retval = ee.run_function(mysin, [arg]) golden = math.sin(1.234) answer = retval.as_real(Type.float()) self.assertTrue(abs(answer-golden)/golden < 1e-5)
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 op_UNARY_NEGATIVE(self, ty, source, target): if ty == btypes.int_type: self.stack[target] = self.builder.sub(Constant.int(int_type, 0), self.stack[source], target) elif ty == btypes.float_type: self.stack[target] = self.builder.fsub( Constant.real(float_type, 0.0), self.stack[source], target)
def visit_LitInt(self, node): ty = self.specialize(node) if ty is double_type: return Constant.real(double_type, node.n) elif ty == int_type: return Constant.int(int_type, node.n) elif ty == int64_type: return Constant.int(int64_type, node.n)
def test_mysin(self): # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) mod = Module.new('test') float = Type.float() 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) #logging.debug(mod) # ; ModuleID = 'test' # # define void @showme() { # entry: # call i32 @llvm.bswap.i32( i32 42 ) ; <i32>:0 [#uses # } # # declare i32 @llvm.bswap.i32(i32) nounwind readnone # # define float @mysin(float %x) { # entry: # %cosx = call float @llvm.cos.f32( float %x ) ; <float # %cos2 = call float @llvm.powi.f32( float %cosx, i32 2 ) # %onemc2 = sub float 1.000000e+00, %cos2 ; <float> [#uses # %sin = call float @llvm.sqrt.f32( float %onemc2 ) # ret float %sin # } # # declare float @llvm.sqrt.f32(float) nounwind readnone # # declare float @llvm.powi.f32(float, i32) nounwind readnone # # declare float @llvm.cos.f32(float) nounwind readnone # let's run the function ee = le.ExecutionEngine.new(mod) arg = le.GenericValue.real(Type.float(), 1.234) retval = ee.run_function(mysin, [arg]) golden = math.sin(1.234) answer = retval.as_real(Type.float()) self.assertTrue(abs(answer - golden) / golden < 1e-5)
def const(self, val): if isinstance(val, (int, long)): return Constant.int(int_type, val) elif isinstance(val, float): return Constant.real(double_type, val) elif isinstance(val, bool): return Constant.int(bool_type, int(val)) elif isinstance(val, str): return Constant.stringz(val) else: raise NotImplementedError
def const(self, val): if isinstance(val, (int, long)): return Constant.int(int_type, val) elif isinstance(val, float): return Constant.real(float_type, val) elif isinstance(val, bool): return Constant.int(bool_type, int(val)) elif isinstance(val, str): return Constant.stringz(val) else: raise NotImplementedError
def test_struct_extract_value_2d(self): ta = Type.struct([Type.int(32), Type.float()]) tb = Type.struct([ta, Type.float()]) m = Module.new('') f = m.add_function(Type.function(Type.void(), []), "foo") b = Builder.new(f.append_basic_block('')) v = Constant.undef(tb) ins = b.insert_value(v, Constant.real(Type.float(), 1.234), [0, 1]) ext = b.extract_value(ins, [0, 1]) b.ret_void() m.verify() self.assertEqual(str(ext), 'float 0x3FF3BE76C0000000')
def is_true(self, builder, typ, val): if typ in types.integer_domain: return builder.icmp(lc.ICMP_NE, val, Constant.null(val.type)) elif typ in types.real_domain: return builder.fcmp(lc.FCMP_ONE, val, Constant.real(val.type, 0)) elif typ in types.complex_domain: cmplx = self.make_complex(typ)(self, builder, val) fty = types.float32 if typ == types.complex64 else types.float64 real_istrue = self.is_true(builder, fty, cmplx.real) imag_istrue = self.is_true(builder, fty, cmplx.imag) return builder.or_(real_istrue, imag_istrue) raise NotImplementedError("is_true", val, typ)
def timedelta_over_timedelta(context, builder, sig, args): [va, vb] = args [ta, tb] = sig.args not_nan = are_not_nat(builder, [va, vb]) ll_ret_type = context.get_value_type(sig.return_type) ret = cgutils.alloca_once(builder, ll_ret_type, name='ret') builder.store(Constant.real(ll_ret_type, float('nan')), ret) with cgutils.if_likely(builder, not_nan): va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb) va = builder.sitofp(va, ll_ret_type) vb = builder.sitofp(vb, ll_ret_type) builder.store(builder.fdiv(va, vb), ret) return builder.load(ret)
def op_UNARY_NEGATIVE(self, ty, source, target): if ty == btypes.int_type: self.stack[target] = self.builder.sub( Constant.int(int_type, 0), self.stack[source], target ) elif ty == btypes.float_type: self.stack[target] = self.builder.fsub( Constant.real(float_type, 0.0), self.stack[source], target )
def real_sign_impl(context, builder, sig, args): [x] = args POS = Constant.real(x.type, 1) NEG = Constant.real(x.type, -1) ZERO = Constant.real(x.type, 0) presult = cgutils.alloca_once(builder, x.type) is_pos = builder.fcmp(lc.FCMP_OGT, x, ZERO) is_neg = builder.fcmp(lc.FCMP_OLT, x, ZERO) with cgutils.ifelse(builder, is_pos) as (gt_zero, not_gt_zero): with gt_zero: builder.store(POS, presult) with not_gt_zero: with cgutils.ifelse(builder, is_neg) as (lt_zero, not_lt_zero): with lt_zero: builder.store(NEG, presult) with not_lt_zero: # For both NaN and 0, the result of sign() is simply # the input value. builder.store(x, presult) return builder.load(presult)
def code_gen(self): condition = self.expr.code_gen() if str(condition.type) == 'double': condition_value = g_llvm_builder.fcmp(RPRED_UNE, condition, Constant.real(condition.type, 0)) else: condition_value = g_llvm_builder.icmp(IPRED_NE, condition, Constant.int(condition.type, 0)) function = g_llvm_builder.basic_block.function #pre_header_block = g_llvm_builder.basic_block loop_block = function.append_basic_block('while') afterloop_block = function.append_basic_block('afterwhile') g_llvm_builder.cbranch(condition_value, loop_block, afterloop_block) g_llvm_builder.position_at_end(loop_block) for stmt in self.stmts: stmt.code_gen() condition = self.expr.code_gen() if str(condition.type) == 'double': condition_value = g_llvm_builder.fcmp(RPRED_UNE, condition, Constant.real(condition.type, 0)) else: condition_value = g_llvm_builder.icmp(IPRED_NE, condition, Constant.int(condition.type, 0)) g_llvm_builder.cbranch(condition_value, loop_block, afterloop_block) g_llvm_builder.position_at_end(afterloop_block)
def real_sign_impl(context, builder, sig, args): [x] = args POS = Constant.real(x.type, 1) NEG = Constant.real(x.type, -1) ZERO = Constant.real(x.type, 0) cmp_zero = builder.fcmp(lc.FCMP_OEQ, x, ZERO) cmp_pos = builder.fcmp(lc.FCMP_OGT, x, ZERO) presult = builder.alloca(x.type) bb_zero = cgutils.append_basic_block(builder, ".zero") bb_postest = cgutils.append_basic_block(builder, ".postest") bb_pos = cgutils.append_basic_block(builder, ".pos") bb_neg = cgutils.append_basic_block(builder, ".neg") bb_exit = cgutils.append_basic_block(builder, ".exit") builder.cbranch(cmp_zero, bb_zero, bb_postest) with cgutils.goto_block(builder, bb_zero): builder.store(ZERO, presult) builder.branch(bb_exit) with cgutils.goto_block(builder, bb_postest): builder.cbranch(cmp_pos, bb_pos, bb_neg) with cgutils.goto_block(builder, bb_pos): builder.store(POS, presult) builder.branch(bb_exit) with cgutils.goto_block(builder, bb_neg): builder.store(NEG, presult) builder.branch(bb_exit) builder.position_at_end(bb_exit) return builder.load(presult)
def complex_negate_impl(context, builder, sig, args): [typ] = sig.args [val] = args cmplxcls = context.make_complex(typ) cmplx = cmplxcls(context, builder, val) real = cmplx.real imag = cmplx.imag zero = Constant.real(real.type, 0) res = cmplxcls(context, builder) res.real = builder.fsub(zero, real) res.imag = builder.fsub(zero, imag) return res._getvalue()
def code_gen(self): if self.constant_token.lexme_type == LexmeType.Integer: return Constant.int(Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.Double: return Constant.real(Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.String: s = self.constant_token.word.strip('"') global constant_string_num global_string = GlobalVariable.new(g_llvm_module, Type.array(Type.int(8), len(s) + 1), ".str%d" % constant_string_num) constant_string_num += 1 global_string.initializer = Constant.stringz(s) return global_string elif self.constant_token.lexme_type == LexmeType.Char: ascii = ord(self.constant_token.word.strip("'")) return Constant.int(Helper.get_type(self.constant_token.lexme_type), ascii)
def codegen_for_data(expr): if isinstance(expr, int) or isinstance(expr, float): return Constant.real(Type.double(), expr) elif isinstance(expr, Symbol): return CallExpressionNode("intern", [StringExpressionNode(expr.name)]).CodeGen() elif expr is None: return CallExpressionNode("intern", [StringExpressionNode("nil")]).CodeGen() elif isinstance(expr, Cons): return CallExpressionNode("cons", [QuoteExpressionNode(expr.car), QuoteExpressionNode(expr.cdr)]).CodeGen() else: raise RuntimeError("Don't know how to codewalk following data type %s" % type(expr))
def op_LOAD_CONST(self, value, target): if isinstance(value, bool): self.stack[target] = Constant.int(bool_type, value) elif isinstance(value, int): self.stack[target] = Constant.int(int_type, value) elif isinstance(value, (float, int)): self.stack[target] = Constant.real(float_type, value) elif isinstance(value, str): content = Constant.stringz(value) name = CONSTANT_NAMING % self.string_count self.string_count += 1 globalstr = self.module.add_global_variable(content.type, name) globalstr.initializer = content globalstr.linkage = lc.LINKAGE_LINKONCE_ODR self.stack[target] = globalstr.bitcast(pointer(content.type.element)) else: raise NotImplementedError
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 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): 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 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 _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 codegen_expr(builder, expr): kind = expr[0] if kind == 'number': number = expr[1] return Constant.real(double_type, number) elif kind == 'variable': name = expr[1] try: return named_values[name] except KeyError: raise CodegenError("unknown variable name") elif kind == 'binary': op, lhs, rhs = expr[1], expr[2], expr[3] lhs_val = codegen_expr(builder, lhs) rhs_val = codegen_expr(builder, rhs) if op == '+': return builder.add(lhs_val, rhs_val, 'addtmp') elif op == '-': return builder.sub(lhs_val, rhs_val, 'subtmp') elif op == '*': return builder.mul(lhs_val, rhs_val, 'multmp') elif op == '<': i = builder.fcmp(FCMP_ULT, lhs_val, rhs_val, 'cmptmp') return builder.uitofp(i, 'booltmp') else: raise CodegenError("invalid binary operator") elif kind == 'call': name, args = expr[1], expr[2] try: callee = Function.get(the_module, name) except LLVMException: raise CodegenError("unknown function referenced") if len(callee.args) != len(args): raise CodegenError("incorrect # arguments passed") arg_vals = [] for arg in args: arg_val = codegen_expr(builder, arg) arg_vals.append(arg_val) return builder.call(callee, arg_vals, 'calltmp')
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 codegen_expr(builder, expr): kind = expr[0] if kind == "number": number = expr[1] return Constant.real(double_type, number) elif kind == "variable": name = expr[1] try: return named_values[name] except KeyError: raise CodegenError("unknown variable name") elif kind == "binary": op, lhs, rhs = expr[1], expr[2], expr[3] lhs_val = codegen_expr(builder, lhs) rhs_val = codegen_expr(builder, rhs) if op == "+": return builder.add(lhs_val, rhs_val, "addtmp") elif op == "-": return builder.sub(lhs_val, rhs_val, "subtmp") elif op == "*": return builder.mul(lhs_val, rhs_val, "multmp") elif op == "<": i = builder.fcmp(FCMP_ULT, lhs_val, rhs_val, "cmptmp") return builder.uitofp(i, "booltmp") else: raise CodegenError("invalid binary operator") elif kind == "call": name, args = expr[1], expr[2] try: callee = Function.get(the_module, name) except LLVMException: raise CodegenError("unknown function referenced") if len(callee.args) != len(args): raise CodegenError("incorrect # arguments passed") arg_vals = [] for arg in args: arg_val = codegen_expr(builder, arg) arg_vals.append(arg_val) return builder.call(callee, arg_vals, "calltmp")
def code(self, context): condition = self.condition.code(context) zero = Constant.real(Type.double(), 0) boolean = context.builder.fcmp(FCMP_ONE, condition, zero, 'ifcond') func = context.builder.basic_block.function # Create blocks for the then and else cases. Insert the 'then' block # at the end of the function. then_block = func.append_basic_block('then') else_block = func.append_basic_block('else') merge_block = func.append_basic_block('ifcont') context.builder.cbranch(boolean, then_block, else_block) # Emit then value. context.builder.position_at_end(then_block) then_value = self.then_branch.code(context) context.builder.branch(merge_block) # code generation of 'Then' can change the current block; update # then_block or the PHI node. then_block = context.builder.basic_block # Emit else block. context.builder.position_at_end(else_block) else_value = self.else_branch.code(context) context.builder.branch(merge_block) # code generation of 'Else' can change the current block, update # else_block or the PHI node. else_block = context.builder.basic_block # Emit merge block. context.builder.position_at_end(merge_block) phi = context.builder.phi(Type.double(), 'iftmp') phi.add_incoming(then_value, then_block) phi.add_incoming(else_value, else_block) return phi
def code(self, context): old_bindings = {} function = context.builder.basic_block.function # Register all variables and emit their initializer. for name, expression in self.variables.items(): # Emit the initializer before adding the variable to scope, this # prevents the initializer from referencing the variable itself, # d permits stuff like this: # var a = 1 in # var a = a in ... # refers to outer 'a'. if expression is not None: value = expression.code(context) else: value = Constant.real(Type.double(), 0) alloca = create_alloca_block(function, name) context.builder.store(value, alloca) # Remember the old variable binding so that we can restore the # binding when we unrecurse. old_bindings[name] = context.scope.get(name, None) # Remember this binding. context.scope[name] = alloca # Codegen the body, now that all vars are in scope. body = self.body.code(context) # Pop all our variables from scope. for name in self.variables: if old_bindings[name] is not None: context.scope[name] = old_bindings[name] else: del context.scope[name] # Return the body computation. return body
def CodeGen(self): old_bindings = {} function = g_llvm_builder.basic_block.function # Register all variables and emit their initializer. for var_name, var_expression in self.variables.iteritems(): # Emit the initializer before adding the variable to scope, this prevents # the initializer from referencing the variable itself, and permits stuff # like this: # var a = 1 in # var a = a in ... # refers to outer 'a'. if var_expression is not None: var_value = var_expression.CodeGen() else: var_value = Constant.real(Type.double(), 0) alloca = CreateEntryBlockAlloca(function, var_name) g_llvm_builder.store(var_value, alloca) # Remember the old variable binding so that we can restore the binding # when we unrecurse. old_bindings[var_name] = g_named_values.get(var_name, None) # Remember this binding. g_named_values[var_name] = alloca # Codegen the body, now that all vars are in scope. body = self.body.CodeGen() # Pop all our variables from scope. 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 the body computation. return body
def code_gen(self): if self.constant_token.lexme_type == LexmeType.Integer: return Constant.int( Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.Double: return Constant.real( Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.String: s = self.constant_token.word.strip('"') global constant_string_num global_string = GlobalVariable.new( g_llvm_module, Type.array(Type.int(8), len(s) + 1), ".str%d" % constant_string_num) constant_string_num += 1 global_string.initializer = Constant.stringz(s) return global_string elif self.constant_token.lexme_type == LexmeType.Char: ascii = ord(self.constant_token.word.strip("'")) return Constant.int( Helper.get_type(self.constant_token.lexme_type), ascii)
def real_divmod_func_body(context, builder, vx, wx): # Reference Objects/floatobject.c # # float_divmod(PyObject *v, PyObject *w) # { # double vx, wx; # double div, mod, floordiv; # CONVERT_TO_DOUBLE(v, vx); # CONVERT_TO_DOUBLE(w, wx); # mod = fmod(vx, wx); # /* fmod is typically exact, so vx-mod is *mathematically* an # exact multiple of wx. But this is fp arithmetic, and fp # vx - mod is an approximation; the result is that div may # not be an exact integral value after the division, although # it will always be very close to one. # */ # div = (vx - mod) / wx; # if (mod) { # /* ensure the remainder has the same sign as the denominator */ # if ((wx < 0) != (mod < 0)) { # mod += wx; # div -= 1.0; # } # } # else { # /* the remainder is zero, and in the presence of signed zeroes # fmod returns different results across platforms; ensure # it has the same sign as the denominator; we'd like to do # "mod = wx * 0.0", but that may get optimized away */ # mod *= mod; /* hide "mod = +0" from optimizer */ # if (wx < 0.0) # mod = -mod; # } # /* snap quotient to nearest integral value */ # if (div) { # floordiv = floor(div); # if (div - floordiv > 0.5) # floordiv += 1.0; # } # else { # /* div is zero - get the same sign as the true quotient */ # div *= div; /* hide "div = +0" from optimizers */ # floordiv = div * vx / wx; /* zero w/ sign of vx/wx */ # } # return Py_BuildValue("(dd)", floordiv, mod); # } pmod = cgutils.alloca_once(builder, vx.type) pdiv = cgutils.alloca_once(builder, vx.type) pfloordiv = cgutils.alloca_once(builder, vx.type) mod = builder.frem(vx, wx) div = builder.fdiv(builder.fsub(vx, mod), wx) builder.store(mod, pmod) builder.store(div, pdiv) ZERO = Constant.real(vx.type, 0) ONE = Constant.real(vx.type, 1) mod_istrue = builder.fcmp(lc.FCMP_ONE, mod, ZERO) wx_ltz = builder.fcmp(lc.FCMP_OLT, wx, ZERO) mod_ltz = builder.fcmp(lc.FCMP_OLT, mod, ZERO) with cgutils.ifthen(builder, mod_istrue): wx_ltz_ne_mod_ltz = builder.icmp(lc.ICMP_NE, wx_ltz, mod_ltz) with cgutils.ifthen(builder, wx_ltz_ne_mod_ltz): mod = builder.fadd(mod, wx) div = builder.fsub(div, ONE) builder.store(mod, pmod) builder.store(div, pdiv) del mod del div with cgutils.ifnot(builder, mod_istrue): mod = builder.load(pmod) mod = builder.fmul(mod, mod) builder.store(mod, pmod) del mod with cgutils.ifthen(builder, wx_ltz): mod = builder.load(pmod) mod = builder.fsub(ZERO, mod) builder.store(mod, pmod) del mod div = builder.load(pdiv) div_istrue = builder.fcmp(lc.FCMP_ONE, div, ZERO) with cgutils.ifthen(builder, div_istrue): module = cgutils.get_module(builder) floorfn = lc.Function.intrinsic(module, lc.INTR_FLOOR, [wx.type]) floordiv = builder.call(floorfn, [div]) floordivdiff = builder.fsub(div, floordiv) floordivincr = builder.fadd(floordiv, ONE) HALF = Constant.real(wx.type, 0.5) pred = builder.fcmp(lc.FCMP_OGT, floordivdiff, HALF) floordiv = builder.select(pred, floordivincr, floordiv) builder.store(floordiv, pfloordiv) with cgutils.ifnot(builder, div_istrue): div = builder.fmul(div, div) builder.store(div, pdiv) floordiv = builder.fdiv(builder.fmul(div, vx), wx) builder.store(floordiv, pfloordiv) return builder.load(pfloordiv), builder.load(pmod)
def impl(context, builder, sig, args): [tyvx, tywy, tyout] = sig.args [vx, wy, out] = args assert tyvx.dtype == tywy.dtype ndim = tyvx.ndim xary = context.make_array(tyvx)(context, builder, vx) yary = context.make_array(tywy)(context, builder, wy) oary = context.make_array(tyout)(context, builder, out) intpty = context.get_value_type(types.intp) # TODO handle differing shape by mimicking broadcasting loopshape = cgutils.unpack_tuple(builder, xary.shape, ndim) xyo_shape = [cgutils.unpack_tuple(builder, ary.shape, ndim) for ary in (xary, yary, oary)] xyo_strides = [cgutils.unpack_tuple(builder, ary.strides, ndim) for ary in (xary, yary, oary)] xyo_data = [ary.data for ary in (xary, yary, oary)] xyo_layout = [ty.layout for ty in (tyvx, tywy, tyout)] with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: [px, py, po] = [cgutils.get_item_pointer2(builder, data=data, shape=shape, strides=strides, layout=layout, inds=indices) for data, shape, strides, layout in zip(xyo_data, xyo_shape, xyo_strides, xyo_layout)] x = builder.load(px) y = builder.load(py) if divbyzero: # Handle division iszero = cgutils.is_scalar_zero(builder, y) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if tyout.dtype in types.real_domain: # If x is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(tyout.dtype) shouldretnan = cgutils.is_scalar_zero(builder, x) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) res = builder.select(shouldretnan, nan, inf) elif (tyout.dtype in types.signed_domain and not numpy_support.int_divbyzero_returns_zero): res = Constant.int(y.type, 0x1 << (y.type.width-1)) else: res = Constant.null(y.type) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) with orelse: # Normal res = core(builder, (x, y)) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) else: # Handle other operations res = core(builder, (x, y)) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) return out
def CodeGen(self): # Here is where things can be changed for types other than double # This returns a 'ConstantFloatingPoint' number from the # llvm.core.Constant class return Constant.real(Type.double(), self.value)
def float_usub(builder, val): return builder.fsub(Constant.real(val.type, 0), val)
def float_not(builder, val): return builder.fcmp(lc.FCMP_OEQ, val, Constant.real(val.type, 0))
def impl(context, builder, sig, args): [tyinp1, tyinp2, tyout] = sig.args [inp1, inp2, out] = args if isinstance(tyinp1, types.Array): scalar_inp1 = False scalar_tyinp1 = tyinp1.dtype inp1_ndim = tyinp1.ndim elif tyinp1 in types.number_domain: scalar_inp1 = True scalar_tyinp1 = tyinp1 inp1_ndim = 1 else: raise TypeError('unknown type for first input operand') if isinstance(tyinp2, types.Array): scalar_inp2 = False scalar_tyinp2 = tyinp2.dtype inp2_ndim = tyinp2.ndim elif tyinp2 in types.number_domain: scalar_inp2 = True scalar_tyinp2 = tyinp2 inp2_ndim = 1 else: raise TypeError('unknown type for second input operand') out_ndim = tyout.ndim if asfloat: promote_type = types.float64 elif scalar_tyinp1 in types.real_domain or \ scalar_tyinp2 in types.real_domain: promote_type = types.float64 elif scalar_tyinp1 in types.signed_domain or \ scalar_tyinp2 in types.signed_domain: promote_type = types.int64 else: promote_type = types.uint64 result_type = promote_type # Temporary hack for __ftol2 llvm bug. Don't allow storing # float results in uint64 array on windows. if result_type in types.real_domain and \ tyout.dtype is types.uint64 and \ sys.platform.startswith('win32'): raise TypeError('Cannot store result in uint64 array') sig = typing.signature(result_type, promote_type, promote_type) if not scalar_inp1: i1ary = context.make_array(tyinp1)(context, builder, inp1) if not scalar_inp2: i2ary = context.make_array(tyinp2)(context, builder, inp2) oary = context.make_array(tyout)(context, builder, out) fnwork = context.get_function(funckey, sig) intpty = context.get_value_type(types.intp) if not scalar_inp1: inp1_shape = cgutils.unpack_tuple(builder, i1ary.shape, inp1_ndim) inp1_strides = cgutils.unpack_tuple(builder, i1ary.strides, inp1_ndim) inp1_data = i1ary.data inp1_layout = tyinp1.layout if not scalar_inp2: inp2_shape = cgutils.unpack_tuple(builder, i2ary.shape, inp2_ndim) inp2_strides = cgutils.unpack_tuple(builder, i2ary.strides, inp2_ndim) inp2_data = i2ary.data inp2_layout = tyinp2.layout out_shape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) out_strides = cgutils.unpack_tuple(builder, oary.strides, out_ndim) out_data = oary.data out_layout = tyout.layout ZERO = Constant.int(Type.int(intpty.width), 0) ONE = Constant.int(Type.int(intpty.width), 1) inp1_indices = None if not scalar_inp1: inp1_indices = [] for i in range(inp1_ndim): x = builder.alloca(Type.int(intpty.width)) builder.store(ZERO, x) inp1_indices.append(x) inp2_indices = None if not scalar_inp2: inp2_indices = [] for i in range(inp2_ndim): x = builder.alloca(Type.int(intpty.width)) builder.store(ZERO, x) inp2_indices.append(x) loopshape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: # Increment input indices. # Since the output dimensions are already being incremented, # we'll use that to set the input indices. In order to # handle broadcasting, any input dimension of size 1 won't be # incremented. def build_increment_blocks(inp_indices, inp_shape, inp_ndim, inp_num): bb_inc_inp_index = [cgutils.append_basic_block(builder, '.inc_inp{0}_index{1}'.format(inp_num, str(i))) for i in range(inp_ndim)] bb_end_inc_index = cgutils.append_basic_block(builder, '.end_inc{0}_index'.format(inp_num)) builder.branch(bb_inc_inp_index[0]) for i in range(inp_ndim): with cgutils.goto_block(builder, bb_inc_inp_index[i]): # If the shape of this dimension is 1, then leave the # index at 0 so that this dimension is broadcasted over # the corresponding input and output dimensions. cond = builder.icmp(ICMP_UGT, inp_shape[i], ONE) with cgutils.ifthen(builder, cond): builder.store(indices[out_ndim-inp_ndim+i], inp_indices[i]) if i + 1 == inp_ndim: builder.branch(bb_end_inc_index) else: builder.branch(bb_inc_inp_index[i+1]) builder.position_at_end(bb_end_inc_index) if not scalar_inp1: build_increment_blocks(inp1_indices, inp1_shape, inp1_ndim, '1') if not scalar_inp2: build_increment_blocks(inp2_indices, inp2_shape, inp2_ndim, '2') if scalar_inp1: x = inp1 else: inds = [builder.load(index) for index in inp1_indices] px = cgutils.get_item_pointer2(builder, data=inp1_data, shape=inp1_shape, strides=inp1_strides, layout=inp1_layout, inds=inds) x = builder.load(px) if scalar_inp2: y = inp2 else: inds = [builder.load(index) for index in inp2_indices] py = cgutils.get_item_pointer2(builder, data=inp2_data, shape=inp2_shape, strides=inp2_strides, layout=inp2_layout, inds=inds) y = builder.load(py) po = cgutils.get_item_pointer2(builder, data=out_data, shape=out_shape, strides=out_strides, layout=out_layout, inds=indices) if divbyzero: # Handle division iszero = cgutils.is_scalar_zero(builder, y) with cgutils.ifelse(builder, iszero, expect=False) as (then, orelse): with then: # Divide by zero if (scalar_tyinp1 in types.real_domain or scalar_tyinp2 in types.real_domain) or \ not numpy_support.int_divbyzero_returns_zero: # If y is float and is 0 also, return Nan; else # return Inf outltype = context.get_data_type(result_type) shouldretnan = cgutils.is_scalar_zero(builder, x) nan = Constant.real(outltype, float("nan")) inf = Constant.real(outltype, float("inf")) tempres = builder.select(shouldretnan, nan, inf) res = context.cast(builder, tempres, result_type, tyout.dtype) elif tyout.dtype in types.signed_domain and \ not numpy_support.int_divbyzero_returns_zero: res = Constant.int(context.get_data_type(tyout.dtype), 0x1 << (y.type.width-1)) else: res = Constant.null(context.get_data_type(tyout.dtype)) assert res.type == po.type.pointee, \ (str(res.type), str(po.type.pointee)) builder.store(res, po) with orelse: # Normal d_x = context.cast(builder, x, scalar_tyinp1, promote_type) d_y = context.cast(builder, y, scalar_tyinp2, promote_type) tempres = fnwork(builder, [d_x, d_y]) res = context.cast(builder, tempres, result_type, tyout.dtype) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) else: # Handle non-division operations d_x = context.cast(builder, x, scalar_tyinp1, promote_type) d_y = context.cast(builder, y, scalar_tyinp2, promote_type) tempres = fnwork(builder, [d_x, d_y]) res = context.cast(builder, tempres, result_type, tyout.dtype) assert res.type == po.type.pointee, (res.type, po.type.pointee) builder.store(res, po) return out