package com.oracle.truffle.llvm.initialization;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.TruffleLanguage.ContextReference;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.llvm.runtime.LLVMContext;
import com.oracle.truffle.llvm.runtime.LLVMLanguage;
import com.oracle.truffle.llvm.runtime.NativeContextExtension;
import com.oracle.truffle.llvm.runtime.except.LLVMParserException;
public final class LoadNativeNode extends RootNode {
private final String path;
@CompilationFinal private ContextReference<LLVMContext> ctxRef;
private LoadNativeNode(FrameDescriptor rootFrame, LLVMLanguage language, TruffleFile file) {
super(language, rootFrame);
this.path = file.getPath();
}
public static LoadNativeNode create(FrameDescriptor rootFrame, LLVMLanguage language, TruffleFile file) {
return new LoadNativeNode(rootFrame, language, file);
}
@Override
public Object execute(VirtualFrame frame) {
if (ctxRef == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
this.ctxRef = lookupContextReference(LLVMLanguage.class);
}
LoadModulesNode.LLVMLoadingPhase phase;
if (frame.getArguments().length > 0 && (frame.getArguments()[0] instanceof LoadModulesNode.LLVMLoadingPhase)) {
phase = (LoadModulesNode.LLVMLoadingPhase) frame.getArguments()[0];
} else if (frame.getArguments().length == 0) {
throw new LLVMParserException(this, "Toplevel executable %s does not contain bitcode", path);
} else {
throw new LLVMParserException(this, "LoadNativeNode is called either with unexpected arguments or as a toplevel");
}
if (LoadModulesNode.LLVMLoadingPhase.INIT_SYMBOLS.isActive(phase)) {
LLVMContext context = ctxRef.get();
parseAndInitialiseNativeLib(context);
}
return null;
}
@TruffleBoundary
private void parseAndInitialiseNativeLib(LLVMContext context) {
NativeContextExtension nativeContextExtension = context.getContextExtensionOrNull(NativeContextExtension.class);
if (nativeContextExtension != null) {
CallTarget callTarget = nativeContextExtension.parseNativeLibrary(path, context);
nativeContextExtension.addLibraryHandles(callTarget.call());
}
}
}