Search in sources :

Example 11 with LLVMStatementNode

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));
}
Also used : LLVMX86_ConversionNode(com.oracle.truffle.llvm.runtime.nodes.intrinsics.llvm.x86.LLVMX86_ConversionNode) PrimitiveType(com.oracle.truffle.llvm.runtime.types.PrimitiveType) VectorType(com.oracle.truffle.llvm.runtime.types.VectorType) PointerType(com.oracle.truffle.llvm.runtime.types.PointerType) StructureType(com.oracle.truffle.llvm.runtime.types.StructureType) VoidType(com.oracle.truffle.llvm.runtime.types.VoidType) Type(com.oracle.truffle.llvm.runtime.types.Type) LLVMAMD64WriteValueNode(com.oracle.truffle.llvm.runtime.nodes.asm.support.LLVMAMD64WriteValueNode) LLVMAMD64WriteTupelNode(com.oracle.truffle.llvm.runtime.nodes.asm.support.LLVMAMD64WriteTupelNode) LLVMStatementNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode) LLVMExpressionNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode) PointerType(com.oracle.truffle.llvm.runtime.types.PointerType) PrimitiveType(com.oracle.truffle.llvm.runtime.types.PrimitiveType)

Example 12 with LLVMStatementNode

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);
}
Also used : LLVMStatementNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode) LLVMExpressionNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode) SSAValue(com.oracle.truffle.llvm.runtime.types.symbols.SSAValue) LLVMNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode)

Example 13 with LLVMStatementNode

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);
        }
    }
}
Also used : LLVMStatementNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode) LLVMExpressionNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode) LLVMNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode)

Example 14 with LLVMStatementNode

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);
}
Also used : LLVMControlFlowNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode) LLVMStatementNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode) LLVMExpressionNode(com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode)

Aggregations

LLVMStatementNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode)14 LLVMExpressionNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode)10 PointerType (com.oracle.truffle.llvm.runtime.types.PointerType)6 StructureType (com.oracle.truffle.llvm.runtime.types.StructureType)6 ArrayList (java.util.ArrayList)6 Type (com.oracle.truffle.llvm.runtime.types.Type)5 SymbolImpl (com.oracle.truffle.llvm.parser.model.SymbolImpl)4 LLVMControlFlowNode (com.oracle.truffle.llvm.runtime.nodes.api.LLVMControlFlowNode)4 AggregateType (com.oracle.truffle.llvm.runtime.types.AggregateType)4 ArrayType (com.oracle.truffle.llvm.runtime.types.ArrayType)4 FunctionType (com.oracle.truffle.llvm.runtime.types.FunctionType)4 PrimitiveType (com.oracle.truffle.llvm.runtime.types.PrimitiveType)4 Phi (com.oracle.truffle.llvm.parser.LLVMPhiManager.Phi)3 CommonNodeFactory (com.oracle.truffle.llvm.runtime.CommonNodeFactory)3 GetStackSpaceFactory (com.oracle.truffle.llvm.runtime.GetStackSpaceFactory)3 NodeFactory (com.oracle.truffle.llvm.runtime.NodeFactory)3 FrameDescriptor (com.oracle.truffle.api.frame.FrameDescriptor)2 LLVMPhiManager (com.oracle.truffle.llvm.parser.LLVMPhiManager)2 AttributesGroup (com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup)2 FunctionParameter (com.oracle.truffle.llvm.parser.model.functions.FunctionParameter)2