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);
}
}
Aggregations