package com.oracle.truffle.llvm.parser.nodes;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.llvm.parser.LLVMLivenessAnalysis;
import com.oracle.truffle.llvm.parser.LLVMPhiManager;
import com.oracle.truffle.llvm.parser.LLVMPhiManager.Phi;
import com.oracle.truffle.llvm.parser.metadata.DwarfOpcode;
import com.oracle.truffle.llvm.parser.metadata.MDExpression;
import com.oracle.truffle.llvm.parser.metadata.debuginfo.SourceVariable;
import com.oracle.truffle.llvm.parser.metadata.debuginfo.ValueFragment;
import com.oracle.truffle.llvm.parser.model.SymbolImpl;
import com.oracle.truffle.llvm.parser.model.attributes.Attribute;
import com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup;
import com.oracle.truffle.llvm.parser.model.enums.AsmDialect;
import com.oracle.truffle.llvm.parser.model.enums.ReadModifyWriteOperator;
import com.oracle.truffle.llvm.parser.model.symbols.constants.AbstractConstant;
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.UndefinedConstant;
import com.oracle.truffle.llvm.parser.model.symbols.constants.integer.IntegerConstant;
import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalValueSymbol;
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.DbgDeclareInstruction;
import com.oracle.truffle.llvm.parser.model.symbols.instructions.DbgValueInstruction;
import com.oracle.truffle.llvm.parser.model.symbols.instructions.DebugTrapInstruction;
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.FenceInstruction;
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.Instruction;
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.ReadModifyWriteInstruction;
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.TerminatingInstruction;
import com.oracle.truffle.llvm.parser.model.symbols.instructions.UnaryOperationInstruction;
import com.oracle.truffle.llvm.parser.model.symbols.instructions.UnreachableInstruction;
import com.oracle.truffle.llvm.parser.model.symbols.instructions.VaArgInstruction;
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.SymbolVisitor;
import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation.ClearLocalVariableParts;
import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation.InitAggreateLocalVariable;
import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation.LocalVarDebugInfo;
import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation.SetLocalVariablePart;
import com.oracle.truffle.llvm.parser.nodes.LLVMRuntimeDebugInformation.SimpleLocalVariable;
import com.oracle.truffle.llvm.parser.util.LLVMBitcodeTypeHelper;
import com.oracle.truffle.llvm.runtime.CommonNodeFactory;
import com.oracle.truffle.llvm.runtime.LLVMContext;
import com.oracle.truffle.llvm.runtime.NodeFactory;
import com.oracle.truffle.llvm.runtime.datalayout.DataLayout;
import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation;
import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType;
import com.oracle.truffle.llvm.runtime.except.LLVMParserException;
import com.oracle.truffle.llvm.runtime.except.LLVMUserException;
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.nodes.api.LLVMFrameNullerExpressionNodeGen;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMFrameNullerNodeGen;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMInstrumentableNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMVoidStatementNodeGen;
import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNode;
import com.oracle.truffle.llvm.runtime.options.SulongEngineOption;
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.MetaType;
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.Type.TypeArrayBuilder;
import com.oracle.truffle.llvm.runtime.types.Type.TypeOverflowException;
import com.oracle.truffle.llvm.runtime.types.symbols.SSAValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
public final class LLVMBitcodeInstructionVisitor implements SymbolVisitor {
private final LLVMContext context;
private final NodeFactory nodeFactory;
private final FrameDescriptor frame;
private final List<LLVMPhiManager.Phi> blockPhis;
private final int argCount;
private final LLVMSymbolReadResolver symbols;
private final ArrayList<LLVMLivenessAnalysis.NullerInformation> nullerInfos;
private final LLVMStack.UniquesRegion uniquesRegion;
private final DataLayout dataLayout;
private final HashSet<Integer> neededForDebug;
private final ArrayList<LLVMNode> instructionNodes;
private final ArrayList<SSAValue> instructionTargets;
private final ArrayList<LocalVarDebugInfo> debugInfo;
private SSAValue[] nullerInfo;
private LLVMControlFlowNode controlFlowNode;
private LLVMSourceLocation lastLocation;
private boolean optimizeFrameSlots;
public LLVMBitcodeInstructionVisitor(FrameDescriptor frame, LLVMStack.UniquesRegion uniquesRegion, List<LLVMPhiManager.Phi> blockPhis, int argCount, LLVMSymbolReadResolver symbols,
LLVMContext context, ArrayList<LLVMLivenessAnalysis.NullerInformation> nullerInfos, HashSet<Integer> neededForDebug, DataLayout dataLayout,
NodeFactory nodeFactory) {
this.context = context;
this.neededForDebug = neededForDebug;
this.nodeFactory = nodeFactory;
this.frame = frame;
this.blockPhis = blockPhis;
this.argCount = argCount;
this.symbols = symbols;
this.nullerInfos = nullerInfos;
this.uniquesRegion = uniquesRegion;
this.dataLayout = dataLayout;
this.instructionNodes = new ArrayList<>();
this.instructionTargets = new ArrayList<>();
this.debugInfo = new ArrayList<>();
this.optimizeFrameSlots = context.getEnv().getOptions().get(SulongEngineOption.OPTIMIZE_FRAME_SLOTS) && !context.getEnv().getOptions().get(SulongEngineOption.LL_DEBUG);
}
public LLVMControlFlowNode getControlFlowNode() {
return controlFlowNode;
}
public void setInstructionIndex(int instructionIndex) {
assert instructionNodes.size() == instructionTargets.size();
if (!nullerInfos.isEmpty()) {
assert nullerInfos.get(nullerInfos.size() - 1).getInstructionIndex() >= instructionIndex : "we either missed an instruction or the nuller information is not sorted correctly";
int last = nullerInfos.size();
while (last > 0 && nullerInfos.get(last - 1).getInstructionIndex() == instructionIndex) {
last--;
}
if (last < nullerInfos.size()) {
SSAValue[] slots = new SSAValue[nullerInfos.size() - last];
for (int i = slots.length - 1; i >= 0; i--) {
slots[i] = nullerInfos.get(last + i).getIdentifier();
nullerInfos.remove(last + i);
}
nullerInfo = slots;
return;
}
}
nullerInfo = null;
}
public LLVMStatementNode[] finish() {
for (int i = 0; i < instructionNodes.size(); i++) {
LLVMNode node = instructionNodes.get(i);
SSAValue target = instructionTargets.get(i);
if (target == null) {
assert node instanceof LLVMStatementNode;
} else {
assert node instanceof LLVMExpressionNode;
instructionNodes.set(i, nodeFactory.createFrameWrite(target.getType(), (LLVMExpressionNode) node, symbols.findOrAddFrameSlot(frame, target)));
}
}
return instructionNodes.toArray(LLVMStatementNode.NO_STATEMENTS);
}
public LocalVarDebugInfo[] getDebugInfo() {
return debugInfo.toArray(new LocalVarDebugInfo[debugInfo.size()]);
}
private FrameSlot[] createNullerSlots(SSAValue[] stackValues) {
if (stackValues != null) {
int count = 0;
for (SSAValue value : stackValues) {
if (value != null) {
count++;
}
}
if (count > 0) {
int pos = 0;
FrameSlot[] result = new FrameSlot[count];
for (SSAValue value : stackValues) {
if (value != null) {
result[pos++] = symbols.findOrAddFrameSlot(frame, value);
}
}
return result;
}
}
return null;
}
public static FrameSlot findFrameSlot(FrameDescriptor frame, int frameIdentifier) {
return frame.findFrameSlot(frameIdentifier);
}
@Override
public void defaultAction(SymbolImpl symbol) {
throw new LLVMParserException("Instruction not implemented: " + symbol.getClass().getSimpleName());
}
private LLVMExpressionNode resolveOptimized(SymbolImpl symbol, int excludeOtherIndex, SymbolImpl other, SymbolImpl... others) {
if (optimizeFrameSlots && nullerInfo != null) {
if (symbol instanceof SSAValue) {
if (symbol == other || neededForDebug.contains(((SSAValue) symbol).getFrameIdentifier())) {
return symbols.resolve(symbol);
}
for (int i = 0; i < others.length; i++) {
SymbolImpl o = others[i];
if (i != excludeOtherIndex && symbol == o) {
return symbols.resolve(symbol);
}
}
for (int i = 0; i < nullerInfo.length; i++) {
if (nullerInfo[i] == symbol) {
if (frame.findFrameSlot(nullerInfo[i].getFrameIdentifier()) == null) {
LLVMExpressionNode node = extractNulledValue(nullerInfo[i]);
if (node != null) {
nullerInfo[i] = null;
return node;
}
}
break;
}
}
}
}
return symbols.resolve(symbol);
}
private LLVMExpressionNode resolveOptimized(SymbolImpl symbol, SymbolImpl... other) {
return resolveOptimized(symbol, -1, null, other);
}
private LLVMExpressionNode (SSAValue slot) {
assert slot != null;
if (instructionNodes.isEmpty()) {
return null;
}
SSAValue target = instructionTargets.get(instructionTargets.size() - 1);
if (target == slot) {
LLVMExpressionNode expression = (LLVMExpressionNode) instructionNodes.get(instructionNodes.size() - 1);
instructionNodes.remove(instructionNodes.size() - 1);
instructionTargets.remove(instructionTargets.size() - 1);
return expression;
}
return null;
}
@Override
public void visit(AllocateInstruction allocate) {
final Type type = allocate.getPointeeType();
int alignment;
if (allocate.getAlign() == 0) {
alignment = type.getAlignment(dataLayout);
} else {
alignment = 1 << (allocate.getAlign() - 1);
}
if (alignment == 0) {
alignment = LLVMStack.NO_ALIGNMENT_REQUIREMENTS;
}
final SymbolImpl count = allocate.getCount();
LLVMExpressionNode result;
if (count instanceof NullConstant) {
result = nodeFactory.createAlloca(type, alignment);
} else if (count instanceof IntegerConstant) {
long numElements = ((IntegerConstant) count).getValue();
if (numElements == 1) {
result = nodeFactory.createAlloca(type, alignment);
} else {
ArrayType arrayType = new ArrayType(type, numElements);
result = nodeFactory.createAlloca(arrayType, alignment);
}
} else {
LLVMExpressionNode num = resolveOptimized(count);
result = nodeFactory.createAllocaArray(type, num, alignment);
}
final SourceInstrumentationStrategy intention;
if (context.getEnv().getOptions().get(SulongEngineOption.LL_DEBUG)) {
intention = SourceInstrumentationStrategy.FORCED;
} else {
intention = SourceInstrumentationStrategy.DISABLED;
}
createFrameWrite(result, allocate, intention);
}
@Override
public void visit(BinaryOperationInstruction operation) {
SymbolImpl rhs = operation.getRHS();
SymbolImpl lhs = operation.getLHS();
LLVMExpressionNode rhsNode = resolveOptimized(rhs, lhs);
LLVMExpressionNode lhsNode = resolveOptimized(lhs, rhs);
LLVMExpressionNode result = LLVMBitcodeTypeHelper.createArithmeticInstruction(lhsNode, rhsNode, operation.getOperator(), operation.getType(), nodeFactory);
createFrameWrite(result, operation);
}
@Override
public void visit(UnaryOperationInstruction operation) {
SymbolImpl operand = operation.getOperand();
LLVMExpressionNode operandNode = resolveOptimized(operand);
LLVMExpressionNode result = LLVMBitcodeTypeHelper.createUnaryInstruction(operandNode, operation.getOperator(), operation.getType(), nodeFactory);
createFrameWrite(result, operation);
}
@Override
public void visit(BranchInstruction branch) {
LLVMControlFlowNode unconditionalBranchNode = nodeFactory.createUnconditionalBranch(branch.getSuccessor().getBlockIndex(),
getPhiWriteNodes(branch)[0]);
setControlFlowNode(unconditionalBranchNode, branch);
}
@Override
public void visit(CallInstruction 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++;
if (targetType instanceof StructureType) {
argTypes.set(argIndex, new PointerType(targetType));
argNodes[argIndex] = nodeFactory.createGetUniqueStackSpace(targetType, uniquesRegion, frame);
argIndex++;
}
final SymbolImpl target = call.getCallTarget();
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);
if (isByValue(paramAttr)) {
argNodes[argIndex + i] = capsuleAddressByValue(argNodes[argIndex + i], argTypes.get(argIndex + i), paramAttr);
}
}
LLVMExpressionNode result = nodeFactory.createLLVMBuiltin(target, argNodes, argTypes, argCount);
SourceInstrumentationStrategy intent = SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION;
if (result == null) {
if (target instanceof InlineAsmConstant) {
final InlineAsmConstant inlineAsmConstant = (InlineAsmConstant) target;
result = createInlineAssemblerNode(inlineAsmConstant, argNodes, argTypes, targetType);
} else {
LLVMExpressionNode function = symbols.resolve(target);
result = CommonNodeFactory.createFunctionCall(function, argNodes, new FunctionType(targetType, argTypes, false));
intent = SourceInstrumentationStrategy.FORCED;
}
}
createFrameWrite(result, call, intent);
}
@Override
public void visit(LandingpadInstruction landingpadInstruction) {
Type type = landingpadInstruction.getType();
LLVMExpressionNode allocateLandingPadValue = nodeFactory.createGetUniqueStackSpace(type, uniquesRegion, frame);
LLVMExpressionNode[] entries = new LLVMExpressionNode[landingpadInstruction.getClauseSymbols().length];
for (int i = 0; i < entries.length; i++) {
entries[i] = symbols.resolve(landingpadInstruction.getClauseSymbols()[i]);
}
LLVMExpressionNode getStack = nodeFactory.createGetStackFromFrame();
LLVMExpressionNode landingPad = nodeFactory.createLandingPad(allocateLandingPadValue, getExceptionSlot(), landingpadInstruction.isCleanup(), landingpadInstruction.getClauseTypes(),
entries, getStack);
createFrameWrite(landingPad, landingpadInstruction);
}
@Override
public void visit(ResumeInstruction resumeInstruction) {
LLVMControlFlowNode resume = nodeFactory.createResumeInstruction(getExceptionSlot());
setControlFlowNode(resume, resumeInstruction);
}
@Override
public void visit(CompareExchangeInstruction cmpxchg) {
SymbolImpl ptr = cmpxchg.getPtr();
SymbolImpl cmp = cmpxchg.getCmp();
SymbolImpl replace = cmpxchg.getReplace();
LLVMExpressionNode newNode = resolveOptimized(replace, ptr, cmp);
LLVMExpressionNode cmpNode = resolveOptimized(cmp, ptr, replace);
LLVMExpressionNode ptrNode = resolveOptimized(ptr, cmp, replace);
LLVMExpressionNode result = nodeFactory.createCompareExchangeInstruction(cmpxchg.getAggregateType(), cmp.getType(), ptrNode, cmpNode, newNode);
createFrameWrite(result, cmpxchg);
}
@Override
public void visit(VaArgInstruction vaArgInst) {
LLVMExpressionNode source = resolveOptimized(vaArgInst.getSource());
LLVMExpressionNode result = CommonNodeFactory.createVaArg(vaArgInst.getType(), source);
createFrameWrite(result, vaArgInst);
}
public void initializeAggregateLocalVariable(SourceVariable variable) {
assert instructionNodes.size() == 0;
debugInfo.add(new InitAggreateLocalVariable(0, variable));
}
private void handleDebugIntrinsic(SymbolImpl value, SourceVariable variable, MDExpression expression, long index, boolean isDeclaration) {
if (index != 0) {
return;
}
int valueFrameIdentifier = -1;
Object valueObject = null;
if (value instanceof UndefinedConstant) {
valueObject = symbols.resolve(new NullConstant(MetaType.DEBUG));
} else if (value instanceof AbstractConstant) {
valueObject = symbols.resolve(value);
} else if (value instanceof GlobalValueSymbol) {
valueObject = symbols.resolve(value);
} else if (value instanceof SSAValue) {
valueFrameIdentifier = ((SSAValue) value).getFrameIdentifier();
} else {
return;
}
if (valueObject == null && valueFrameIdentifier == -1) {
return;
}
int partIndex = -1;
int[] clearParts = null;
if (ValueFragment.describesFragment(expression)) {
ValueFragment fragment = ValueFragment.parse(expression);
List<ValueFragment> siblings = variable.getFragments();
List<Integer> clearSiblings = new ArrayList<>(siblings.size());
partIndex = ValueFragment.getPartIndex(fragment, siblings, clearSiblings);
if (!clearSiblings.isEmpty()) {
clearParts = clearSiblings.stream().mapToInt(Integer::intValue).toArray();
}
}
if (partIndex < 0 && variable.hasFragments()) {
partIndex = variable.getFragmentIndex(0, (int) variable.getSymbol().getType().getSize());
if (partIndex < 0) {
throw new LLVMParserException("Cannot find index of value fragment!");
}
clearParts = new int[variable.getFragments().size() - 1];
for (int i = 0; i < partIndex; i++) {
clearParts[i] = i;
}
for (int i = partIndex; i < clearParts.length; i++) {
clearParts[i] = i + 1;
}
}
boolean mustDereference = isDeclaration || mustDereferenceValue(expression, variable.getSourceType(), value);
if (clearParts != null && clearParts.length != 0) {
debugInfo.add(new ClearLocalVariableParts(instructionNodes.size(), variable.getSymbol(), clearParts));
}
if (partIndex < 0 && clearParts == null) {
debugInfo.add(new SimpleLocalVariable(instructionNodes.size(), mustDereference, valueObject, valueFrameIdentifier, variable.getSymbol()));
} else if (partIndex >= 0) {
debugInfo.add(new SetLocalVariablePart(instructionNodes.size(), mustDereference, valueObject, valueFrameIdentifier, variable.getSymbol(), partIndex));
}
}
private static boolean mustDereferenceValue(MDExpression expr, LLVMSourceType type, SymbolImpl value) {
return DwarfOpcode.isDeref(expr) || (type != null && !type.isPointer() && value instanceof AllocateInstruction);
}
@Override
public void visit(DbgDeclareInstruction inst) {
handleDebugIntrinsic(inst.getValue(), inst.getVariable(), inst.getExpression(), 0L, true);
handleNullerInfo();
}
@Override
public void visit(DbgValueInstruction inst) {
handleDebugIntrinsic(inst.getValue(), inst.getVariable(), inst.getExpression(), inst.getIndex(), false);
handleNullerInfo();
}
@Override
public void visit(DebugTrapInstruction inst) {
addStatement(CommonNodeFactory.createDebugTrap(), inst, SourceInstrumentationStrategy.FORCED);
}
@Override
public void visit(VoidCallInstruction call) {
final int argumentCount = call.getArgumentCount() + 1;
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++;
SymbolImpl target = call.getCallTarget();
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);
if (isByValue(paramAttr)) {
argNodes[argIndex + i] = capsuleAddressByValue(argNodes[argIndex + i], argTypes.get(argIndex + i), paramAttr);
}
}
LLVMExpressionNode result = nodeFactory.createLLVMBuiltin(target, argNodes, argTypes, argCount);
SourceInstrumentationStrategy intent = SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION;
if (result == null) {
if (target instanceof InlineAsmConstant) {
final InlineAsmConstant inlineAsmConstant = (InlineAsmConstant) target;
result = createInlineAssemblerNode(inlineAsmConstant, argNodes, argTypes, call.getType());
assignSourceLocation(result, call);
} else {
final LLVMExpressionNode function = resolveOptimized(target, call.getArguments());
final FunctionType functionType = new FunctionType(call.getType(), argTypes, false);
result = CommonNodeFactory.createFunctionCall(function, argNodes, functionType);
intent = SourceInstrumentationStrategy.FORCED;
}
}
addStatement(result, call, intent);
}
@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 (targetType instanceof StructureType) {
argTypes.set(argIndex, new PointerType(targetType));
argNodes[argIndex] = nodeFactory.createGetUniqueStackSpace(targetType, uniquesRegion, frame);
argIndex++;
}
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);
if (isByValue(paramAttr)) {
argNodes[argIndex + i] = capsuleAddressByValue(argNodes[argIndex + i], argTypes.get(argIndex + i), paramAttr);
}
}
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);
LLVMExpressionNode function = symbols.resolve(target);
LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(nodeFactory.createFrameWrite(targetType, null, symbols.findOrAddFrameSlot(frame, call)), function, argNodes,
new FunctionType(targetType, argTypes, false),
regularIndex, unwindIndex, normalPhi, unwindPhi);
setControlFlowNode(result, call, SourceInstrumentationStrategy.FORCED);
}
@Override
public void visit(VoidInvokeInstruction call) {
final SymbolImpl target = call.getCallTarget();
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++;
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);
if (isByValue(paramAttr)) {
args[argIndex + i] = capsuleAddressByValue(args[argIndex + i], argsType.get(argIndex + i), paramAttr);
}
}
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);
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);
}
private static int getArgumentCount(int argumentCount, final Type targetType) {
int count = argumentCount;
if (targetType instanceof StructureType) {
count++;
}
count++;
return count;
}
@Override
public void visit(CastInstruction cast) {
LLVMExpressionNode fromNode = resolveOptimized(cast.getValue());
Type from = cast.getValue().getType();
Type to = cast.getType();
LLVMExpressionNode result = LLVMBitcodeTypeHelper.createCast(fromNode, to, from, cast.getOperator(), nodeFactory);
createFrameWrite(result, cast);
}
@Override
public void visit(CompareInstruction compare) {
SymbolImpl rhs = compare.getRHS();
SymbolImpl lhs = compare.getLHS();
LLVMExpressionNode rhsNode = resolveOptimized(rhs, lhs);
LLVMExpressionNode lhsNode = resolveOptimized(lhs, rhs);
LLVMExpressionNode result = CommonNodeFactory.createComparison(compare.getOperator(), lhs.getType(), lhsNode, rhsNode);
createFrameWrite(result, compare);
}
@Override
public void visit(ConditionalBranchInstruction branch) {
LLVMExpressionNode conditionNode = symbols.resolve(branch.getCondition());
int trueIndex = branch.getTrueSuccessor().getBlockIndex();
int falseIndex = branch.getFalseSuccessor().getBlockIndex();
LLVMStatementNode[] phiWriteNodes = getPhiWriteNodes(branch);
LLVMControlFlowNode node = nodeFactory.createConditionalBranch(trueIndex, falseIndex, conditionNode, phiWriteNodes[0], phiWriteNodes[1]);
setControlFlowNode(node, branch);
}
@Override
public void (ExtractElementInstruction extract) {
SymbolImpl index = extract.getIndex();
SymbolImpl vector = extract.getVector();
LLVMExpressionNode indexNode = resolveOptimized(index, vector);
LLVMExpressionNode vectorNode = resolveOptimized(vector, index);
LLVMExpressionNode result = nodeFactory.createExtractElement(extract.getType(), vectorNode, indexNode);
createFrameWrite(result, extract);
}
@Override
public void (ExtractValueInstruction extract) {
if (!(extract.getAggregate().getType() instanceof ArrayType || extract.getAggregate().getType() instanceof StructureType || extract.getAggregate().getType() instanceof PointerType)) {
throw new LLVMParserException("\'extractvalue\' can only extract elements of arrays and structs!");
}
final LLVMExpressionNode baseAddress = resolveOptimized(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;
LLVMExpressionNode result;
try {
long offset = aggregateType.getOffsetOf(targetIndex, dataLayout);
final Type targetType = aggregateType.getElementType(targetIndex);
if (targetType != null && !((targetType instanceof StructureType) && (((StructureType) targetType).isPacked()))) {
offset = Type.addUnsignedExact(offset, Type.getPadding(offset, targetType, dataLayout));
}
if (offset != 0) {
final LLVMExpressionNode oneLiteralNode = CommonNodeFactory.createLiteral(1, PrimitiveType.I32);
targetAddress = nodeFactory.createTypedElementPointer(offset, extract.getType(), targetAddress, oneLiteralNode);
}
result = nodeFactory.createExtractValue(resultType, targetAddress);
} catch (TypeOverflowException e) {
result = Type.handleOverflowExpression(e);
}
createFrameWrite(result, extract);
}
@Override
public void visit(GetElementPointerInstruction gep) {
createFrameWrite(symbols.resolveElementPointer(gep.getBasePointer(), gep.getIndices(), this::resolveOptimized), 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] = branch.getSuccessor(i).getBlockIndex();
}
LLVMExpressionNode value = symbols.resolve(branch.getAddress());
LLVMControlFlowNode node = nodeFactory.createIndirectBranch(value, labelTargets, getPhiWriteNodes(branch));
setControlFlowNode(node, branch);
} else {
assert branch.getSuccessorCount() == 1;
LLVMControlFlowNode node = nodeFactory.createUnconditionalBranch(branch.getSuccessor(0).getBlockIndex(), getPhiWriteNodes(branch)[0]);
setControlFlowNode(node, branch);
}
}
@Override
public void visit(InsertElementInstruction insert) {
SymbolImpl index = insert.getIndex();
SymbolImpl value = insert.getValue();
SymbolImpl vector = insert.getVector();
LLVMExpressionNode indexNode = resolveOptimized(index, index, vector);
LLVMExpressionNode elementNode = resolveOptimized(value, value, vector);
LLVMExpressionNode vectorNode = resolveOptimized(vector, value, index);
LLVMExpressionNode result = nodeFactory.createInsertElement(insert.getType(), vectorNode, elementNode, indexNode);
createFrameWrite(result, insert);
}
@Override
public void visit(InsertValueInstruction insert) {
if (!(insert.getAggregate().getType() instanceof StructureType || insert.getAggregate().getType() instanceof ArrayType)) {
throw new LLVMParserException("\'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 LLVMExpressionNode resultAggregate = nodeFactory.createGetUniqueStackSpace(sourceType, uniquesRegion, frame);
LLVMExpressionNode result;
try {
final long offset = sourceType.getOffsetOf(targetIndex, dataLayout);
result = nodeFactory.createInsertValue(resultAggregate, sourceAggregate,
sourceType.getSize(dataLayout), offset, valueToInsert, valueType);
} catch (TypeOverflowException e) {
result = Type.handleOverflowExpression(e);
}
createFrameWrite(result, insert);
}
@Override
public void visit(LoadInstruction load) {
LLVMExpressionNode source = resolveOptimized(load.getSource());
LLVMExpressionNode result = nodeFactory.createLoad(load.getType(), source);
createFrameWrite(result, load);
}
@Override
public void visit(PhiInstruction phi) {
handleNullerInfo();
}
@Override
public void visit(ReturnInstruction ret) {
LLVMControlFlowNode node;
if (ret.getValue() == null) {
node = nodeFactory.createRetVoid();
} else {
final Type type = ret.getValue().getType();
final LLVMExpressionNode value = symbols.resolve(ret.getValue());
node = nodeFactory.createNonVoidRet(value, type);
}
setControlFlowNode(node, ret);
}
@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(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(type, vector1, vector2, mask);
createFrameWrite(result, shuffle);
}
@Override
public void visit(StoreInstruction store) {
SymbolImpl value = store.getSource();
SymbolImpl pointer = store.getDestination();
LLVMExpressionNode valueNode = resolveOptimized(value, pointer);
LLVMExpressionNode pointerNode = resolveOptimized(pointer, value);
SourceInstrumentationStrategy intention = SourceInstrumentationStrategy.DISABLED;
if (!(store.getSource() instanceof CallInstruction || store.getSource() instanceof InvokeInstruction) || context.getEnv().getOptions().get(SulongEngineOption.LL_DEBUG)) {
intention = SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION;
}
Type type = value.getType();
LLVMStatementNode node = nodeFactory.createStore(pointerNode, valueNode, type);
addStatement(node, store, intention);
}
@Override
public void visit(ReadModifyWriteInstruction rmw) {
SymbolImpl value = rmw.getValue();
SymbolImpl pointer = rmw.getPtr();
LLVMExpressionNode valueNode = resolveOptimized(value, pointer);
LLVMExpressionNode pointerNode = resolveOptimized(pointer, value);
Type type = rmw.getValue().getType();
LLVMExpressionNode result = createReadModifyWrite(rmw.getOperator(), pointerNode, valueNode, type);
createFrameWrite(result, rmw);
}
private LLVMExpressionNode createReadModifyWrite(ReadModifyWriteOperator op, LLVMExpressionNode pointerNode, LLVMExpressionNode valueNode, Type type) {
switch (op) {
case SUB:
return nodeFactory.createRMWSub(pointerNode, valueNode, type);
case XCHG:
return nodeFactory.createRMWXchg(pointerNode, valueNode, type);
case ADD:
return nodeFactory.createRMWAdd(pointerNode, valueNode, type);
case AND:
return nodeFactory.createRMWAnd(pointerNode, valueNode, type);
case NAND:
return nodeFactory.createRMWNand(pointerNode, valueNode, type);
case OR:
return nodeFactory.createRMWOr(pointerNode, valueNode, type);
case XOR:
return nodeFactory.createRMWXor(pointerNode, valueNode, type);
case MAX:
case MIN:
case UMIN:
case UMAX:
case FADD:
case FSUB:
default:
throw new LLVMParserException("Unsupported read-modify-write operation: " + op);
}
}
@Override
public void visit(FenceInstruction fence) {
addStatement(nodeFactory.createFence(), fence);
}
@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] = zwitch.getCaseBlock(i).getBlockIndex();
}
successors[successors.length - 1] = zwitch.getDefaultBlock().getBlockIndex();
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(cond, successors, cases, llvmType, getPhiWriteNodes(zwitch));
setControlFlowNode(node, zwitch);
}
private LLVMStatementNode[] getPhiWriteNodes(TerminatingInstruction terminatingInstruction) {
if (blockPhis != null) {
ArrayList<LLVMPhiManager.Phi>[] phisPerSuccessor = LLVMPhiManager.getPhisForSuccessors(terminatingInstruction, blockPhis);
return createPhiWriteNodes(phisPerSuccessor);
}
return new LLVMStatementNode[terminatingInstruction.getSuccessorCount()];
}
private LLVMStatementNode[] createPhiWriteNodes(ArrayList<Phi>[] phisPerSuccessor) {
if (phisPerSuccessor.length == 0) {
return LLVMStatementNode.NO_STATEMENTS;
}
LLVMStatementNode[] result = new LLVMStatementNode[phisPerSuccessor.length];
for (int i = 0; i < result.length; i++) {
result[i] = createPhiWriteNodes(phisPerSuccessor[i]);
}
return result;
}
private LLVMStatementNode createPhiWriteNodes(ArrayList<Phi> phis) {
if (phis.size() == 0) {
return null;
}
if (phis.size() == 1) {
Phi phi = phis.get(0);
return nodeFactory.createFrameWrite(phi.getValue().getType(), symbols.resolve(phi.getValue()), symbols.findOrAddFrameSlot(frame, phi.getPhiValue()));
}
HashMap<PhiInstruction, Phi> pendingPhis = new HashMap<>();
for (Phi phi : phis) {
pendingPhis.put(phi.getPhiValue(), phi);
}
ArrayList<Phi> ordinary = new ArrayList<>();
ArrayList<Phi> cycles = new ArrayList<>();
while (!pendingPhis.isEmpty()) {
boolean progress = false;
Iterator<Entry<PhiInstruction, Phi>> iter = pendingPhis.entrySet().iterator();
while (iter.hasNext()) {
Phi phi = iter.next().getValue();
if (!pendingPhis.containsKey(phi.getValue())) {
iter.remove();
ordinary.add(phi);
progress = true;
}
}
if (!progress) {
iter = pendingPhis.entrySet().iterator();
Phi phi = iter.next().getValue();
iter.remove();
cycles.add(phi);
}
}
LLVMExpressionNode[] cycleFrom = new LLVMExpressionNode[cycles.size()];
LLVMWriteNode[] cycleWrites = new LLVMWriteNode[cycles.size()];
LLVMWriteNode[] ordinaryWrites = new LLVMWriteNode[ordinary.size()];
for (int i = 0; i < cycles.size(); i++) {
Phi phi = cycles.get(i);
cycleFrom[i] = symbols.resolve(phi.getValue());
cycleWrites[i] = nodeFactory.createFrameWrite(phi.getValue().getType(), null, symbols.findOrAddFrameSlot(frame, phi.getPhiValue()));
}
for (int i = 0; i < ordinary.size(); i++) {
Phi phi = ordinary.get(ordinary.size() - 1 - i);
ordinaryWrites[i] = nodeFactory.createFrameWrite(phi.getValue().getType(), symbols.resolve(phi.getValue()), symbols.findOrAddFrameSlot(frame, phi.getPhiValue()));
}
return nodeFactory.createPhi(cycleFrom, cycleWrites, ordinaryWrites);
}
@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] = zwitch.getCaseBlock(i).getBlockIndex();
}
successors[successors.length - 1] = zwitch.getDefaultBlock().getBlockIndex();
final PrimitiveType llvmType = (PrimitiveType) zwitch.getCondition().getType();
final LLVMExpressionNode[] cases = new LLVMExpressionNode[zwitch.getCaseCount()];
for (int i = 0; i < cases.length; i++) {
switch (llvmType.getPrimitiveKind()) {
case I8:
cases[i] = CommonNodeFactory.createLiteral((byte) zwitch.getCaseValue(i), llvmType);
break;
case I16:
cases[i] = CommonNodeFactory.createLiteral((short) zwitch.getCaseValue(i), llvmType);
break;
case I32:
cases[i] = CommonNodeFactory.createLiteral((int) zwitch.getCaseValue(i), llvmType);
break;
default:
cases[i] = CommonNodeFactory.createLiteral(zwitch.getCaseValue(i), llvmType);
}
}
LLVMControlFlowNode node = nodeFactory.createSwitch(cond, successors, cases, llvmType, getPhiWriteNodes(zwitch));
setControlFlowNode(node, zwitch);
}
@Override
public void visit(UnreachableInstruction ui) {
final LLVMControlFlowNode node = nodeFactory.createUnreachableNode();
setControlFlowNode(node, ui);
}
public void handleNullerInfo() {
FrameSlot[] frameSlots = createNullerSlots(nullerInfo);
nullerInfo = null;
if (frameSlots != null) {
if (instructionNodes.isEmpty()) {
instructionNodes.add(LLVMFrameNullerNodeGen.create(frameSlots, null));
instructionTargets.add(null);
} else {
int index = instructionNodes.size() - 1;
LLVMNode node = instructionNodes.get(index);
if (node instanceof LLVMStatementNode) {
node = LLVMFrameNullerNodeGen.create(frameSlots, (LLVMStatementNode) node);
} else {
node = LLVMFrameNullerExpressionNodeGen.create(frameSlots, (LLVMExpressionNode) node);
}
instructionNodes.set(instructionNodes.size() - 1, node);
}
}
}
private void addNode(LLVMNode node, ValueInstruction target) {
instructionNodes.add(node);
instructionTargets.add(target);
}
private void createFrameWrite(LLVMExpressionNode result, ValueInstruction source) {
createFrameWrite(result, source, SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION);
}
private void createFrameWrite(LLVMExpressionNode result, ValueInstruction source, SourceInstrumentationStrategy intention) {
assignSourceLocation(result, source, intention);
addNode(result, source);
handleNullerInfo();
}
private LLVMExpressionNode createInlineAssemblerNode(InlineAsmConstant inlineAsmConstant, LLVMExpressionNode[] argNodes, TypeArrayBuilder argsType, Type retType) {
if (inlineAsmConstant.needsAlignedStack()) {
throw new LLVMParserException("Assembly Expressions that require an aligned Stack are not supported yet!");
}
if (inlineAsmConstant.getDialect() != AsmDialect.AT_T) {
throw new LLVMParserException("Unsupported Assembly Dialect: " + inlineAsmConstant.getDialect());
}
return nodeFactory.createInlineAssemblerExpression(inlineAsmConstant.getAsmExpression(), inlineAsmConstant.getAsmFlags(), argNodes, argsType, retType);
}
private FrameSlot getExceptionSlot() {
return frame.findFrameSlot(LLVMUserException.FRAME_SLOT_ID);
}
private void addStatement(LLVMStatementNode node, Instruction instruction) {
addStatement(node, instruction, SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION);
}
private void addStatement(LLVMExpressionNode node, Instruction instruction, SourceInstrumentationStrategy intention) {
assignSourceLocation(node, instruction, intention);
addNode(LLVMVoidStatementNodeGen.create(node), null);
handleNullerInfo();
}
private void addStatement(LLVMStatementNode node, Instruction instruction, SourceInstrumentationStrategy intention) {
assignSourceLocation(node, instruction, intention);
addNode(node, null);
handleNullerInfo();
}
private void setControlFlowNode(LLVMControlFlowNode controlFlowNode, Instruction sourceInstruction) {
setControlFlowNode(controlFlowNode, sourceInstruction, SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION);
}
private void setControlFlowNode(LLVMControlFlowNode controlFlowNode, Instruction sourceInstruction, SourceInstrumentationStrategy intention) {
assert this.controlFlowNode == null;
this.controlFlowNode = controlFlowNode;
assignSourceLocation(controlFlowNode, sourceInstruction, intention);
}
private LLVMExpressionNode capsuleAddressByValue(LLVMExpressionNode child, Type type, AttributesGroup paramAttr) {
try {
final Type pointee = ((PointerType) type).getPointeeType();
final long size = pointee.getSize(dataLayout);
int alignment = pointee.getAlignment(dataLayout);
for (Attribute attr : paramAttr.getAttributes()) {
if (attr instanceof Attribute.KnownIntegerValueAttribute && ((Attribute.KnownIntegerValueAttribute) attr).getAttr() == Attribute.Kind.ALIGN) {
alignment = ((Attribute.KnownIntegerValueAttribute) attr).getValue();
}
}
return nodeFactory.createVarArgCompoundValue(size, alignment, child);
} catch (TypeOverflowException e) {
return Type.handleOverflowExpression(e);
}
}
private static boolean isByValue(AttributesGroup parameter) {
if (parameter == null) {
return false;
}
for (Attribute a : parameter.getAttributes()) {
if (a instanceof Attribute.KnownAttribute && ((Attribute.KnownAttribute) a).getAttr() == Attribute.Kind.BYVAL) {
return true;
}
}
return false;
}
private void assignSourceLocation(LLVMInstrumentableNode node, Instruction sourceInstruction) {
assignSourceLocation(node, sourceInstruction, SourceInstrumentationStrategy.ONLY_FIRST_STATEMENT_ON_LOCATION);
}
private void assignSourceLocation(LLVMInstrumentableNode node, Instruction sourceInstruction, SourceInstrumentationStrategy instrumentationStrategy) {
if (node == null) {
return;
}
final LLVMSourceLocation location = sourceInstruction.getSourceLocation();
if (location == null) {
return;
}
node.setSourceLocation(location);
assert instrumentationStrategy != null;
switch (instrumentationStrategy) {
case FORCED:
node.setHasStatementTag(true);
lastLocation = location;
break;
case ONLY_FIRST_STATEMENT_ON_LOCATION:
if (lastLocation == location) {
break;
} else if (lastLocation != null && Objects.equals(lastLocation.describeFile(), location.describeFile()) && lastLocation.getLine() == location.getLine()) {
break;
} else {
node.setHasStatementTag(true);
lastLocation = location;
}
break;
case DISABLED:
break;
default:
throw new LLVMParserException("Unknown instrumentation strategy: " + instrumentationStrategy);
}
}
private enum SourceInstrumentationStrategy {
FORCED,
ONLY_FIRST_STATEMENT_ON_LOCATION,
DISABLED
}
}