예제 #1
0
파일: LLVMGen.py 프로젝트: mingtaoy/RIAL
    def _get_by_identifier(self, identifier: str, variable: Optional = None) -> Optional:
        if isinstance(variable, RIALVariable):
            variable = variable.backing_value

        if not variable is None and hasattr(variable, 'type') and isinstance(variable.type, PointerType):
            if isinstance(variable.type.pointee, RIALIdentifiedStructType):
                struct = ParserState.find_struct(variable.type.pointee.name)

                if struct is None:
                    return None

                if not self.check_struct_access_allowed(struct):
                    raise PermissionError(f"Tried accesssing struct {struct.name}")

                prop = struct.definition.properties[identifier]

                if prop is None:
                    return None

                # Check property access
                if not self.check_property_access_allowed(struct, prop[1]):
                    raise PermissionError(f"Tried to access property {prop[1].name} but it was not allowed!")

                variable = self.builder.gep(variable, [ir.Constant(ir.IntType(32), 0),
                                                       ir.Constant(ir.IntType(32), prop[0])])
        else:
            # Search local variables
            variable = self.current_block.get_named_value(identifier)

            # Search for a global variable
            if variable is None:
                glob = ParserState.find_global(identifier)

                # Check if in same module
                if glob is not None:
                    if glob.backing_value.parent.name != ParserState.module().name:
                        glob_current_module = ParserState.module().get_global_safe(glob.name)

                        if glob_current_module is not None:
                            variable = glob_current_module
                        else:
                            # TODO: Check if global access is allowed
                            variable = self.gen_global(glob.name, None, glob.backing_value.type.pointee,
                                                       glob.access_modifier, "external",
                                                       glob.backing_value.global_constant)
                    else:
                        variable = glob.backing_value

        # If variable is none, just do a full function search
        if variable is None:
            variable = ParserState.find_function(identifier)

            if variable is None:
                variable = ParserState.find_function(mangle_function_name(identifier, []))

            # Check if in same module
            if variable is not None:
                if variable.module.name != ParserState.module().name:
                    variable_current_module = ParserState.module().get_global_safe(variable.name)

                    if variable_current_module is not None:
                        variable = variable_current_module
                    else:
                        variable = self.create_function_with_type(variable.name, variable.name, variable.function_type,
                                                                  variable.linkage,
                                                                  variable.calling_convention,
                                                                  variable.definition)

        return variable
예제 #2
0
파일: LLVMGen.py 프로젝트: mingtaoy/RIAL
    def gen_function_call(self, possible_function_names: List[str],
                          llvm_args: List) -> Optional[CallInstr]:
        func = None
        # Check if it's actually a local variable
        for function_name in possible_function_names:
            var = self.get_definition(function_name)

            if var is not None:
                func = var

        # Try to find by function name
        if func is None:
            for function_name in possible_function_names:
                func = ParserState.find_function(function_name)

                if func is not None:
                    break

        # Try to find by function name but enable canonical name
        if func is None:
            rial_arg_types = [map_llvm_to_type(arg.type) for arg in llvm_args]

            for function_name in possible_function_names:
                func = ParserState.find_function(function_name, rial_arg_types)

                if func is not None:
                    break

        if func is None:
            return None

        if isinstance(func, RIALVariable):
            func = func.backing_value

        if isinstance(func, ir.PointerType) and isinstance(func.pointee, RIALFunction):
            func = func.pointee
        elif isinstance(func, GlobalVariable) or isinstance(func, AllocaInstr):
            loaded_func = self.builder.load(func)
            call = self.builder.call(loaded_func, llvm_args)
            return call

        # Check if call is allowed
        if not self.check_function_call_allowed(func):
            raise PermissionError(f"Tried calling function {func.name} from {self.current_func.name}")

        # Check if function is declared in current module
        if ParserState.module().get_global_safe(func.name) is None:
            func = self.create_function_with_type(func.name, func.canonical_name, func.function_type, func.linkage,
                                                  func.calling_convention, func.definition)

        args = list()

        # Gen a load if necessary
        for i, arg in enumerate(llvm_args):
            llvm_arg = func.definition.rial_args[i].llvm_type

            if llvm_arg == arg.type:
                args.append(arg)
                continue

            args.append(self.builder.load(arg))

        # Check type matching
        for i, arg in enumerate(args):
            if len(func.args) > i and arg.type != func.args[i].type:
                # Check for base types
                ty = isinstance(arg.type, PointerType) and arg.type.pointee or arg.type
                func_arg_type = isinstance(func.args[i].type, PointerType) and func.args[i].type.pointee or func.args[
                    i].type

                if isinstance(ty, RIALIdentifiedStructType):
                    struct = ParserState.find_struct(ty.name)

                    if struct is not None:
                        found = False

                        # Check if a base struct matches the type expected
                        # TODO: Recursive check
                        for base_struct in struct.definition.base_structs:
                            if base_struct == func_arg_type.name:
                                args.remove(arg)
                                args.insert(i, self.builder.bitcast(arg, ir.PointerType(base_struct)))
                                found = True
                                break
                        if found:
                            continue

                    # TODO: SLOC information
                raise TypeError(
                    f"Function {func.name} expects a {func.args[i].type} but got a {arg.type}")

        # Gen call
        return self.builder.call(func, args)