use of com.oracle.truffle.llvm.runtime.LLVMScopeChain in project graal by oracle.
the class LoadModulesNode method execute.
@Override
public Object execute(VirtualFrame frame) {
LLVMContext context = getContext();
synchronized (context) {
if (!hasInitialised) {
CompilerDirectives.transferToInterpreterAndInvalidate();
LLVMFunction mainFunction = findMainFunction();
if (mainFunction != null) {
main = new CachedMainFunction(mainFunction);
} else {
main = null;
}
initContext = this.insert(language.createInitializeContextNode());
hasInitialised = true;
}
LLVMScopeChain firstScopeChain = loadModule(frame, context);
context.addSourceForCache(bitcodeID, source);
context.addCalltargetForCache(libraryName, this.getCallTarget());
// Only the root library (not a dependency) will have a non-null scope.
if (firstScopeChain != null) {
SulongLibrary library = new SulongLibrary(this.libraryName, firstScopeChain, main, context, parserRuntime.getLocator(), parserRuntime.getBitcodeID());
if (main != null) {
context.setMainLibrary(library);
}
return library;
}
}
return null;
}
use of com.oracle.truffle.llvm.runtime.LLVMScopeChain 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);
}
}
use of com.oracle.truffle.llvm.runtime.LLVMScopeChain in project graal by oracle.
the class InitializeExternalNode method execute.
/*
* (PLi): Need to be careful of native functions/globals that are not in the nfi context (i.e.
* __xstat). Ideally they will be added to the symbol table as unresolved/undefined
* functions/globals.
*/
public void execute(LLVMContext context, LLVMScopeChain localScope, LLVMDLOpen.RTLDFlags rtldFlags) {
LLVMScopeChain globalScope = context.getGlobalScopeChain();
LLVMIntrinsicProvider intrinsicProvider = getLanguage().getCapability(LLVMIntrinsicProvider.class);
NativeContextExtension nativeContextExtension = getNativeContextExtension(context);
for (int i = 0; i < globals.length; i++) {
LLVMGlobal global = globals[i];
LLVMPointer pointer = allocExternalSymbol.execute(localScope, globalScope, intrinsicProvider, nativeContextExtension, context, rtldFlags, global);
if (pointer == null) {
continue;
}
context.initializeSymbol(globals[i], pointer);
}
for (int i = 0; i < functions.length; i++) {
LLVMFunction function = functions[i];
LLVMPointer pointer = allocExternalSymbol.execute(localScope, globalScope, intrinsicProvider, nativeContextExtension, context, rtldFlags, function);
if (pointer == null) {
continue;
}
context.initializeSymbol(functions[i], pointer);
}
}
use of com.oracle.truffle.llvm.runtime.LLVMScopeChain in project graal by oracle.
the class InitializeOverwriteNode method execute.
public void execute(LLVMContext context, LLVMScopeChain localScope, RTLDFlags rtldFlags) {
LLVMScopeChain globalScope = context.getGlobalScopeChain();
for (LLVMFunction function : functions) {
LLVMPointer pointer = allocExternalSymbol.execute(localScope, globalScope, null, null, context, rtldFlags, function);
// skip allocating fallbacks
if (pointer == null) {
continue;
}
context.initializeSymbol(function, pointer);
}
for (LLVMGlobal global : globals) {
LLVMPointer pointer = allocExternalSymbol.execute(localScope, globalScope, null, null, context, rtldFlags, global);
// skip allocating fallbacks
if (pointer == null) {
continue;
}
context.initializeSymbol(global, pointer);
}
}
use of com.oracle.truffle.llvm.runtime.LLVMScopeChain in project graal by oracle.
the class LLVMDebuggerScopeFactory method toDebuggerScope.
@TruffleBoundary
private static LLVMDebuggerScopeEntries toDebuggerScope(LLVMScopeChain scope, DataLayout dataLayout, LLVMContext context) {
final LLVMDebuggerScopeEntries entries = new LLVMDebuggerScopeEntries();
LLVMScopeChain next = scope;
while (next != null) {
for (LLVMSymbol symbol : next.getScope().values()) {
if (symbol.isGlobalVariable()) {
LLVMGlobal global = symbol.asGlobalVariable();
Object value = CommonNodeFactory.toGenericDebuggerValue(global.getPointeeType(), context.getSymbolUncached(global), dataLayout);
entries.add(LLVMIdentifier.toGlobalIdentifier(global.getName()), value);
}
}
next = next.getNext();
}
return entries;
}
Aggregations