def code(self, codegen): lhs = self.lhs rhs = self.rhs left = codegen.visit(lhs) right = codegen.visit(rhs) if left.type == Integer.as_llvm() and right.type == Integer.as_llvm(): return int_ops(codegen.builder, left, right, self) return float_ops(codegen.builder, left, right, self)
def cast(self, from_, to): if from_.type == Integer.as_llvm() and to is Bool: result = self.alloc_and_store(from_, Integer.as_llvm()) result = self.load(result) return self.builder.icmp_signed('!=', result, self.const(0)) if from_.type == Float.as_llvm() and to is Bool: result = self.alloc_and_store(from_, Float.as_llvm()) result = self.load(result) return self.builder.fcmp_ordered('!=', result, self.const(0.0)) raise NotImplementedError('Unsupported cast')
def code(self, codegen): init_block = codegen.add_block('for.init') cond_block = codegen.add_block('for.cond') codegen.loop_cond_blocks.append(cond_block) body_block = codegen.add_block('for.body') end_block = codegen.add_block('for.end') codegen.loop_end_blocks.append(end_block) codegen.branch(init_block) codegen.position_at_end(init_block) vector = codegen.visit(self.iterable) size = codegen.call('vector_size', [vector]) size = codegen.alloc_and_store(size, Integer.as_llvm(), name='size') index = codegen.alloc_and_store(codegen.const(0), Integer.as_llvm(), 'index') codegen.branch(cond_block) codegen.position_at_end(cond_block) should_go_on = codegen.builder.icmp_signed('<', codegen.load(index), codegen.load(size)) codegen.cbranch(should_go_on, body_block, end_block) codegen.position_at_end(body_block) pos = codegen.load(index) val = codegen.vector_get(vector, pos) codegen.assign(self.var.val, val, Integer.as_llvm()) codegen.visit(self.body) if not codegen.is_break: codegen.builder.store(codegen.builder.add(codegen.const(1), pos), index) codegen.branch(cond_block) else: codegen.is_break = False codegen.position_at_end(end_block) codegen.loop_end_blocks.pop() codegen.loop_cond_blocks.pop()
def const(self, val): # has to come first because freaking `isinstance(True, int) == True` if isinstance(val, bool): return ir.Constant(Bool.as_llvm(), val and 1 or 0) if isinstance(val, int): return ir.Constant(Integer.as_llvm(), val) if isinstance(val, float): return ir.Constant(Float.as_llvm(), val) raise NotImplementedError
def _add_builtins(self): malloc_ty = ir.FunctionType(Int8.as_llvm().as_pointer(), [Integer.as_llvm()]) ir.Function(self.module, malloc_ty, 'malloc') free_ty = ir.FunctionType(Any.as_llvm(), [Int8.as_llvm().as_pointer()]) ir.Function(self.module, free_ty, 'free') puts_ty = ir.FunctionType(Integer.as_llvm(), [Int8.as_llvm().as_pointer()]) ir.Function(self.module, puts_ty, 'puts') int_to_string_ty = ir.FunctionType(Int8.as_llvm().as_pointer(), [ Integer.as_llvm(), Int8.as_llvm().as_pointer(), Integer.as_llvm() ]) ir.Function(self.module, int_to_string_ty, 'int_to_string') printf_ty = ir.FunctionType(Integer.as_llvm(), [Int8.as_llvm().as_pointer()], var_arg=True) ir.Function(self.module, printf_ty, 'printf') vector_init_ty = ir.FunctionType(Any.as_llvm(), [List.as_llvm().as_pointer()]) ir.Function(self.module, vector_init_ty, 'vector_init') vector_append_ty = ir.FunctionType( Any.as_llvm(), [List.as_llvm().as_pointer(), Int8.as_llvm().as_pointer()]) ir.Function(self.module, vector_append_ty, 'vector_append') vector_get_ty = ir.FunctionType( Int8.as_llvm().as_pointer(), [List.as_llvm().as_pointer(), Integer.as_llvm()]) ir.Function(self.module, vector_get_ty, 'vector_get') vector_size_ty = ir.FunctionType(Integer.as_llvm(), [List.as_llvm().as_pointer()]) ir.Function(self.module, vector_size_ty, 'vector_size')
def test_has_a_llvm_representation(self): Integer.as_llvm().should.be.equal(ir.IntType(32))
def vector_get(self, vector, index): val = self.call('vector_get', [vector, index]) val = self.builder.ptrtoint(val, Integer.as_llvm()) return val
def code(self, codegen): val = codegen.visit(self.val) typ = None if isinstance(self.val, VarValue): typ = codegen.typetab[self.val.val] if isinstance(self.val, String) or isinstance(typ, PointerType): typ = String elif isinstance(self.val, Integer) or val.type is Integer.as_llvm(): typ = Integer elif isinstance(self.val, Float) or val.type is Float.as_llvm(): typ = Float elif isinstance(self.val, Bool) or val.type is Bool.as_llvm(): typ = Bool if typ is String: # Cast to a i8* pointer char_ty = val.type.pointee.element str_ptr = codegen.bitcast(val, char_ty.as_pointer()) codegen.call('puts', [str_ptr]) return if typ is Integer: number = codegen.alloc_and_store(val, val.type) number_ptr = codegen.load(number) buffer = codegen.alloc(ir.ArrayType(Int8.as_llvm(), 10)) buffer_ptr = codegen.gep(buffer, INDICES, inbounds=True) codegen.call('int_to_string', [number_ptr, buffer_ptr, (codegen.const(10))]) codegen.call('puts', [buffer_ptr]) return if typ is Float: percent_g = String('%g\n').code(codegen) percent_g = codegen.gep(percent_g, INDICES) value = percent_g type_ = Int8.as_llvm().as_pointer() percent_g = codegen.bitcast(value, type_) codegen.call('printf', [percent_g, val]) return if typ is Bool: mod = codegen.module true = codegen.insert_const_string(mod, 'true') true = codegen.gep(true, INDICES) false = codegen.insert_const_string(mod, 'false') false = codegen.gep(false, INDICES) if hasattr(val, 'constant'): if val.constant: val = true else: val = false else: val = codegen.select(val, true, false) codegen.call('printf', [val]) return raise NotImplementedError(f'can\'t print {self.val}')