예제 #1
0
    def build_or_get_function(self, parent, volpe_args):
        module: ir.Module = parent.builder.module

        func_args = unwrap(self.args())
        if not isinstance(volpe_args, VolpeObject):
            func_args = ir.LiteralStructType([func_args])

        for func in module.functions:
            if func.name == self.name:
                break
        else:
            func_type = ir.FunctionType(unwrap(self.ret()), func_args)
            func = ir.Function(module, func_type, self.name)

        volpe_func_type = ir.FunctionType(unwrap(
            self.ret()), [ir.LiteralStructType([]),
                          unwrap(self.args())])
        volpe_func = ir.Function(module, volpe_func_type,
                                 str(next(module.func_count)))
        with build_func(volpe_func) as (b, args):
            b: ir.IRBuilder
            args = [args[1]]
            if isinstance(volpe_args, VolpeObject):
                args = [
                    b.extract_value(args[0], i)
                    for i in range(len(volpe_args.type_dict))
                ]

            b.ret(b.call(func, args))

        return volpe_func
예제 #2
0
 def constant_array(self, tree: TypeTree):
     value = self.visit(tree.children[0])
     array_value = unwrap(tree.return_type)(ir.Undefined)
     if tree.return_type.count == 0:
         return array_value
     array_value = self.builder.insert_element(array_value, value, int64(0))
     mask = ir.VectorType(
         int32, tree.return_type.count)([0] * tree.return_type.count)
     return self.builder.shuffle_vector(
         array_value,
         unwrap(tree.return_type)(ir.Undefined), mask)
예제 #3
0
def volpe_llvm(tree: TypeTree,
               verbose=False,
               more_verbose=False,
               console=False):
    if more_verbose:
        print(tree.pretty())

    arg_scope = {}

    def scope(name, local_tree: TypeTree):
        if name in arg_scope:
            return arg_scope[name]
        raise VolpeError(f"variable `{name}` not found", local_tree)

    AnnotateScope(tree, scope)

    if verbose:
        print(tree.pretty())

    module = ir.Module("program")
    module.func_count = itertools.count()

    run_func = ir.Function(
        module,
        ir.FunctionType(unknown, [unwrap(tree.return_type).as_pointer()]),
        "run")
    with build_func(run_func) as (b, args):
        arg_scope = {}

        def scope(name):
            return arg_scope[name]

        def ret(value):
            b.store(value, args[0], 8)
            b.ret_void()

        LLVMScope(b, tree, scope, ret, None)

    return str(module)
예제 #4
0
def determine_c_type(volpe_type):
    """Interpret the volpe type and return a corresponding C type."""
    if DEBUG_BUFFER:
        return get_padding(64)

    # Simple types:
    if volpe_type == int1:
        return c_bool
    if volpe_type == int64:
        return c_int64
    if volpe_type == flt64:
        return c_double
    if volpe_type == char:
        return c_char

    # Aggregate types:
    if isinstance(volpe_type, VolpeObject):
        # Create fields with padding in between to counteract abi incompatibility.
        # Fields begin with '*' to avoid name collision with Structure attributes.
        fields = []
        pos = 0

        for i, (key, value) in enumerate(volpe_type.type_dict.items()):
            ll_type = unwrap(volpe_type)._get_ll_pointer_type(
                target_data).element_type
            pad_needed = target_data.get_element_offset(ll_type, i) - pos
            if pad_needed != 0:
                fields.append((f"*pad_at_{pos}_size_{pad_needed}",
                               get_padding(pad_needed)))
                pos += pad_needed

            c_type = determine_c_type(value)
            fields.append((f"*{key}", c_type))
            pos += sizeof(c_type)

        class CObject(Structure):
            _fields_ = fields

            def __repr__(self):
                # Filter out padding fields.
                keys = [key for (key, _) in self._fields_ if key[:4] != "*pad"]
                # Field names are being shown only if they don't begin with an underscore.
                res = "{" + ", ".join(
                    [("" if key[1] == "_" else f"{key[1:]}: ") +
                     get_repr(getattr(self, key)) for key in keys]) + "}"
                return res

        return CObject

    if isinstance(volpe_type, VolpeArray):

        class CArray(Structure):
            _fields_ = [
                ("elements",
                 determine_c_type(volpe_type.element) * volpe_type.count)
            ]

            def __repr__(self):
                if volpe_type.element == char:
                    try:
                        return f'"{bytes(self).decode(ENCODING)}"'
                    except UnicodeDecodeError:
                        # if not valid ascii, use default repr, but replace b' ' with b" "
                        return f'"{repr(self.elements[:])[2:-1]}"'
                else:
                    return repr(self.elements[:])

        return CArray

    if isinstance(volpe_type, VolpeClosure):

        class CFunc(Structure):
            _fields_ = [(key, determine_c_type(value))
                        for key, value in volpe_type.env.items()]

            def __repr__(self):
                return f"closure (line {volpe_type.tree.meta.line})"

        return CFunc

    # Unknown type
    return None
예제 #5
0
 def object(self, tree: TypeTree):
     value = unwrap(tree.return_type)(ir.Undefined)
     for i, child in enumerate(tree.children):
         key, attribute = get_obj_key_value(child, i)
         value = self.builder.insert_value(value, self.visit(attribute), i)
     return value
예제 #6
0
 def block(self, tree: TypeTree):
     with options(self.builder, unwrap(tree.return_type)) as (ret, phi):
         self.__class__(self.builder, tree, self.get_scope, ret, None)
     return phi
예제 #7
0
 def func(self, tree: TypeTree):
     closure = unwrap(tree.return_type)(ir.Undefined)
     for i, name in enumerate(tree.return_type.env.keys()):
         closure = self.builder.insert_value(closure, self.get_scope(name),
                                             i)
     return closure
예제 #8
0
 def make_pointer(self, tree: TypeTree):
     value = self.visit(tree.children[0])
     ptr = self.builder.alloca(value.type)
     self.builder.store(value, ptr)
     return self.builder.bitcast(ptr, unwrap(tree.return_type))
예제 #9
0
 def array(self, tree: TypeTree):
     array_value = unwrap(tree.return_type)(ir.Undefined)
     for i, ret in enumerate(self.visit_children(tree)):
         array_value = self.builder.insert_element(array_value, ret,
                                                   int64(i))
     return array_value