Beispiel #1
0
    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)
Beispiel #2
0
    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')
Beispiel #3
0
    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()
Beispiel #4
0
    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
Beispiel #5
0
    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')
Beispiel #6
0
 def test_has_a_llvm_representation(self):
     Integer.as_llvm().should.be.equal(ir.IntType(32))
Beispiel #7
0
 def vector_get(self, vector, index):
     val = self.call('vector_get', [vector, index])
     val = self.builder.ptrtoint(val, Integer.as_llvm())
     return val
Beispiel #8
0
    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}')