Ejemplo n.º 1
0
    def o_roundx(self, target_bits, builder):
        if builder is None:
            return VInt(target_bits)
        else:
            r = VInt(64)
            a, b = self._nd(builder)
            h_b = builder.ashr(b, ll.Constant(ll.IntType(64), 1))

            function = builder.basic_block.function
            add_block = function.append_basic_block("fr_add")
            sub_block = function.append_basic_block("fr_sub")
            merge_block = function.append_basic_block("fr_merge")

            condition = builder.icmp_signed(
                "<", a, ll.Constant(ll.IntType(64), 0))
            builder.cbranch(condition, sub_block, add_block)

            builder.position_at_end(add_block)
            a_add = builder.add(a, h_b)
            builder.branch(merge_block)
            builder.position_at_end(sub_block)
            a_sub = builder.sub(a, h_b)
            builder.branch(merge_block)

            builder.position_at_end(merge_block)
            a = builder.phi(ll.IntType(64))
            a.add_incoming(a_add, add_block)
            a.add_incoming(a_sub, sub_block)
            r.auto_store(builder, builder.sdiv(a, b))
            return r.o_intx(target_bits, builder)
Ejemplo n.º 2
0
def _signnum(builder, a, b):
    function = builder.basic_block.function
    orig_block = builder.basic_block
    swap_block = function.append_basic_block("sn_swap")
    merge_block = function.append_basic_block("sn_merge")

    condition = builder.icmp_signed(
        "<", b, ll.Constant(ll.IntType(64), 0))
    builder.cbranch(condition, swap_block, merge_block)

    builder.position_at_end(swap_block)
    minusone = ll.Constant(ll.IntType(64), -1)
    a_swp = builder.mul(minusone, a)
    b_swp = builder.mul(minusone, b)
    builder.branch(merge_block)

    builder.position_at_end(merge_block)
    a_phi = builder.phi(ll.IntType(64))
    a_phi.add_incoming(a, orig_block)
    a_phi.add_incoming(a_swp, swap_block)
    b_phi = builder.phi(ll.IntType(64))
    b_phi.add_incoming(b, orig_block)
    b_phi.add_incoming(b_swp, swap_block)

    return a_phi, b_phi
Ejemplo n.º 3
0
    def _build_rpc(self, args, builder):
        r = base_types.VInt()
        if builder is not None:
            new_args = []
            new_args.append(args[0].auto_load(builder))  # RPC number
            for arg in args[1:]:
                # type tag
                arg_type_str = _value_to_str(arg)
                arg_type_int = 0
                for c in reversed(arg_type_str):
                    arg_type_int <<= 8
                    arg_type_int |= ord(c)
                new_args.append(ll.Constant(ll.IntType(32), arg_type_int))

                # pointer to value
                if not isinstance(arg, base_types.VNone):
                    if isinstance(arg.llvm_value.type, ll.PointerType):
                        new_args.append(arg.llvm_value)
                    else:
                        arg_ptr = arg.new()
                        arg_ptr.alloca(builder)
                        arg_ptr.auto_store(builder, arg.llvm_value)
                        new_args.append(arg_ptr.llvm_value)
            # end marker
            new_args.append(ll.Constant(ll.IntType(32), 0))
            r.auto_store(builder, builder.call(self.rpc, new_args))
        return r
Ejemplo n.º 4
0
 def get_llvm_type(self):
     count = 0 if self.alloc_count is None else self.alloc_count
     if isinstance(self.el_type, VNone):
         return ll.LiteralStructType([ll.IntType(32)])
     else:
         return ll.LiteralStructType([
             ll.IntType(32),
             ll.ArrayType(self.el_type.get_llvm_type(), count)
         ])
Ejemplo n.º 5
0
 def o_len(self, builder):
     r = VInt()
     if builder is not None:
         count_ptr = builder.gep(self.llvm_value, [
             ll.Constant(ll.IntType(32), 0),
             ll.Constant(ll.IntType(32), 0)
         ])
         r.auto_store(builder, builder.load(count_ptr))
     return r
Ejemplo n.º 6
0
 def o_subscript(self, index, builder):
     r = self.el_type.new()
     if builder is not None and not isinstance(r, VNone):
         index = index.o_int(builder).auto_load(builder)
         ssa_r = builder.gep(self.llvm_value, [
             ll.Constant(ll.IntType(32), 0),
             ll.Constant(ll.IntType(32), 1), index
         ])
         r.auto_store(builder, ssa_r)
     return r
Ejemplo n.º 7
0
def _chr_to_type(c):
    if c == "n":
        return ll.VoidType()
    if c == "b":
        return ll.IntType(1)
    if c == "i":
        return ll.IntType(32)
    if c == "I":
        return ll.IntType(64)
    raise ValueError
Ejemplo n.º 8
0
 def _visit_stmt_Raise(self, node):
     if self._active_exception_stack:
         finally_block, propagate, propagate_eid = (
             self._active_exception_stack[-1])
         self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
         if node.exc is not None:
             eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
             self.builder.store(eid, propagate_eid)
         self.builder.branch(finally_block)
     else:
         eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
         self.runtime.build_raise(self.builder, eid)
Ejemplo n.º 9
0
    def init_module(self, module):
        self.module = module
        llvm_module = self.module.llvm_module

        # RPC
        func_type = ll.FunctionType(ll.IntType(32), [ll.IntType(32)],
                                    var_arg=1)
        self.rpc = ll.Function(llvm_module, func_type, "__syscall_rpc")

        # syscalls
        self.syscalls = dict()
        for func_name, func_type_str in _syscalls.items():
            func_type = _str_to_functype(func_type_str)
            self.syscalls[func_name] = ll.Function(llvm_module, func_type,
                                                   "__syscall_" + func_name)

        # exception handling
        func_type = ll.FunctionType(ll.IntType(32),
                                    [ll.PointerType(ll.IntType(8))])
        self.eh_setjmp = ll.Function(llvm_module, func_type, "__eh_setjmp")
        self.eh_setjmp.attributes.add("nounwind")
        self.eh_setjmp.attributes.add("returns_twice")

        func_type = ll.FunctionType(ll.PointerType(ll.IntType(8)), [])
        self.eh_push = ll.Function(llvm_module, func_type, "__eh_push")

        func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
        self.eh_pop = ll.Function(llvm_module, func_type, "__eh_pop")

        func_type = ll.FunctionType(ll.IntType(32), [])
        self.eh_getid = ll.Function(llvm_module, func_type, "__eh_getid")

        func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
        self.eh_raise = ll.Function(llvm_module, func_type, "__eh_raise")
        self.eh_raise.attributes.add("noreturn")
Ejemplo n.º 10
0
 def o_bool(self, builder):
     r = VBool()
     if builder is not None:
         zero = ll.Constant(ll.IntType(64), 0)
         a = builder.extract_element(self.auto_load(builder), 0)
         r.auto_store(builder, builder.icmp_signed("!=", a, zero))
     return r
Ejemplo n.º 11
0
    def _visit_stmt_Assign(self, node):
        val = self.visit_expression(node.value)
        if isinstance(node.value, ast.List):
            if len(node.targets) > 1:
                raise NotImplementedError
            target = self.visit_expression(node.targets[0])
            target.set_count(self.builder, val.alloc_count)
            for i, elt in enumerate(val.elts):
                idx = base_types.VInt()
                idx.set_const_value(self.builder, i)
                target.o_subscript(idx,
                                   self.builder).set_value(self.builder, elt)
        elif isinstance(node.value, ast.ListComp):
            if len(node.targets) > 1:
                raise NotImplementedError
            target = self.visit_expression(node.targets[0])
            target.set_count(self.builder, val.alloc_count)

            i = base_types.VInt()
            i.alloca(self.builder)
            i.auto_store(self.builder, ll.Constant(ll.IntType(32), 0))

            function = self.builder.basic_block.function
            copy_block = function.append_basic_block("ai_copy")
            end_block = function.append_basic_block("ai_end")
            self.builder.branch(copy_block)

            self.builder.position_at_end(copy_block)
            target.o_subscript(i,
                               self.builder).set_value(self.builder, val.elt)
            i.auto_store(
                self.builder,
                self.builder.add(i.auto_load(self.builder),
                                 ll.Constant(ll.IntType(32), 1)))
            cont = self.builder.icmp_signed(
                "<", i.auto_load(self.builder),
                ll.Constant(ll.IntType(32), val.alloc_count))
            self.builder.cbranch(cont, copy_block, end_block)

            self.builder.position_at_end(end_block)
        else:
            for target in node.targets:
                target = self.visit_expression(target)
                target.set_value(self.builder, val)
Ejemplo n.º 12
0
 def _o_cmp(self, other, icmp, builder):
     diff = self.o_sub(other, builder)
     if diff is NotImplemented:
         return NotImplemented
     r = VBool()
     if builder is not None:
         diff = diff.auto_load(builder)
         a = builder.extract_value(diff, 0)
         zero = ll.Constant(ll.IntType(64), 0)
         ssa_r = builder.icmp_signed(icmp, a, zero)
         r.auto_store(builder, ssa_r)
     return r
Ejemplo n.º 13
0
    def _handle_exception(self, function, finally_block, propagate,
                          propagate_eid, handlers):
        eid = self.runtime.build_getid(self.builder)
        self._active_exception_stack.append(
            (finally_block, propagate, propagate_eid))
        self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
        self.builder.store(eid, propagate_eid)

        for handler in handlers:
            handled_exc_block = function.append_basic_block("try_exc_h")
            cont_exc_block = function.append_basic_block("try_exc_c")
            if handler.type is None:
                self.builder.branch(handled_exc_block)
            else:
                if isinstance(handler.type, ast.Tuple):
                    match = self.builder.icmp_signed(
                        "==", eid,
                        ll.Constant(ll.IntType(32),
                                    handler.type.elts[0].args[0].n))
                    for elt in handler.type.elts[1:]:
                        match = self.builder.or_(
                            match,
                            self.builder.icmp_signed(
                                "==", eid,
                                ll.Constant(ll.IntType(32), elt.args[0].n)))
                else:
                    match = self.builder.icmp_signed(
                        "==", eid,
                        ll.Constant(ll.IntType(32), handler.type.args[0].n))
                self.builder.cbranch(match, handled_exc_block, cont_exc_block)
            self.builder.position_at_end(handled_exc_block)
            self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
            self.visit_statements(handler.body)
            if not self._bb_terminated():
                self.builder.branch(finally_block)
            self.builder.position_at_end(cont_exc_block)
        self.builder.branch(finally_block)

        self._active_exception_stack.pop()
Ejemplo n.º 14
0
    def _visit_stmt_Try(self, node):
        function = self.builder.basic_block.function
        noexc_block = function.append_basic_block("try_noexc")
        exc_block = function.append_basic_block("try_exc")
        finally_block = function.append_basic_block("try_finally")

        propagate = self.builder.alloca(ll.IntType(1), name="propagate")
        self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
        propagate_eid = self.builder.alloca(ll.IntType(32),
                                            name="propagate_eid")
        exception_occured = self.runtime.build_catch(self.builder)
        self.builder.cbranch(exception_occured, exc_block, noexc_block)

        self.builder.position_at_end(noexc_block)
        self._exception_level_stack[-1] += 1
        self.visit_statements(node.body)
        self._exception_level_stack[-1] -= 1
        if not self._bb_terminated():
            self.runtime.build_pop(self.builder, 1)
            self.visit_statements(node.orelse)
            if not self._bb_terminated():
                self.builder.branch(finally_block)
        self.builder.position_at_end(exc_block)
        self._handle_exception(function, finally_block, propagate,
                               propagate_eid, node.handlers)

        propagate_block = function.append_basic_block("try_propagate")
        merge_block = function.append_basic_block("try_merge")
        self.builder.position_at_end(finally_block)
        self.visit_statements(node.finalbody)
        if not self._bb_terminated():
            self.builder.cbranch(self.builder.load(propagate), propagate_block,
                                 merge_block)
        self.builder.position_at_end(propagate_block)
        self.runtime.build_raise(self.builder,
                                 self.builder.load(propagate_eid))
        self.builder.branch(merge_block)
        self.builder.position_at_end(merge_block)
Ejemplo n.º 15
0
 def _o_eq_inv(self, other, builder, ne):
     if not isinstance(other, (VInt, VFraction)):
         return NotImplemented
     r = VBool()
     if builder is not None:
         if isinstance(other, VInt):
             other = other.o_int64(builder)
             a, b = self._nd(builder)
             ssa_r = builder.and_(
                 builder.icmp_signed("==", a,
                                     other.auto_load()),
                 builder.icmp_signed("==", b,
                                     ll.Constant(ll.IntType(64), 1)))
         else:
             a, b = self._nd(builder)
             c, d = other._nd(builder)
             ssa_r = builder.and_(
                 builder.icmp_signed("==", a, c),
                 builder.icmp_signed("==", b, d))
         if ne:
             ssa_r = builder.xor(ssa_r,
                                 ll.Constant(ll.IntType(1), 1))
         r.auto_store(builder, ssa_r)
     return r
Ejemplo n.º 16
0
def main():
    def process_diagnostic(diag):
        print("\n".join(diag.render()))
        if diag.level in ("fatal", "error"):
            exit(1)

    engine = diagnostic.Engine()
    engine.process = process_diagnostic

    mod = Module(Source.from_string("".join(fileinput.input()).expandtabs(), engine=engine))

    target = NativeTarget()
    llmod = mod.build_llvm_ir(target=target)

    # Add main so that the result can be executed with lli
    llmain = ll.Function(llmod, ll.FunctionType(ll.VoidType(), []), "main")
    llbuilder = ll.IRBuilder(llmain.append_basic_block("entry"))
    llbuilder.call(llmod.get_global(llmod.name + ".__modinit__"), [
                    ll.Constant(ll.IntType(8).as_pointer(), None)])
    llbuilder.ret_void()

    print(llmod)
Ejemplo n.º 17
0
def _make_ssa(builder, n, d):
    value = ll.Constant(ll.ArrayType(ll.IntType(64), 2), ll.Undefined)
    value = builder.insert_value(value, n, 0)
    value = builder.insert_value(value, d, 1)
    return value
Ejemplo n.º 18
0
 def get_llvm_type(self):
     return ll.ArrayType(ll.IntType(64), 2)
Ejemplo n.º 19
0
 def set_count(self, builder, count):
     count_ptr = builder.gep(
         self.llvm_value,
         [ll.Constant(ll.IntType(32), 0),
          ll.Constant(ll.IntType(32), 0)])
     builder.store(ll.Constant(ll.IntType(32), count), count_ptr)
Ejemplo n.º 20
0
 def get_llvm_type(self):
     return ll.IntType(self.nbits)
Ejemplo n.º 21
0
 def build_pop(self, builder, levels):
     builder.call(self.eh_pop, [ll.Constant(ll.IntType(32), levels)])
Ejemplo n.º 22
0
 def build_catch(self, builder):
     jmpbuf = builder.call(self.eh_push, [])
     exception_occured = builder.call(self.eh_setjmp, [jmpbuf])
     return builder.icmp_signed("!=", exception_occured,
                                ll.Constant(ll.IntType(32), 0))