/* * 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.nodes.op.compare; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeChildren; import com.oracle.truffle.api.dsl.Specialization; 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.nodes.Node; import com.oracle.truffle.llvm.nodes.op.compare.LLVMAddressCompareNodeGen.ToComparableValueNodeGen; import com.oracle.truffle.llvm.runtime.LLVMAddress; import com.oracle.truffle.llvm.runtime.LLVMBoxedPrimitive; import com.oracle.truffle.llvm.runtime.LLVMFunction; import com.oracle.truffle.llvm.runtime.LLVMTruffleObject; import com.oracle.truffle.llvm.runtime.global.LLVMGlobalVariable; import com.oracle.truffle.llvm.runtime.interop.ToLLVMNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; @NodeChildren({@NodeChild(type = LLVMExpressionNode.class), @NodeChild(type = LLVMExpressionNode.class)}) public abstract class LLVMAddressCompareNode extends LLVMExpressionNode { public enum Kind { ULT, UGT, UGE, ULE, SLE, SGT, SGE, SLT, EQ, NEQ, } public static LLVMAddressCompareNode create(Kind kind, LLVMExpressionNode l, LLVMExpressionNode r) { switch (kind) { case SLT: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.signedLessThan(val2); } }, l, r); case SGE: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.signedGreaterEquals(val2); } }, l, r); case SGT: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.signedGreaterThan(val2); } }, l, r); case SLE: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.signedLessEquals(val2); } }, l, r); case UGE: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.unsignedGreaterEquals(val2); } }, l, r); case UGT: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.unsignedGreaterThan(val2); } }, l, r); case ULE: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.unsignedLessEquals(val2); } }, l, r); case ULT: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.unsignedLessThan(val2); } }, l, r); case EQ: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.getVal() == val2.getVal(); } }, l, r); case NEQ: return LLVMAddressCompareNodeGen.create(new AddressCompare() { @Override public boolean compare(LLVMAddress val1, LLVMAddress val2) { return val1.getVal() != val2.getVal(); } }, l, r); default: throw new AssertionError(); } } protected abstract static class AddressCompare { abstract boolean compare(LLVMAddress val1, LLVMAddress val2); } private final AddressCompare op; public LLVMAddressCompareNode(AddressCompare op) { this.op = op; } @NodeChild(type = LLVMExpressionNode.class) protected abstract static class ToComparableValue extends LLVMExpressionNode { protected abstract LLVMAddress executeWithTarget(Object v1); @Specialization protected LLVMAddress doAddress(long address) { return LLVMAddress.fromLong(address); } @Specialization protected LLVMAddress doAddress(LLVMAddress address) { return address; } @Specialization protected LLVMAddress doLLVMGlobalVariableDescriptor(LLVMGlobalVariable address) { return address.getNativeLocation(); } @Child private Node isNull = Message.IS_NULL.createNode(); @Specialization protected LLVMAddress doLLVMTruffleObject(LLVMTruffleObject address) { if (ForeignAccess.sendIsNull(isNull, address.getObject())) { return LLVMAddress.fromLong(address.getOffset()); } else { return LLVMAddress.fromLong(address.getObject().hashCode() + address.getOffset()); } } @Specialization(guards = "notLLVM(address)") protected LLVMAddress doTruffleObject(TruffleObject address) { if (ForeignAccess.sendIsNull(isNull, address)) { return LLVMAddress.nullPointer(); } else { return LLVMAddress.fromLong(address.hashCode()); } } @Specialization protected LLVMAddress doLLVMFunction(LLVMFunction address) { return LLVMAddress.fromLong(address.getFunctionPointer()); } @Child private ToLLVMNode toLLVM = ToLLVMNode.createNode(long.class); @Specialization protected LLVMAddress doLLVMBoxedPrimitive(LLVMBoxedPrimitive address) { return LLVMAddress.fromLong((long) toLLVM.executeWithTarget(address.getValue())); } } @Child private ToComparableValue convertVal1 = ToComparableValueNodeGen.create(null); @Child private ToComparableValue convertVal2 = ToComparableValueNodeGen.create(null); @Specialization public boolean doCompare(Object val1, Object val2) { return op.compare(convertVal1.executeWithTarget(val1), convertVal2.executeWithTarget(val2)); } }