/* * 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.runtime.nodes.api; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.llvm.runtime.LLVMAddress; import com.oracle.truffle.llvm.runtime.LLVMBoxedPrimitive; import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.LLVMSharedGlobalVariable; import com.oracle.truffle.llvm.runtime.LLVMTruffleAddress; import com.oracle.truffle.llvm.runtime.LLVMTruffleObject; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobalVariable; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNodeFactory.LLVMForceLLVMAddressNodeGen; import com.oracle.truffle.llvm.runtime.vector.LLVMDoubleVector; import com.oracle.truffle.llvm.runtime.vector.LLVMFloatVector; import com.oracle.truffle.llvm.runtime.vector.LLVMI16Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI1Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI32Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI64Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI8Vector; /** * An expression node is a node that returns a result, e.g., a local variable read, or an addition * operation. */ @TypeSystemReference(LLVMTypes.class) public abstract class LLVMExpressionNode extends LLVMNode { public static final int DOUBLE_SIZE_IN_BYTES = 8; public static final int FLOAT_SIZE_IN_BYTES = 4; public static final int I16_SIZE_IN_BYTES = 2; public static final int I16_SIZE_IN_BITS = 16; public static final int I16_MASK = 0xffff; public static final int I32_SIZE_IN_BYTES = 4; public static final int I32_SIZE_IN_BITS = 32; public static final long I32_MASK = 0xffffffffL; public static final int I64_SIZE_IN_BYTES = 8; public static final int I64_SIZE_IN_BITS = 64; public static final int I8_SIZE_IN_BITS = 8; public static final int I8_MASK = 0xff; public static final int ADDRESS_SIZE_IN_BYTES = 8; public abstract Object executeGeneric(VirtualFrame frame); public LLVM80BitFloat executeLLVM80BitFloat(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVM80BitFloat(executeGeneric(frame)); } public LLVMAddress executeLLVMAddress(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMAddress(executeGeneric(frame)); } public LLVMTruffleAddress executeLLVMTruffleAddress(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMTruffleAddress(executeGeneric(frame)); } public LLVMTruffleObject executeLLVMTruffleObject(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMTruffleObject(executeGeneric(frame)); } public TruffleObject executeTruffleObject(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectTruffleObject(executeGeneric(frame)); } public byte[] executeByteArray(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectByteArray(executeGeneric(frame)); } public double executeDouble(VirtualFrame frame) { // An UnexpectedResultException would be an error return (double) executeGeneric(frame); } public float executeFloat(VirtualFrame frame) { // An UnexpectedResultException would be an error return (float) executeGeneric(frame); } public short executeI16(VirtualFrame frame) { // An UnexpectedResultException would be an error return (short) executeGeneric(frame); } public boolean executeI1(VirtualFrame frame) { // An UnexpectedResultException would be an error return (boolean) executeGeneric(frame); } public int executeI32(VirtualFrame frame) { // An UnexpectedResultException would be an error return (int) executeGeneric(frame); } public long executeI64(VirtualFrame frame) { // An UnexpectedResultException would be an error return (long) executeGeneric(frame); } public LLVMIVarBit executeLLVMIVarBit(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMIVarBit(executeGeneric(frame)); } public byte executeI8(VirtualFrame frame) { // An UnexpectedResultException would be an error return (byte) executeGeneric(frame); } public LLVMI8Vector executeLLVMI8Vector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMI8Vector) executeGeneric(frame); } public LLVMI64Vector executeLLVMI64Vector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMI64Vector) executeGeneric(frame); } public LLVMI32Vector executeLLVMI32Vector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMI32Vector) executeGeneric(frame); } public LLVMI1Vector executeLLVMI1Vector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMI1Vector) executeGeneric(frame); } public LLVMI16Vector executeLLVMI16Vector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMI16Vector) executeGeneric(frame); } public LLVMFloatVector executeLLVMFloatVector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMFloatVector) executeGeneric(frame); } public LLVMDoubleVector executeLLVMDoubleVector(VirtualFrame frame) { // An UnexpectedResultException would be an error return (LLVMDoubleVector) executeGeneric(frame); } public LLVMFunctionDescriptor executeLLVMFunctionDescriptor(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMFunctionDescriptor(executeGeneric(frame)); } protected boolean isLLVMAddress(Object object) { return object instanceof LLVMAddress; } public String getSourceDescription() { return getRootNode().getName(); } public static boolean notLLVM(TruffleObject object) { return !(object instanceof LLVMFunctionDescriptor || object instanceof LLVMTruffleAddress || object instanceof LLVMSharedGlobalVariable); } protected abstract static class LLVMForceLLVMAddressNode extends Node { public abstract LLVMAddress executeWithTarget(Object object); @Specialization public LLVMAddress doAddressCase(LLVMAddress a) { return a; } @Specialization public LLVMAddress doAddressCase(LLVMGlobalVariable a) { return a.getNativeLocation(); } @Specialization public LLVMAddress executeLLVMBoxedPrimitive(LLVMBoxedPrimitive from) { if (from.getValue() instanceof Long) { return LLVMAddress.fromLong((long) from.getValue()); } else { CompilerDirectives.transferToInterpreter(); throw new IllegalAccessError(String.format("Cannot convert a primitive value (type: %s, value: %s) to an LLVMAddress).", String.valueOf(from.getValue().getClass()), String.valueOf(from.getValue()))); } } @Child private Node isPointer = Message.IS_POINTER.createNode(); @Child private Node asPointer = Message.AS_POINTER.createNode(); @Child private Node isNull = Message.IS_NULL.createNode(); @Child private Node toNative = Message.TO_NATIVE.createNode(); @Specialization(guards = "notLLVM(pointer)") LLVMAddress nativeToAddress(TruffleObject pointer) { try { if (ForeignAccess.sendIsNull(isNull, pointer)) { return LLVMAddress.nullPointer(); } else if (ForeignAccess.sendIsPointer(isPointer, pointer)) { return LLVMAddress.fromLong(ForeignAccess.sendAsPointer(asPointer, pointer)); } else { TruffleObject n = (TruffleObject) ForeignAccess.sendToNative(toNative, pointer); return LLVMAddress.fromLong(ForeignAccess.sendAsPointer(asPointer, n)); } } catch (UnsupportedMessageException | ClassCastException e) { CompilerDirectives.transferToInterpreter(); throw new IllegalStateException("Cannot convert " + pointer + " to LLVMAddress", e); } } protected boolean notLLVM(TruffleObject pointer) { return LLVMExpressionNode.notLLVM(pointer); } } public static final LLVMForceLLVMAddressNode getForceLLVMAddressNode() { return LLVMForceLLVMAddressNodeGen.create(); } public static final LLVMForceLLVMAddressNode[] getForceLLVMAddressNodes(int size) { LLVMForceLLVMAddressNode[] forceToLLVM = new LLVMForceLLVMAddressNode[size]; for (int i = 0; i < size; i++) { forceToLLVM[i] = getForceLLVMAddressNode(); } return forceToLLVM; } }