/* * Copyright (c) 2016, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.parser; import java.util.ArrayList; import java.util.List; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.llvm.parser.LLVMPhiManager.Phi; import com.oracle.truffle.llvm.parser.instructions.LLVMArithmeticInstructionType; import com.oracle.truffle.llvm.parser.instructions.LLVMConversionType; import com.oracle.truffle.llvm.parser.instructions.LLVMLogicalInstructionKind; import com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock; import com.oracle.truffle.llvm.parser.model.enums.AsmDialect; import com.oracle.truffle.llvm.parser.model.functions.FunctionDeclaration; import com.oracle.truffle.llvm.parser.model.symbols.constants.InlineAsmConstant; import com.oracle.truffle.llvm.parser.model.symbols.constants.NullConstant; import com.oracle.truffle.llvm.parser.model.symbols.constants.integer.IntegerConstant; import com.oracle.truffle.llvm.parser.model.symbols.instructions.AllocateInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.BinaryOperationInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.BranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CallInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CastInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CompareExchangeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.CompareInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ConditionalBranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ExtractElementInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ExtractValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.GetElementPointerInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.IndirectBranchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InsertElementInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InsertValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.InvokeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.LandingpadInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.LoadInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.PhiInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ResumeInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ReturnInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SelectInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ShuffleVectorInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.StoreInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SwitchInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.SwitchOldInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.UnreachableInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.ValueInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.VoidCallInstruction; import com.oracle.truffle.llvm.parser.model.symbols.instructions.VoidInvokeInstruction; import com.oracle.truffle.llvm.parser.model.visitors.InstructionVisitor; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolResolver; import com.oracle.truffle.llvm.parser.util.LLVMBitcodeTypeHelper; import com.oracle.truffle.llvm.runtime.LLVMException; import com.oracle.truffle.llvm.runtime.LLVMLogger; import com.oracle.truffle.llvm.runtime.memory.LLVMStack; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.types.AggregateType; import com.oracle.truffle.llvm.runtime.types.ArrayType; import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.PrimitiveType; import com.oracle.truffle.llvm.runtime.types.StructureType; import com.oracle.truffle.llvm.runtime.types.Type; import com.oracle.truffle.llvm.runtime.types.VariableBitWidthType; import com.oracle.truffle.llvm.runtime.types.symbols.Symbol; final class LLVMBitcodeInstructionVisitor implements InstructionVisitor { private final LLVMBitcodeFunctionVisitor method; private final InstructionBlock block; private final LLVMSymbolResolver symbols; private final SulongNodeFactory nodeFactory; private final LLVMParserRuntime runtime; LLVMBitcodeInstructionVisitor(LLVMBitcodeFunctionVisitor method, InstructionBlock block, SulongNodeFactory nodeFactory) { this.method = method; this.block = block; this.symbols = method.getSymbolResolver(); this.nodeFactory = nodeFactory; this.runtime = method.getRuntime(); } @Override public void visit(AllocateInstruction allocate) { final Type type = allocate.getPointeeType(); int alignment; if (allocate.getAlign() == 0) { alignment = runtime.getByteAlignment(type); } else { alignment = 1 << (allocate.getAlign() - 1); } if (alignment == 0) { alignment = LLVMStack.NO_ALIGNMENT_REQUIREMENTS; } final int size = runtime.getByteSize(type); final Symbol count = allocate.getCount(); final LLVMExpressionNode result; if (count instanceof NullConstant) { result = nodeFactory.createAlloc(runtime, type, size, alignment, null, null); } else if (count instanceof IntegerConstant) { if (type instanceof VariableBitWidthType) { result = nodeFactory.createAlloc(runtime, type, size * (int) ((IntegerConstant) count).getValue(), alignment, null, null); } else { result = nodeFactory.createAlloc(runtime, type, size * (int) ((IntegerConstant) count).getValue(), alignment, null, null); } } else { LLVMExpressionNode num = symbols.resolve(count); result = nodeFactory.createAlloc(runtime, type, size, alignment, count.getType(), num); } createFrameWrite(result, allocate); } @Override public void visit(BinaryOperationInstruction operation) { LLVMExpressionNode lhs = symbols.resolve(operation.getLHS()); LLVMExpressionNode rhs = symbols.resolve(operation.getRHS()); final Type type = operation.getType(); final LLVMArithmeticInstructionType opA = LLVMBitcodeTypeHelper.toArithmeticInstructionType(operation.getOperator()); if (opA != null) { final LLVMExpressionNode result = nodeFactory.createArithmeticOperation(runtime, lhs, rhs, opA, type); createFrameWrite(result, operation); return; } final LLVMLogicalInstructionKind opL = LLVMBitcodeTypeHelper.toLogicalInstructionType(operation.getOperator()); if (opL != null) { final LLVMExpressionNode result = nodeFactory.createLogicalOperation(runtime, lhs, rhs, opL, type); createFrameWrite(result, operation); return; } throw new RuntimeException("Missed a binary operator"); } @Override public void visit(BranchInstruction branch) { method.addTerminatingInstruction(nodeFactory.createUnconditionalBranch(runtime, method.labels().get(branch.getSuccessor().getName()), getPhiWriteNodes(branch.getSuccessors())[0], runtime.getSourceSection(branch)), block.getBlockIndex(), block.getName()); } @Override public void visit(CallInstruction call) { final Type targetType = call.getType(); int argumentCount = getArgumentCount(call, targetType); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[argumentCount]; final Type[] argTypes = new Type[argumentCount]; int argIndex = 0; if (targetType instanceof StructureType) { final int size = runtime.getByteSize(targetType); final int align = runtime.getByteAlignment(targetType); argTypes[argIndex] = new PointerType(targetType); argNodes[argIndex] = nodeFactory.createAlloc(runtime, targetType, size, align, null, null); argIndex++; } for (int i = 0; argIndex < argumentCount; i++, argIndex++) { argNodes[argIndex] = symbols.resolve(call.getArgument(i)); argTypes[argIndex] = call.getArgument(i).getType(); } final SourceSection sourceSection = runtime.getSourceSection(call); final Symbol target = call.getCallTarget(); LLVMExpressionNode result = nodeFactory.createLLVMBuiltin(target, argNodes, method.getArgCount(), sourceSection); if (result == null) { if (target instanceof InlineAsmConstant) { final InlineAsmConstant inlineAsmConstant = (InlineAsmConstant) target; result = createInlineAssemblerNode(inlineAsmConstant, argNodes, argTypes, targetType, sourceSection); } else { LLVMExpressionNode function = symbols.resolve(target); result = nodeFactory.createFunctionCall(runtime, function, argNodes, new FunctionType(targetType, argTypes, false), sourceSection); } } createFrameWrite(result, call); } @Override public void visit(LandingpadInstruction landingpadInstruction) { Type type = landingpadInstruction.getType(); final int size = runtime.getByteSize(type); final int align = runtime.getByteAlignment(type); LLVMExpressionNode allocateLandingPadValue = nodeFactory.createAlloc(runtime, type, size, align, null, null); LLVMExpressionNode[] entries = new LLVMExpressionNode[landingpadInstruction.getClauseSymbols().length]; for (int i = 0; i < entries.length; i++) { entries[i] = symbols.resolve(landingpadInstruction.getClauseSymbols()[i]); } FrameSlot exceptionSlot = method.getSlot(LLVMException.FRAME_SLOT_ID); LLVMExpressionNode landingPad = nodeFactory.createLandingPad(runtime, allocateLandingPadValue, exceptionSlot, landingpadInstruction.isCleanup(), landingpadInstruction.getClauseTypes(), entries); createFrameWrite(landingPad, landingpadInstruction); } @Override public void visit(ResumeInstruction resumeInstruction) { FrameSlot exceptionSlot = method.getSlot(LLVMException.FRAME_SLOT_ID); LLVMControlFlowNode resume = nodeFactory.createResumeInstruction(runtime, exceptionSlot, runtime.getSourceSection(resumeInstruction)); method.addTerminatingInstruction(resume, block.getBlockIndex(), block.getName()); } @Override public void visit(CompareExchangeInstruction cmpxchg) { final LLVMExpressionNode ptrNode = symbols.resolve(cmpxchg.getPtr()); final LLVMExpressionNode cmpNode = symbols.resolve(cmpxchg.getCmp()); final LLVMExpressionNode newNode = symbols.resolve(cmpxchg.getReplace()); final Type elementType = cmpxchg.getCmp().getType(); createFrameWrite(nodeFactory.createCompareExchangeInstruction(runtime, cmpxchg.getType(), elementType, ptrNode, cmpNode, newNode), cmpxchg); } @Override public void visit(VoidCallInstruction call) { final Symbol target = call.getCallTarget(); if (target instanceof FunctionDeclaration) { final String name = ((FunctionDeclaration) target).getName(); if ("@llvm.dbg.declare".equals(name) || "@llvm.dbg.value".equals(name)) { // these intrinsics are debug information and should be resolved during parsing, not // at runtime return; } } int explicitArgumentCount = call.getArgumentCount(); final LLVMExpressionNode[] args = new LLVMExpressionNode[explicitArgumentCount]; final Type[] argsType = new Type[explicitArgumentCount]; int argIndex = 0; for (int i = 0; i < explicitArgumentCount; i++) { args[argIndex] = symbols.resolve(call.getArgument(i)); argsType[argIndex] = call.getArgument(i).getType(); argIndex++; } final SourceSection sourceSection = runtime.getSourceSection(call); LLVMExpressionNode node = nodeFactory.createLLVMBuiltin(target, args, method.getArgCount(), sourceSection); if (node == null) { if (target instanceof InlineAsmConstant) { final InlineAsmConstant inlineAsmConstant = (InlineAsmConstant) target; node = createInlineAssemblerNode(inlineAsmConstant, args, argsType, call.getType(), sourceSection); } else { final LLVMExpressionNode function = symbols.resolve(target); final FunctionType functionType = new FunctionType(call.getType(), argsType, false); node = nodeFactory.createFunctionCall(runtime, function, args, functionType, sourceSection); } } method.addInstruction(node); } @Override public void visit(InvokeInstruction call) { final Type targetType = call.getType(); int argumentCount = getArgumentCount(call, targetType); final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[argumentCount]; final Type[] argTypes = new Type[argumentCount]; int argIndex = 0; if (targetType instanceof StructureType) { final int size = runtime.getByteSize(targetType); final int align = runtime.getByteAlignment(targetType); argTypes[argIndex] = new PointerType(targetType); argNodes[argIndex] = nodeFactory.createAlloc(runtime, targetType, size, align, null, null); argIndex++; } for (int i = 0; argIndex < argumentCount; i++, argIndex++) { argNodes[argIndex] = symbols.resolve(call.getArgument(i)); argTypes[argIndex] = call.getArgument(i).getType(); } final Symbol target = call.getCallTarget(); int regularIndex = method.labels().get(call.normalSuccessor().getName()); int unwindIndex = method.labels().get(call.unwindSuccessor().getName()); List<LLVMExpressionNode> normalPhiWriteNodes = new ArrayList<>(); List<LLVMExpressionNode> unwindPhiWriteNodes = new ArrayList<>(); List<Phi> phis = method.getPhiManager().get(block); if (phis != null) { for (Phi phi : phis) { FrameSlot slot = method.getSlot(phi.getPhiValue().getName()); LLVMExpressionNode value = symbols.resolve(phi.getValue()); LLVMExpressionNode phiWriteNode = nodeFactory.createFrameWrite(runtime, phi.getValue().getType(), value, slot, null); if (call.normalSuccessor() == phi.getBlock()) { normalPhiWriteNodes.add(phiWriteNode); } else { unwindPhiWriteNodes.add(phiWriteNode); } } } LLVMExpressionNode[] normalPhiWriteNodesArray = normalPhiWriteNodes.toArray(new LLVMExpressionNode[normalPhiWriteNodes.size()]); LLVMExpressionNode[] unwindPhiWriteNodesArray = unwindPhiWriteNodes.toArray(new LLVMExpressionNode[unwindPhiWriteNodes.size()]); final SourceSection sourceSection = runtime.getSourceSection(call); LLVMExpressionNode function = nodeFactory.createLLVMBuiltin(target, argNodes, method.getArgCount(), null); if (function == null) { function = symbols.resolve(target); } LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(runtime, method.getSlot(call.getName()), function, argNodes, new FunctionType(targetType, argTypes, false), regularIndex, unwindIndex, normalPhiWriteNodesArray, unwindPhiWriteNodesArray, sourceSection); method.addTerminatingInstruction(result, block.getBlockIndex(), block.getName()); } @Override public void visit(VoidInvokeInstruction call) { final Symbol target = call.getCallTarget(); int explicitArgumentCount = call.getArgumentCount(); final LLVMExpressionNode[] args = new LLVMExpressionNode[explicitArgumentCount]; final Type[] argsType = new Type[explicitArgumentCount]; int argIndex = 0; for (int i = 0; i < explicitArgumentCount; i++) { args[argIndex] = symbols.resolve(call.getArgument(i)); argsType[argIndex] = call.getArgument(i).getType(); argIndex++; } int regularIndex = method.labels().get(call.normalSuccessor().getName()); int unwindIndex = method.labels().get(call.unwindSuccessor().getName()); List<LLVMExpressionNode> normalPhiWriteNodes = new ArrayList<>(); List<LLVMExpressionNode> unwindPhiWriteNodes = new ArrayList<>(); List<Phi> phis = method.getPhiManager().get(block); if (phis != null) { for (Phi phi : phis) { FrameSlot slot = method.getSlot(phi.getPhiValue().getName()); LLVMExpressionNode value = symbols.resolve(phi.getValue()); LLVMExpressionNode phiWriteNode = nodeFactory.createFrameWrite(runtime, phi.getValue().getType(), value, slot, null); if (call.normalSuccessor() == phi.getBlock()) { normalPhiWriteNodes.add(phiWriteNode); } else { unwindPhiWriteNodes.add(phiWriteNode); } } } LLVMExpressionNode[] normalPhiWriteNodesArray = normalPhiWriteNodes.toArray(new LLVMExpressionNode[normalPhiWriteNodes.size()]); LLVMExpressionNode[] unwindPhiWriteNodesArray = unwindPhiWriteNodes.toArray(new LLVMExpressionNode[unwindPhiWriteNodes.size()]); final SourceSection sourceSection = runtime.getSourceSection(call); LLVMExpressionNode function = nodeFactory.createLLVMBuiltin(target, args, method.getArgCount(), null); if (function == null) { function = symbols.resolve(target); } LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(runtime, null, function, args, new FunctionType(call.getType(), argsType, false), regularIndex, unwindIndex, normalPhiWriteNodesArray, unwindPhiWriteNodesArray, sourceSection); method.addTerminatingInstruction(result, block.getBlockIndex(), block.getName()); } private static int getArgumentCount(CallInstruction call, final Type targetType) { int argumentCount = call.getArgumentCount(); if (targetType instanceof StructureType) { argumentCount++; } return argumentCount; } private static int getArgumentCount(InvokeInstruction call, final Type targetType) { int argumentCount = call.getArgumentCount(); if (targetType instanceof StructureType) { argumentCount++; } return argumentCount; } @Override public void visit(CastInstruction cast) { LLVMConversionType type = LLVMBitcodeTypeHelper.toConversionType(cast.getOperator()); LLVMExpressionNode fromNode = symbols.resolve(cast.getValue()); Type from = cast.getValue().getType(); Type to = cast.getType(); LLVMExpressionNode result = nodeFactory.createCast(runtime, fromNode, to, from, type); createFrameWrite(result, cast); } @Override public void visit(CompareInstruction compare) { LLVMExpressionNode result = nodeFactory.createComparison(runtime, compare.getOperator(), compare.getLHS().getType(), symbols.resolve(compare.getLHS()), symbols.resolve(compare.getRHS())); createFrameWrite(result, compare); } @Override public void visit(ConditionalBranchInstruction branch) { LLVMExpressionNode conditionNode = symbols.resolve(branch.getCondition()); int trueIndex = method.labels().get(branch.getTrueSuccessor().getName()); int falseIndex = method.labels().get(branch.getFalseSuccessor().getName()); LLVMExpressionNode[][] phiWriteNodes = getPhiWriteNodes(branch.getSuccessors()); LLVMControlFlowNode node = nodeFactory.createConditionalBranch(runtime, trueIndex, falseIndex, conditionNode, phiWriteNodes[0], phiWriteNodes[1], runtime.getSourceSection(branch)); method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } @Override public void visit(ExtractElementInstruction extract) { LLVMExpressionNode vector = symbols.resolve(extract.getVector()); LLVMExpressionNode index = symbols.resolve(extract.getIndex()); Type resultType = extract.getType(); LLVMExpressionNode result = nodeFactory.createExtractElement(runtime, resultType, vector, index); createFrameWrite(result, extract); } @Override public void visit(ExtractValueInstruction extract) { if (!(extract.getAggregate().getType() instanceof ArrayType || extract.getAggregate().getType() instanceof StructureType || extract.getAggregate().getType() instanceof PointerType)) { throw new IllegalStateException("\'extractvalue\' can only extract elements of arrays and structs!"); } final LLVMExpressionNode baseAddress = symbols.resolve(extract.getAggregate()); final Type baseType = extract.getAggregate().getType(); final int targetIndex = extract.getIndex(); final Type resultType = extract.getType(); LLVMExpressionNode targetAddress = baseAddress; final AggregateType aggregateType = (AggregateType) baseType; int offset = runtime.getIndexOffset(targetIndex, aggregateType); final Type targetType = aggregateType.getElementType(targetIndex); if (targetType != null && !((targetType instanceof StructureType) && (((StructureType) targetType).isPacked()))) { offset += runtime.getBytePadding(offset, targetType); } if (offset != 0) { final LLVMExpressionNode oneLiteralNode = nodeFactory.createLiteral(runtime, 1, PrimitiveType.I32); targetAddress = nodeFactory.createTypedElementPointer(runtime, targetAddress, oneLiteralNode, offset, extract.getType()); } final LLVMExpressionNode result = nodeFactory.createExtractValue(runtime, resultType, targetAddress); createFrameWrite(result, extract); } @Override public void visit(GetElementPointerInstruction gep) { final LLVMExpressionNode targetAddress = symbols.resolveElementPointer(gep.getBasePointer(), gep.getIndices()); createFrameWrite(targetAddress, gep); } @Override public void visit(IndirectBranchInstruction branch) { if (branch.getSuccessorCount() > 1) { int[] labelTargets = new int[branch.getSuccessorCount()]; for (int i = 0; i < labelTargets.length; i++) { labelTargets[i] = method.labels().get(branch.getSuccessor(i).getName()); } LLVMExpressionNode value = symbols.resolve(branch.getAddress()); LLVMControlFlowNode node = nodeFactory.createIndirectBranch(runtime, value, labelTargets, getPhiWriteNodes(branch.getSuccessors()), runtime.getSourceSection(branch)); method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } else { assert branch.getSuccessorCount() == 1; LLVMControlFlowNode node = nodeFactory.createUnconditionalBranch(runtime, method.labels().get(branch.getSuccessor(0).getName()), getPhiWriteNodes(branch.getSuccessors())[0], runtime.getSourceSection(branch)); method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } } @Override public void visit(InsertElementInstruction insert) { final LLVMExpressionNode vector = symbols.resolve(insert.getVector()); final LLVMExpressionNode index = symbols.resolve(insert.getIndex()); final LLVMExpressionNode element = symbols.resolve(insert.getValue()); final Type type = insert.getType(); final LLVMExpressionNode result = nodeFactory.createInsertElement(runtime, type, vector, element, index); createFrameWrite(result, insert); } @Override public void visit(InsertValueInstruction insert) { if (!(insert.getAggregate().getType() instanceof StructureType || insert.getAggregate().getType() instanceof ArrayType)) { throw new IllegalStateException("\'insertvalue\' can only insert values into arrays and structs!"); } final AggregateType sourceType = (AggregateType) insert.getAggregate().getType(); final LLVMExpressionNode sourceAggregate = symbols.resolve(insert.getAggregate()); final LLVMExpressionNode valueToInsert = symbols.resolve(insert.getValue()); final Type valueType = insert.getValue().getType(); final int targetIndex = insert.getIndex(); final int size = runtime.getByteSize(sourceType); final int alignment = runtime.getByteAlignment(sourceType); final LLVMExpressionNode resultAggregate = nodeFactory.createAlloc(runtime, sourceType, size, alignment, null, null); final int offset = runtime.getIndexOffset(targetIndex, sourceType); final LLVMExpressionNode result = nodeFactory.createInsertValue(runtime, resultAggregate, sourceAggregate, runtime.getByteSize(sourceType), offset, valueToInsert, valueType); createFrameWrite(result, insert); } @Override public void visit(LoadInstruction load) { LLVMExpressionNode source = symbols.resolve(load.getSource()); LLVMExpressionNode result = nodeFactory.createLoad(runtime, load.getType(), source); createFrameWrite(result, load); } @Override public void visit(PhiInstruction phi) { // TODO add sourcesection to this phi } @Override public void visit(ReturnInstruction ret) { LLVMControlFlowNode node; if (ret.getValue() == null) { node = nodeFactory.createRetVoid(runtime, runtime.getSourceSection(ret)); } else { final Type type = ret.getValue().getType(); final LLVMExpressionNode value = symbols.resolve(ret.getValue()); node = nodeFactory.createNonVoidRet(runtime, value, type, runtime.getSourceSection(ret)); } method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } @Override public void visit(SelectInstruction select) { final LLVMExpressionNode condition = symbols.resolve(select.getCondition()); final LLVMExpressionNode trueValue = symbols.resolve(select.getTrueValue()); final LLVMExpressionNode falseValue = symbols.resolve(select.getFalseValue()); final Type type = select.getType(); final LLVMExpressionNode result = nodeFactory.createSelect(runtime, type, condition, trueValue, falseValue); createFrameWrite(result, select); } @Override public void visit(ShuffleVectorInstruction shuffle) { final LLVMExpressionNode vector1 = symbols.resolve(shuffle.getVector1()); final LLVMExpressionNode vector2 = symbols.resolve(shuffle.getVector2()); final LLVMExpressionNode mask = symbols.resolve(shuffle.getMask()); final Type type = shuffle.getType(); final LLVMExpressionNode result = nodeFactory.createShuffleVector(runtime, type, vector1, vector2, mask); createFrameWrite(result, shuffle); } @Override public void visit(StoreInstruction store) { final LLVMExpressionNode pointerNode = symbols.resolve(store.getDestination()); final LLVMExpressionNode valueNode = symbols.resolve(store.getSource()); Type type = store.getSource().getType(); final LLVMExpressionNode node = nodeFactory.createStore(runtime, pointerNode, valueNode, type, runtime.getSourceSection(store)); method.addInstruction(node); } @Override public void visit(SwitchInstruction zwitch) { LLVMExpressionNode cond = symbols.resolve(zwitch.getCondition()); int[] successors = new int[zwitch.getCaseCount() + 1]; for (int i = 0; i < successors.length - 1; i++) { successors[i] = method.labels().get(zwitch.getCaseBlock(i).getName()); } successors[successors.length - 1] = method.labels().get(zwitch.getDefaultBlock().getName()); Type llvmType = zwitch.getCondition().getType(); LLVMExpressionNode[] cases = new LLVMExpressionNode[zwitch.getCaseCount()]; for (int i = 0; i < cases.length; i++) { cases[i] = symbols.resolve(zwitch.getCaseValue(i)); } LLVMControlFlowNode node = nodeFactory.createSwitch(runtime, cond, successors, cases, (PrimitiveType) llvmType, getPhiWriteNodes(zwitch.getSuccessors()), runtime.getSourceSection(zwitch)); method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } private LLVMExpressionNode[][] getPhiWriteNodes(List<InstructionBlock> successors) { List<Phi> phis = method.getPhiManager().get(block); if (phis != null) { ArrayList<Phi>[] phisPerSuccessor = collectPhis(successors, phis); return convertToPhiWriteNodes(phisPerSuccessor); } return new LLVMExpressionNode[successors.size()][0]; } private static ArrayList<Phi>[] collectPhis(List<InstructionBlock> successors, List<Phi> phis) { @SuppressWarnings("unchecked") ArrayList<Phi>[] phisPerSuccessor = new ArrayList[successors.size()]; for (int i = 0; i < phisPerSuccessor.length; i++) { phisPerSuccessor[i] = new ArrayList<>(); } for (Phi phi : phis) { assignPhiToSuccessor(successors, phi, phisPerSuccessor); } return phisPerSuccessor; } private static void assignPhiToSuccessor(List<InstructionBlock> successors, Phi phi, ArrayList<Phi>[] phisPerSuccessor) { for (int i = 0; i < successors.size(); i++) { if (successors.get(i) == phi.getBlock()) { ArrayList<Phi> phis = phisPerSuccessor[i]; if (!hasMatchingPhi(phis, phi)) { phis.add(phi); return; } } } throw new RuntimeException("Could not find a matching successor for a phi."); } private static boolean hasMatchingPhi(ArrayList<Phi> possiblePhiList, Phi phi) { for (int j = 0; j < possiblePhiList.size(); j++) { if (possiblePhiList.get(j).getPhiValue() == phi.getPhiValue()) { // this successor already has a phi that corresponds to the same phi symbol -> it // can't be for that successor. this case happens when we have the same successor // block multiple times in the list of the successors. return true; } } return false; } private LLVMExpressionNode[][] convertToPhiWriteNodes(ArrayList<Phi>[] phisPerSuccessor) { LLVMExpressionNode[][] result = new LLVMExpressionNode[phisPerSuccessor.length][]; for (int i = 0; i < result.length; i++) { result[i] = new LLVMExpressionNode[phisPerSuccessor[i].size()]; for (int j = 0; j < phisPerSuccessor[i].size(); j++) { Phi phi = phisPerSuccessor[i].get(j); FrameSlot slot = method.getSlot(phi.getPhiValue().getName()); LLVMExpressionNode value = symbols.resolve(phi.getValue()); Type baseType = phi.getValue().getType(); LLVMExpressionNode phiWriteNode = nodeFactory.createFrameWrite(runtime, baseType, value, slot, null); result[i][j] = phiWriteNode; } } return result; } @Override public void visit(SwitchOldInstruction zwitch) { LLVMExpressionNode cond = symbols.resolve(zwitch.getCondition()); int[] successors = new int[zwitch.getCaseCount() + 1]; for (int i = 0; i < successors.length - 1; i++) { successors[i] = method.labels().get(zwitch.getCaseBlock(i).getName()); } successors[successors.length - 1] = method.labels().get(zwitch.getDefaultBlock().getName()); final PrimitiveType llvmType = (PrimitiveType) zwitch.getCondition().getType(); final LLVMExpressionNode[] cases = new LLVMExpressionNode[zwitch.getCaseCount()]; for (int i = 0; i < cases.length; i++) { // the case value is always a long here regardless of the values actual type, implicit // casts to smaller types in the factoryfacade won't work switch (llvmType.getPrimitiveKind()) { case I8: cases[i] = nodeFactory.createLiteral(runtime, (byte) zwitch.getCaseValue(i), llvmType); break; case I16: cases[i] = nodeFactory.createLiteral(runtime, (short) zwitch.getCaseValue(i), llvmType); break; case I32: cases[i] = nodeFactory.createLiteral(runtime, (int) zwitch.getCaseValue(i), llvmType); break; default: cases[i] = nodeFactory.createLiteral(runtime, zwitch.getCaseValue(i), llvmType); } } LLVMControlFlowNode node = nodeFactory.createSwitch(runtime, cond, successors, cases, llvmType, getPhiWriteNodes(zwitch.getSuccessors()), runtime.getSourceSection(zwitch)); method.addTerminatingInstruction(node, block.getBlockIndex(), block.getName()); } @Override public void visit(UnreachableInstruction ui) { method.addTerminatingInstruction(nodeFactory.createUnreachableNode(runtime), block.getBlockIndex(), block.getName()); } private void createFrameWrite(LLVMExpressionNode result, ValueInstruction source) { final LLVMExpressionNode node = nodeFactory.createFrameWrite(runtime, source.getType(), result, method.getSlot(source.getName()), runtime.getSourceSection(source)); method.addInstruction(node); } private LLVMExpressionNode createInlineAssemblerNode(InlineAsmConstant inlineAsmConstant, LLVMExpressionNode[] argNodes, Type[] argsType, Type retType, SourceSection sourceSection) { if (inlineAsmConstant.hasSideEffects()) { LLVMLogger.info("Parsing Inline Assembly Constant with Sideeffects!"); } if (inlineAsmConstant.needsAlignedStack()) { throw new UnsupportedOperationException("Assembly Expressions that require an aligned Stack are not supported yet!"); } if (inlineAsmConstant.getDialect() != AsmDialect.AT_T) { throw new UnsupportedOperationException("Unsupported Assembly Dialect: " + inlineAsmConstant.getDialect()); } return nodeFactory.createInlineAssemblerExpression(runtime, inlineAsmConstant.getAsmExpression(), inlineAsmConstant.getAsmFlags(), argNodes, argsType, retType, sourceSection); } }