use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class AsmFactory method createBinaryOperationImplicitSize.
void createBinaryOperationImplicitSize(String operation, AsmOperand a, AsmOperand b) {
AsmOperand dst = b;
AsmOperand src = a;
assert a != null && b != null;
Type dstType = getType(b, a);
LLVMExpressionNode srcA;
LLVMExpressionNode srcB;
LLVMExpressionNode out;
switch(operation) {
case "lea":
out = getOperandAddress(dstType, src);
if (isLeaPointer(src)) {
dstType = new PointerType(dstType);
}
break;
case "xor":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I8:
out = LLVMAMD64XorbNodeGen.create(srcA, srcB);
break;
case I16:
out = LLVMAMD64XorwNodeGen.create(srcA, srcB);
break;
case I32:
out = LLVMAMD64XorlNodeGen.create(srcA, srcB);
break;
case I64:
out = LLVMAMD64XorqNodeGen.create(srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
break;
case "mov":
if (dstType instanceof PrimitiveType || dstType instanceof PointerType) {
out = getOperandLoad(dstType, a);
} else {
throw invalidOperandType(dstType);
}
break;
case "bsr":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I16:
out = LLVMAMD64BsrwNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
case I32:
out = LLVMAMD64BsrlNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
case I64:
out = LLVMAMD64BsrqNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
break;
case "bsf":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I16:
out = LLVMAMD64BsfwNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
case I32:
out = LLVMAMD64BsflNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
case I64:
out = LLVMAMD64BsfqNodeGen.create(getFlagWrite(LLVMAMD64Flags.ZF), srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
break;
case "xchg":
{
LLVMStatementNode res;
XchgOperands operands = new XchgOperands(a, b, dstType);
switch(getPrimitiveType(dstType)) {
case I8:
res = LLVMAMD64XchgbNodeGen.create(operands.dst, operands.srcA, operands.srcB);
break;
case I16:
res = LLVMAMD64XchgwNodeGen.create(operands.dst, operands.srcA, operands.srcB);
break;
case I32:
res = LLVMAMD64XchglNodeGen.create(operands.dst, operands.srcA, operands.srcB);
break;
case I64:
res = LLVMAMD64XchgqNodeGen.create(operands.dst, operands.srcA, operands.srcB);
break;
default:
throw invalidOperandType(dstType);
}
/**
* Make xchg unconditionally atomic. Some code (e.g. musl libc) using xchg relies on
* its (and any other instruction's) non-atomic behavior in concurrency with other
* locked/atomic instructions to be atomic.
*
* The issue is that we should avoid globally locking memory operations, and so
* instead we hand-pick instructions that are used in code related to
* synchronization, and xchg is one of those (e.g. in the musl libc). This is not
* entirely correct behavior, but should cover most practical use-cases.
*/
statements.add(makeAtomic(res, b));
return;
}
case "cmpxchg":
{
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
LLVMAMD64WriteValueNode dst1 = getStore(dstType, b);
LLVMAMD64WriteValueNode dst2;
LLVMExpressionNode accumulator;
LLVMStatementNode res;
if (dstType instanceof PointerType) {
dst2 = getRegisterStore("rax");
accumulator = getOperandLoad(new PointerType(PrimitiveType.I8), new AsmRegisterOperand("rax"));
res = LLVMAMD64CmpXchgqNodeGen.create(getUpdateCPAZSOFlagsNode(), dst1, dst2, accumulator, srcA, srcB);
} else {
switch(getPrimitiveType(dstType)) {
case I8:
dst2 = getRegisterStore("al");
accumulator = getOperandLoad(PrimitiveType.I8, new AsmRegisterOperand("al"));
res = LLVMAMD64CmpXchgbNodeGen.create(getUpdateCPAZSOFlagsNode(), dst1, dst2, accumulator, srcA, srcB);
break;
case I16:
dst2 = getRegisterStore("ax");
accumulator = getOperandLoad(PrimitiveType.I16, new AsmRegisterOperand("ax"));
res = LLVMAMD64CmpXchgwNodeGen.create(getUpdateCPAZSOFlagsNode(), dst1, dst2, accumulator, srcA, srcB);
break;
case I32:
dst2 = getRegisterStore("eax");
accumulator = getOperandLoad(PrimitiveType.I32, new AsmRegisterOperand("eax"));
res = LLVMAMD64CmpXchglNodeGen.create(getUpdateCPAZSOFlagsNode(), dst1, dst2, accumulator, srcA, srcB);
break;
case I64:
dst2 = getRegisterStore("rax");
accumulator = getOperandLoad(PrimitiveType.I64, new AsmRegisterOperand("rax"));
res = LLVMAMD64CmpXchgqNodeGen.create(getUpdateCPAZSOFlagsNode(), dst1, dst2, accumulator, srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
}
statements.add(maybeMakeAtomic(res, b));
return;
}
case "and":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I8:
out = LLVMAMD64AndbNodeGen.create(getUpdatePZSFlagsNode(), srcA, srcB);
break;
case I16:
out = LLVMAMD64AndwNodeGen.create(getUpdatePZSFlagsNode(), srcA, srcB);
break;
case I32:
out = LLVMAMD64AndlNodeGen.create(getUpdatePZSFlagsNode(), srcA, srcB);
break;
case I64:
out = LLVMAMD64AndqNodeGen.create(getUpdatePZSFlagsNode(), srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
break;
case "or":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I8:
out = LLVMAMD64OrbNodeGen.create(srcA, srcB);
break;
case I16:
out = LLVMAMD64OrwNodeGen.create(srcA, srcB);
break;
case I32:
out = LLVMAMD64OrlNodeGen.create(srcA, srcB);
break;
case I64:
out = LLVMAMD64OrqNodeGen.create(srcA, srcB);
break;
default:
throw invalidOperandType(dstType);
}
break;
case "pmovmskb":
srcA = getOperandLoad(getType(a), a);
LLVMX86_ConversionNode.LLVMX86_Pmovmskb128 pmovmskb128 = LLVMX86_ConversionNodeFactory.LLVMX86_Pmovmskb128NodeGen.create(srcA);
out = pmovmskb128;
break;
case "xadd":
srcA = getOperandLoad(dstType, a);
srcB = getOperandLoad(dstType, b);
switch(getPrimitiveType(dstType)) {
case I8:
{
LLVMAMD64WriteValueNode dst1 = getRegisterStore(PrimitiveType.I8, a);
LLVMAMD64WriteValueNode dst2 = getStore(dstType, dst);
LLVMAMD64WriteTupelNode res = LLVMAMD64WriteTupelNodeGen.create(dst1, dst2);
statements.add(maybeMakeAtomic(LLVMAMD64XaddbNodeGen.create(getUpdateCPZSOFlagsNode(), res, srcA, srcB), b));
return;
}
case I16:
{
LLVMAMD64WriteValueNode dst1 = getRegisterStore(PrimitiveType.I16, a);
LLVMAMD64WriteValueNode dst2 = getStore(dstType, dst);
LLVMAMD64WriteTupelNode res = LLVMAMD64WriteTupelNodeGen.create(dst1, dst2);
statements.add(maybeMakeAtomic(LLVMAMD64XaddwNodeGen.create(getUpdateCPZSOFlagsNode(), res, srcA, srcB), b));
return;
}
case I32:
{
LLVMAMD64WriteValueNode dst1 = getRegisterStore(PrimitiveType.I32, a);
LLVMAMD64WriteValueNode dst2 = getStore(dstType, dst);
LLVMAMD64WriteTupelNode res = LLVMAMD64WriteTupelNodeGen.create(dst1, dst2);
statements.add(maybeMakeAtomic(LLVMAMD64XaddlNodeGen.create(getUpdateCPZSOFlagsNode(), res, srcA, srcB), b));
return;
}
case I64:
{
LLVMAMD64WriteValueNode dst1 = getRegisterStore(PrimitiveType.I64, a);
LLVMAMD64WriteValueNode dst2 = getStore(dstType, dst);
LLVMAMD64WriteTupelNode res = LLVMAMD64WriteTupelNodeGen.create(dst1, dst2);
statements.add(maybeMakeAtomic(LLVMAMD64XaddqNodeGen.create(getUpdateCPZSOFlagsNode(), res, srcA, srcB), b));
return;
}
default:
throw invalidOperandType(dstType);
}
default:
statements.add(LLVMUnsupportedInstructionNode.create(UnsupportedReason.INLINE_ASSEMBLER, operation));
return;
}
statements.add(getOperandStore(dstType, dst, out));
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LLVMBitcodeInstructionVisitor method finish.
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, CommonNodeFactory.createFrameWrite(target.getType(), (LLVMExpressionNode) node, symbols.findOrAddFrameSlot(target)));
}
}
return instructionNodes.toArray(LLVMStatementNode.NO_STATEMENTS);
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LLVMBitcodeInstructionVisitor method handleNullerInfo.
public void handleNullerInfo() {
int[] 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);
}
}
}
use of com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode in project graal by oracle.
the class LLVMBitcodeInstructionVisitor method visit.
@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);
}
Aggregations