Search in sources :

Example 1 with RTLDFlags

use of com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMDLOpen.RTLDFlags in project graal by oracle.

the class LoadModulesNode method loadModule.

@SuppressWarnings("unchecked")
private LLVMScopeChain loadModule(VirtualFrame frame, LLVMContext context) {
    stackAccess.executeEnter(frame, getContext().getThreadingStack().getStack());
    try {
        LLVMLoadingPhase phase;
        // instead of creating a llvm local scope, just create a llvm scope here, and then put
        // it inside the chains
        LLVMScopeChain headLocalScopeChain = null;
        LLVMScopeChain tailLocalScopeChain = null;
        BitSet visited = null;
        ArrayDeque<CallTarget> que = null;
        ArrayList<CallTarget> dependencies = null;
        LLVMScopeChain headResultScopeChain = null;
        LLVMScopeChain tailResultScopeChain = null;
        RTLDFlags localOrGlobal = RTLDFlags.RTLD_OPEN_DEFAULT;
        // check for arguments for dlOpen
        if (frame.getArguments().length > 0 && (frame.getArguments()[0] instanceof RTLDFlags)) {
            localOrGlobal = (RTLDFlags) frame.getArguments()[0];
        }
        /*
             * The arguments in the frames for every loading phase include: 1) The current loading
             * phase. 2) The visited set. The scope building, the external symbol, and overwriting
             * symbol phases all require an additional argument: 3) The RTLD flag, if the library is
             * loaded with RTLD_LOCAL or RTLD_GLOBAL. The scope building phase also have: 4) The
             * tail of the linked structure for local scope. 5) The que of library dependencies. 6)
             * The tail of the linked structure for returning result scope. The external symbol and
             * overwriting symbol phases require instead: 4) The head of the linked structure for
             * local scope.
             */
        if (frame.getArguments().length > 0 && (frame.getArguments()[0] instanceof LLVMLoadingPhase)) {
            phase = (LLVMLoadingPhase) frame.getArguments()[0];
            if (phase == LLVMLoadingPhase.BUILD_SCOPES || phase == LLVMLoadingPhase.BUILD_DEPENDENCY) {
                visited = (BitSet) frame.getArguments()[1];
            }
            if (phase == LLVMLoadingPhase.INIT_EXTERNALS || phase == LLVMLoadingPhase.INIT_OVERWRITE) {
                localOrGlobal = (RTLDFlags) frame.getArguments()[1];
                headLocalScopeChain = (LLVMScopeChain) frame.getArguments()[2];
            }
            if (phase == LLVMLoadingPhase.BUILD_SCOPES) {
                localOrGlobal = (RTLDFlags) frame.getArguments()[2];
            }
            if (phase == LLVMLoadingPhase.BUILD_DEPENDENCY) {
                dependencies = (ArrayList<CallTarget>) frame.getArguments()[2];
            }
            // Additional arguments are required for building the scopes.
            if (phase == LLVMLoadingPhase.BUILD_SCOPES) {
                tailLocalScopeChain = (LLVMScopeChain) frame.getArguments()[3];
                que = (ArrayDeque<CallTarget>) frame.getArguments()[4];
                tailResultScopeChain = (LLVMScopeChain) frame.getArguments()[5];
            }
        // For the root library, it is defined when either the frame has no argument, or
        // when the first argument is not one of the loading phases.
        } else if (frame.getArguments().length == 0 || !(frame.getArguments()[0] instanceof LLVMLoadingPhase)) {
            // create first and last of the scope chain.
            phase = LLVMLoadingPhase.ALL;
            headResultScopeChain = new LLVMScopeChain(bitcodeID, parserRuntime.getFileScope());
            tailResultScopeChain = headResultScopeChain;
            headLocalScopeChain = new LLVMScopeChain(bitcodeID, parserRuntime.getPublicFileScope());
            tailLocalScopeChain = headLocalScopeChain;
            visited = createBitset(libraryDependencies.length);
            que = new ArrayDeque<>();
            dependencies = new ArrayList<>();
        } else {
            throw new LLVMParserException("LoadModulesNode is called with unexpected arguments");
        }
        /*
             * The scope is built in parsing order, which requires breadth-first with a que.
             */
        if (LLVMLoadingPhase.BUILD_SCOPES.isActive(phase)) {
            int id = bitcodeID.getId();
            if (!visited.get(id)) {
                visited.set(id);
                if (LLVMLoadingPhase.ALL.isActive(phase)) {
                    context.addGlobalScope(new LLVMScopeChain(bitcodeID, parserRuntime.getPublicFileScope()));
                } else {
                    LLVMScopeChain currentLocalScopeChain = new LLVMScopeChain(bitcodeID, parserRuntime.getPublicFileScope());
                    LLVMScopeChain currentResultScopeChain = new LLVMScopeChain(bitcodeID, parserRuntime.getFileScope());
                    if (RTLDFlags.RTLD_OPEN_DEFAULT.isActive(localOrGlobal)) {
                        context.addGlobalScope(new LLVMScopeChain(bitcodeID, parserRuntime.getPublicFileScope()));
                        tailLocalScopeChain.concatNextChain(currentLocalScopeChain);
                        tailResultScopeChain.concatNextChain(currentResultScopeChain);
                    } else if (RTLDFlags.RTLD_LOCAL.isActive(localOrGlobal)) {
                        tailLocalScopeChain.concatNextChain(currentLocalScopeChain);
                    } else if (RTLDFlags.RTLD_GLOBAL.isActive(localOrGlobal)) {
                        tailLocalScopeChain.concatNextChain(currentLocalScopeChain);
                        context.addGlobalScope(new LLVMScopeChain(bitcodeID, parserRuntime.getPublicFileScope()));
                    } else {
                        throw new LLVMParserException(this, "Toplevel executable %s does not contain bitcode");
                    }
                }
                for (int i = 0; i < libraryDependencies.length; i++) {
                    CallTarget callTarget = libraryDependencies[i].execute();
                    if (callTarget != null) {
                        queAdd(que, callTarget);
                    }
                }
                if (LLVMLoadingPhase.ALL.isActive(phase)) {
                    while (!que.isEmpty()) {
                        // Foward the tail scope chain to the latest scope chain.
                        while (tailLocalScopeChain != null && tailLocalScopeChain.getNext() != null) {
                            tailLocalScopeChain = tailLocalScopeChain.getNext();
                        }
                        while (tailResultScopeChain != null && tailResultScopeChain.getNext() != null) {
                            tailResultScopeChain = tailResultScopeChain.getNext();
                        }
                        indirectCall.call(quePoll(que), LLVMLoadingPhase.BUILD_SCOPES, visited, localOrGlobal, tailLocalScopeChain, que, tailResultScopeChain);
                    }
                }
            }
        }
        if (context.isLibraryAlreadyLoaded(bitcodeID)) {
            if (RTLDFlags.RTLD_OPEN_DEFAULT.isActive(localOrGlobal)) {
                return headResultScopeChain;
            } else {
                return headLocalScopeChain;
            }
        }
        if (LLVMLoadingPhase.BUILD_DEPENDENCY.isActive(phase)) {
            if (LLVMLoadingPhase.ALL == phase) {
                visited.clear();
            }
            int id = bitcodeID.getId();
            if (!visited.get(id)) {
                visited.set(id);
                for (LoadDependencyNode libraryDependency : libraryDependencies) {
                    CallTarget lib = libraryDependency.execute();
                    if (lib != null) {
                        callDependencies.call(lib, LLVMLoadingPhase.BUILD_DEPENDENCY, visited, dependencies);
                    }
                }
                dependencies.add(this.getCallTarget());
            }
        }
        /*
             * The order of the initialization nodes is very important. The defined symbols and the
             * external symbols must be initialized before the global symbols can be initialized.
             * The overwriting of symbols can only be done once all the globals are initialized and
             * the symbol table has been allocated.
             */
        switch(phase) {
            case BUILD_SCOPES:
            case BUILD_DEPENDENCY:
                break;
            case ALL:
                assert dependencies != null;
                executeInitialiseAllPhase(dependencies, localOrGlobal, headLocalScopeChain);
                break;
            case INIT_SYMBOLS:
                executeInitialiseSymbolPhase(context);
                break;
            case INIT_EXTERNALS:
                initExternals.execute(context, headLocalScopeChain, localOrGlobal);
                break;
            case INIT_GLOBALS:
                initGlobals.execute(frame, context.getReadOnlyGlobals(bitcodeID));
                break;
            case INIT_OVERWRITE:
                initOverwrite.execute(context, headLocalScopeChain, localOrGlobal);
                break;
            case INIT_CONTEXT:
                initContext.execute(frame);
                break;
            case INIT_MODULE:
                initModules.execute(frame, context);
                break;
            case INIT_DONE:
                context.markLibraryLoaded(bitcodeID);
                break;
            default:
                throw CompilerDirectives.shouldNotReachHere("Unknown loading phase");
        }
        if (LLVMLoadingPhase.ALL == phase) {
            if (RTLDFlags.RTLD_OPEN_DEFAULT.isActive(localOrGlobal)) {
                return headResultScopeChain;
            } else {
                return headLocalScopeChain;
            }
        }
        return null;
    } finally {
        stackAccess.executeExit(frame);
    }
}
Also used : RTLDFlags(com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMDLOpen.RTLDFlags) LLVMScopeChain(com.oracle.truffle.llvm.runtime.LLVMScopeChain) RootCallTarget(com.oracle.truffle.api.RootCallTarget) CallTarget(com.oracle.truffle.api.CallTarget) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) ArrayDeque(java.util.ArrayDeque) LLVMParserException(com.oracle.truffle.llvm.runtime.except.LLVMParserException)

Aggregations

CallTarget (com.oracle.truffle.api.CallTarget)1 RootCallTarget (com.oracle.truffle.api.RootCallTarget)1 LLVMScopeChain (com.oracle.truffle.llvm.runtime.LLVMScopeChain)1 LLVMParserException (com.oracle.truffle.llvm.runtime.except.LLVMParserException)1 RTLDFlags (com.oracle.truffle.llvm.runtime.nodes.intrinsics.c.LLVMDLOpen.RTLDFlags)1 ArrayDeque (java.util.ArrayDeque)1 ArrayList (java.util.ArrayList)1 BitSet (java.util.BitSet)1