use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LLVMBitcodeInstructionVisitor method visit.
@Override
public void visit(VoidInvokeInstruction call) {
final SymbolImpl target = call.getCallTarget();
if (call.getOperandBundle() != null) {
throw new LLVMParserException("Unsupported operand bundle on invoke of " + target.toString());
}
// stackpointer
final int argumentCount = call.getArgumentCount() + 1;
final LLVMExpressionNode[] args = new LLVMExpressionNode[argumentCount];
final TypeArrayBuilder argsType = new TypeArrayBuilder(argumentCount);
int argIndex = 0;
args[argIndex] = nodeFactory.createGetStackFromFrame();
argsType.set(argIndex, new PointerType(null));
argIndex++;
int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount;
for (int i = call.getArgumentCount() - 1; i >= 0; i--) {
args[argIndex + i] = symbols.resolve(call.getArgument(i));
argsType.set(argIndex + i, call.getArgument(i).getType());
final AttributesGroup paramAttr = call.getParameterAttributesGroup(i);
boolean isVarArg = i >= realArgumentCount;
if (isByValue(paramAttr)) {
args[argIndex + i] = capsuleAddressByValue(args[argIndex + i], argsType.get(argIndex + i), paramAttr);
} else if (isVarArg && isArrayByValue(argsType.get(argIndex + i), args[argIndex + i])) {
args[argIndex + i] = capsuleArrayByValue(args[argIndex + i], argsType.get(argIndex + i));
}
}
int regularIndex = call.normalSuccessor().getBlockIndex();
int unwindIndex = call.unwindSuccessor().getBlockIndex();
ArrayList<Phi> normalTo = new ArrayList<>();
ArrayList<Phi> unwindTo = new ArrayList<>();
if (blockPhis != null) {
for (LLVMPhiManager.Phi phi : blockPhis) {
if (call.normalSuccessor() == phi.getBlock()) {
normalTo.add(phi);
} else {
unwindTo.add(phi);
}
}
}
LLVMStatementNode normalPhi = createPhiWriteNodes(normalTo);
LLVMStatementNode unwindPhi = createPhiWriteNodes(unwindTo);
// Builtins are not AST-inlined for Invokes, instead a generic LLVMDispatchNode is used.
LLVMExpressionNode function = resolveOptimized(target, call.getArguments());
LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(null, function, args, new FunctionType(call.getType(), argsType, false), regularIndex, unwindIndex, normalPhi, unwindPhi);
setControlFlowNode(result, call, SourceInstrumentationStrategy.FORCED);
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LLVMBitcodeInstructionVisitor method visit.
@Override
public void visit(InvokeInstruction call) {
final Type targetType = call.getType();
int argumentCount = getArgumentCount(call.getArgumentCount(), targetType);
final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[argumentCount];
final TypeArrayBuilder argTypes = new TypeArrayBuilder(argumentCount);
int argIndex = 0;
argNodes[argIndex] = nodeFactory.createGetStackFromFrame();
argTypes.set(argIndex, new PointerType(null));
argIndex++;
final SymbolImpl target = call.getCallTarget();
if (call.getOperandBundle() != null) {
throw new LLVMParserException("Unsupported operand bundle on invoke of " + target.toString());
}
if (targetType instanceof StructureType) {
argTypes.set(argIndex, new PointerType(targetType));
argNodes[argIndex] = nodeFactory.createGetUniqueStackSpace(targetType, uniquesRegion);
argIndex++;
}
int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount;
for (int i = call.getArgumentCount() - 1; i >= 0; i--) {
argNodes[argIndex + i] = resolveOptimized(call.getArgument(i), i, target, call.getArguments());
argTypes.set(argIndex + i, call.getArgument(i).getType());
final AttributesGroup paramAttr = call.getParameterAttributesGroup(i);
boolean isVarArg = i >= realArgumentCount;
if (isByValue(paramAttr)) {
argNodes[argIndex + i] = capsuleAddressByValue(argNodes[argIndex + i], argTypes.get(argIndex + i), paramAttr);
} else if (isVarArg && isArrayByValue(argTypes.get(argIndex + i), argNodes[argIndex + i])) {
argNodes[argIndex + i] = capsuleArrayByValue(argNodes[argIndex + i], argTypes.get(argIndex + i));
}
}
int regularIndex = call.normalSuccessor().getBlockIndex();
int unwindIndex = call.unwindSuccessor().getBlockIndex();
ArrayList<Phi> normalTo = new ArrayList<>();
ArrayList<Phi> unwindTo = new ArrayList<>();
if (blockPhis != null) {
for (LLVMPhiManager.Phi phi : blockPhis) {
if (call.normalSuccessor() == phi.getBlock()) {
normalTo.add(phi);
} else {
unwindTo.add(phi);
}
}
}
LLVMStatementNode normalPhi = createPhiWriteNodes(normalTo);
LLVMStatementNode unwindPhi = createPhiWriteNodes(unwindTo);
// Builtins are not AST-inlined for Invokes, instead a generic LLVMDispatchNode is used.
LLVMExpressionNode function = symbols.resolve(target);
LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(CommonNodeFactory.createFrameWrite(targetType, null, symbols.findOrAddFrameSlot(call)), function, argNodes, new FunctionType(targetType, argTypes, false), regularIndex, unwindIndex, normalPhi, unwindPhi);
setControlFlowNode(result, call, SourceInstrumentationStrategy.FORCED);
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class InitializeModuleNode method resolveStructor.
private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator<Pair<Integer, ?>> priorityComparator, DataLayout dataLayout, NodeFactory nodeFactory) {
if (!(globalSymbol.getValue() instanceof ArrayConstant)) {
// array globals of length 0 may be initialized with scalar null
return LLVMStatementNode.NO_STATEMENTS;
}
final LLVMGlobal global = (LLVMGlobal) fileScope.get(globalSymbol.getName());
final ArrayConstant arrayConstant = (ArrayConstant) globalSymbol.getValue();
final int elemCount = arrayConstant.getElementCount();
final StructureType elementType = (StructureType) arrayConstant.getType().getElementType();
try {
final long elementSize = elementType.getSize(dataLayout);
final FunctionType functionType = (FunctionType) ((PointerType) elementType.getElementType(1)).getPointeeType();
final int indexedTypeLength = functionType.getAlignment(dataLayout);
final ArrayList<Pair<Integer, LLVMStatementNode>> structors = new ArrayList<>(elemCount);
for (int i = 0; i < elemCount; i++) {
final LLVMExpressionNode globalVarAddress = CommonNodeFactory.createLiteral(global, new PointerType(globalSymbol.getType()));
final LLVMExpressionNode iNode = CommonNodeFactory.createLiteral(i, PrimitiveType.I32);
final LLVMExpressionNode structPointer = nodeFactory.createTypedElementPointer(elementSize, elementType, globalVarAddress, iNode);
final LLVMExpressionNode loadedStruct = nodeFactory.createLoad(elementType, structPointer);
final LLVMExpressionNode oneLiteralNode = CommonNodeFactory.createLiteral(1, PrimitiveType.I32);
final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(indexedTypeLength, functionType, loadedStruct, oneLiteralNode);
final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget);
final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[] { nodeFactory.createGetStackFromFrame() };
final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(CommonNodeFactory.createFunctionCall(loadedFunction, argNodes, functionType));
final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i);
final SymbolImpl prioritySymbol = structorDefinition.getElement(0);
final Integer priority = LLVMSymbolReadResolver.evaluateIntegerConstant(prioritySymbol);
structors.add(new Pair<>(priority != null ? priority : LEAST_CONSTRUCTOR_PRIORITY, functionCall));
}
return structors.stream().sorted(priorityComparator).map(Pair::getSecond).toArray(LLVMStatementNode[]::new);
} catch (Type.TypeOverflowException e) {
return new LLVMStatementNode[] { Type.handleOverflowStatement(e) };
}
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LazyToTruffleConverterImpl method generateCallTarget.
private RootCallTarget generateCallTarget() {
LLVMContext context = LLVMLanguage.getContext();
NodeFactory nodeFactory = runtime.getNodeFactory();
OptionValues options = context.getEnv().getOptions();
boolean printAST = false;
if (LLVMContext.printAstEnabled()) {
String printASTOption = options.get(SulongEngineOption.PRINT_AST_FILTER);
if (!printASTOption.isEmpty()) {
String[] regexes = printASTOption.split(",");
for (String regex : regexes) {
if (method.getName().matches(regex)) {
printAST = true;
LLVMContext.printAstLog("========== " + method.getName());
break;
}
}
}
}
doParse();
// prepare the phis
final Map<InstructionBlock, List<Phi>> phis = LLVMPhiManager.getPhis(method);
LLVMLivenessAnalysisResult liveness = LLVMLivenessAnalysis.computeLiveness(phis, method);
// setup the frameDescriptor
FrameDescriptor.Builder builder = FrameDescriptor.newBuilder();
nodeFactory.addStackSlots(builder);
UniquesRegion uniquesRegion = new UniquesRegion();
GetStackSpaceFactory getStackSpaceFactory = GetStackSpaceFactory.createGetUniqueStackSpaceFactory(uniquesRegion);
LLVMSymbolReadResolver symbols = new LLVMSymbolReadResolver(runtime, builder, getStackSpaceFactory, dataLayout, options.get(SulongEngineOption.LL_DEBUG));
int exceptionSlot = builder.addSlot(FrameSlotKind.Object, null, null);
for (FunctionParameter parameter : method.getParameters()) {
symbols.findOrAddFrameSlot(parameter);
}
HashSet<SSAValue> neededForDebug = getDebugValues();
// create blocks and translate instructions
boolean initDebugValues = true;
LLVMRuntimeDebugInformation info = new LLVMRuntimeDebugInformation(method.getBlocks().size());
LLVMBasicBlockNode[] blockNodes = new LLVMBasicBlockNode[method.getBlocks().size()];
for (InstructionBlock block : method.getBlocks()) {
List<Phi> blockPhis = phis.get(block);
ArrayList<LLVMLivenessAnalysis.NullerInformation> blockNullerInfos = liveness.getNullableWithinBlock()[block.getBlockIndex()];
LLVMBitcodeInstructionVisitor visitor = new LLVMBitcodeInstructionVisitor(exceptionSlot, uniquesRegion, blockPhis, method.getParameters().size(), symbols, context, blockNullerInfos, neededForDebug, dataLayout, nodeFactory);
if (initDebugValues) {
for (SourceVariable variable : method.getSourceFunction().getVariables()) {
if (variable.hasFragments()) {
visitor.initializeAggregateLocalVariable(variable);
}
}
initDebugValues = false;
}
for (int i = 0; i < block.getInstructionCount(); i++) {
visitor.setInstructionIndex(i);
block.getInstruction(i).accept(visitor);
}
LLVMStatementNode[] nodes = visitor.finish();
info.setBlockDebugInfo(block.getBlockIndex(), visitor.getDebugInfo());
blockNodes[block.getBlockIndex()] = LLVMBasicBlockNode.createBasicBlockNode(options, nodes, visitor.getControlFlowNode(), block.getBlockIndex(), block.getName());
}
for (int j = 0; j < blockNodes.length; j++) {
int[] nullableBeforeBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableBeforeBlock()[j]);
int[] nullableAfterBlock = getNullableFrameSlots(liveness.getFrameSlots(), liveness.getNullableAfterBlock()[j]);
blockNodes[j].setNullableFrameSlots(nullableBeforeBlock, nullableAfterBlock);
}
info.setBlocks(blockNodes);
int loopSuccessorSlot = -1;
if (options.get(SulongEngineOption.OSR_MODE) == SulongEngineOption.OSRMode.CFG && !options.get(SulongEngineOption.AOTCacheStore)) {
LLVMControlFlowGraph cfg = new LLVMControlFlowGraph(method.getBlocks().toArray(FunctionDefinition.EMPTY));
cfg.build();
if (cfg.isReducible() && cfg.getCFGLoops().size() > 0) {
loopSuccessorSlot = builder.addSlot(FrameSlotKind.Int, null, null);
resolveLoops(blockNodes, cfg, loopSuccessorSlot, exceptionSlot, info, options);
}
}
LLVMSourceLocation location = method.getLexicalScope();
rootFunction.setSourceLocation(LLVMSourceLocation.orDefault(location));
LLVMStatementNode[] copyArgumentsToFrameArray = copyArgumentsToFrame(symbols).toArray(LLVMStatementNode.NO_STATEMENTS);
FrameDescriptor frame = builder.build();
RootNode rootNode = nodeFactory.createFunction(exceptionSlot, blockNodes, uniquesRegion, copyArgumentsToFrameArray, frame, loopSuccessorSlot, info, method.getName(), method.getSourceName(), method.getParameters().size(), source, location, rootFunction);
method.onAfterParse();
if (printAST) {
printCompactTree(rootNode);
LLVMContext.printAstLog("");
}
return rootNode.getCallTarget();
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LazyToTruffleConverterImpl method resolveLoops.
private void resolveLoops(LLVMBasicBlockNode[] nodes, LLVMControlFlowGraph cfg, int loopSuccessorSlot, int exceptionSlot, LLVMRuntimeDebugInformation info, OptionValues options) {
// The original array is needed to access the frame nuller information for outgoing control
// flow egdes
LLVMBasicBlockNode[] originalBodyNodes = nodes.clone();
info.setBlocks(originalBodyNodes);
for (CFGLoop loop : cfg.getCFGLoops()) {
int headerId = loop.getHeader().id;
int[] indexMapping = new int[nodes.length];
Arrays.fill(indexMapping, -1);
List<LLVMStatementNode> bodyNodes = new ArrayList<>();
// add header to body nodes
LLVMBasicBlockNode header = nodes[headerId];
bodyNodes.add(header);
indexMapping[headerId] = 0;
// add body nodes
int i = 1;
for (CFGBlock block : loop.getBody()) {
bodyNodes.add(nodes[block.id]);
indexMapping[block.id] = i++;
}
int[] loopSuccessors = loop.getSuccessorIDs();
RepeatingNode loopBody = runtime.getNodeFactory().createLoopDispatchNode(exceptionSlot, Collections.unmodifiableList(bodyNodes), originalBodyNodes, headerId, indexMapping, loopSuccessors, loopSuccessorSlot);
LLVMControlFlowNode loopNode = runtime.getNodeFactory().createLoop(loopBody, loopSuccessors);
// replace header block with loop node
nodes[headerId] = LLVMBasicBlockNode.createBasicBlockNode(options, new LLVMStatementNode[0], loopNode, headerId, "loopAt" + headerId);
nodes[headerId].setNullableFrameSlots(header.nullableBefore, header.nullableAfter);
// remove inner loops to reduce number of nodes
for (CFGLoop innerLoop : loop.getInnerLoops()) {
nodes[innerLoop.getHeader().id] = null;
}
}
}
Aggregations