Пример #1
0
    def sizeof(self, tree: Tree):
        nodes = tree.children
        variable: Optional[RIALVariable] = self.transform_helper(nodes[0])
        name = ""

        # If it's not a variable, extract the name manually since it's the name of a type to get the size of
        if variable is None:
            name = nodes[0].children[0].value
            ty = ParserState.map_type_to_llvm_no_pointer(name)

            size = Int32(get_size(ty))
        elif isinstance(variable.backing_value,
                        ir.GEPInstr) or (variable.is_array and isinstance(
                            variable.raw_llvm_type, ir.PointerType)):
            # This is worst case as it cannot be optimized away.
            base = self.llvmgen.builder.ptrtoint(
                self.llvmgen.builder.gep(variable.backing_value,
                                         [ir.Constant(ir.IntType(32), 0)]),
                ir.IntType(32))
            val = self.llvmgen.builder.ptrtoint(
                self.llvmgen.builder.gep(variable.backing_value,
                                         [ir.Constant(ir.IntType(32), 1)]),
                ir.IntType(32))
            size = self.llvmgen.builder.sub(val, base)
            name = "unknown"
        elif variable.is_array:
            if variable.is_constant_sized_array:
                ty = variable.raw_llvm_type
                size = get_size(ty.element) * ty.count
                size = Int32(size)
                name = f"{ty.element}[{ty.count}]"
            else:
                value = variable.raw_backing_value
                size = get_size(value.type.element)
                size = self.llvmgen.gen_multiplication(
                    Int32(size),
                    self.llvmgen.gen_load_if_necessary(value.type.count))
                name = f"{value.type.element}[{value.type.count}]"
        elif variable.raw_llvm_type == variable.raw_backing_value.type:
            size = Int32(get_size(variable.raw_llvm_type))
            name = f"{variable.rial_type}"
        else:
            # This is worst case as it cannot be optimized away.
            base = self.llvmgen.builder.ptrtoint(
                self.llvmgen.builder.gep(variable.backing_value,
                                         [ir.Constant(ir.IntType(32), 0)]),
                ir.IntType(32))
            val = self.llvmgen.builder.ptrtoint(
                self.llvmgen.builder.gep(variable.backing_value,
                                         [ir.Constant(ir.IntType(32), 1)]),
                ir.IntType(32))
            size = self.llvmgen.builder.sub(val, base)
            name = "unknown"

        return RIALVariable(f"sizeof_{name}", "Int32", size)
Пример #2
0
    def declare_nameless_variable_from_rial_type(self, rial_type: str, value):
        returned_type = ParserState.map_type_to_llvm_no_pointer(rial_type)

        if isinstance(returned_type, ir.VoidType):
            return value
        returned_value = self.builder.alloca(returned_type)

        if isinstance(ParserState.map_type_to_llvm(rial_type), PointerType):
            self.builder.store(self.builder.load(value), returned_value)
        else:
            self.builder.store(value, returned_value)

        return returned_value
Пример #3
0
    def array_constructor(self, tree: Tree):
        nodes = tree.children
        name = nodes[0].value
        number: RIALVariable = self.transform_helper(nodes[1])

        if isinstance(number.raw_backing_value, ir.Constant):
            number = number.raw_backing_value.constant
        else:
            number = number.raw_backing_value

        ty = ParserState.map_type_to_llvm_no_pointer(name)
        arr_type = ir.ArrayType(ty, number)

        allocated = self.llvmgen.builder.alloca(arr_type)

        return RIALVariable(
            f"array_{name}[{number}]",
            f"{name}[{isinstance(number, int) and f'{number}' or ''}]",
            allocated)
Пример #4
0
    def cast(self, tree: Tree):
        nodes = tree.children
        ty = ParserState.map_type_to_llvm_no_pointer(nodes[0])
        value: RIALVariable = self.transform_helper(nodes[1])

        if is_builtin_type(nodes[0]):
            # Simple cast for primitive to primitive
            if value.is_primitive:
                cast_function = get_casting_function(value.raw_llvm_type, ty)

                if hasattr(self.llvmgen.builder, cast_function):
                    casted = getattr(self.llvmgen.builder,
                                     cast_function)(value.raw_backing_value,
                                                    ty)
                else:
                    raise TypeError(
                        f"No casting function found for casting {value.rial_type} to {nodes[0]}"
                    )
            else:
                # Casting type to integer ("pointer") (unsafe!)
                with only_allowed_in_unsafe():
                    casted = self.llvmgen.builder.ptrtoint(
                        value.backing_value, ty)
        else:
            # Casting integer to type (unsafe!)
            if value.is_primitive:
                with only_allowed_in_unsafe():
                    casted = self.llvmgen.builder.inttoptr(
                        value.raw_backing_value, ty.as_pointer())
            else:
                # Simple type cast
                casted = self.llvmgen.builder.bitcast(value.backing_value,
                                                      ty.as_pointer())

        return RIALVariable(f"cast_{value.rial_type}_to_{nodes[0]}", nodes[0],
                            casted)
Пример #5
0
 def raw_llvm_type(self):
     from rial.ParserState import ParserState
     return ParserState.map_type_to_llvm_no_pointer(self.rial_type)