/*
* 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.memory;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.NodeField;
import com.oracle.truffle.api.dsl.Specialization;
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.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.llvm.runtime.LLVMAddress;
import com.oracle.truffle.llvm.runtime.LLVMBoxedPrimitive;
import com.oracle.truffle.llvm.runtime.LLVMContext;
import com.oracle.truffle.llvm.runtime.LLVMFunction;
import com.oracle.truffle.llvm.runtime.LLVMFunctionDescriptor;
import com.oracle.truffle.llvm.runtime.LLVMFunctionHandle;
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.interop.LLVMDataEscapeNode;
import com.oracle.truffle.llvm.runtime.interop.LLVMDataEscapeNodeGen;
import com.oracle.truffle.llvm.runtime.interop.ToLLVMNode;
import com.oracle.truffle.llvm.runtime.memory.LLVMHeap;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemory;
import com.oracle.truffle.llvm.runtime.memory.LLVMNativeFunctions;
import com.oracle.truffle.llvm.runtime.memory.LLVMNativeFunctions.MemCopyNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.types.PrimitiveType;
import com.oracle.truffle.llvm.runtime.types.Type;
import com.oracle.truffle.llvm.runtime.types.VariableBitWidthType;
@NodeChildren(value = {@NodeChild(type = LLVMExpressionNode.class, value = "pointerNode")})
public abstract class LLVMStoreNode extends LLVMExpressionNode {
@Child protected Node foreignWrite = Message.WRITE.createNode();
@Child protected LLVMDataEscapeNode dataEscape;
protected final Type valueType;
private final SourceSection sourceSection;
public LLVMStoreNode(Type valueType, SourceSection sourceSection) {
this.valueType = valueType;
this.dataEscape = LLVMDataEscapeNodeGen.create(valueType);
this.sourceSection = sourceSection;
}
protected void doForeignAccess(LLVMTruffleObject addr, int stride, Object value, LLVMContext context) {
try {
ForeignAccess.sendWrite(foreignWrite, addr.getObject(), (int) (addr.getOffset() / stride), dataEscape.executeWithTarget(value, context));
} catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
throw new IllegalStateException(e);
}
}
protected void doForeignAccess(TruffleObject addr, Object value, LLVMContext context) {
try {
ForeignAccess.sendWrite(foreignWrite, addr, 0, dataEscape.executeWithTarget(value, context));
} catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
throw new IllegalStateException(e);
}
}
@Override
public SourceSection getSourceSection() {
return sourceSection;
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMI1StoreNode extends LLVMStoreNode {
public LLVMI1StoreNode(SourceSection source) {
super(PrimitiveType.I1, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, boolean value) {
address.putI1(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, boolean value) {
LLVMMemory.putI1(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, boolean value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, 1, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, boolean value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putI1((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, boolean value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.I1), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMI8StoreNode extends LLVMStoreNode {
public LLVMI8StoreNode(SourceSection source) {
super(PrimitiveType.I8, source);
}
@Specialization
public Object execute(LLVMAddress address, byte value) {
LLVMMemory.putI8(address, value);
return null;
}
@Specialization
public Object execute(LLVMGlobalVariable address, byte value) {
address.putI8(value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, byte value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, 1, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, byte value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putI8((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, byte value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.I8), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMI16StoreNode extends LLVMStoreNode {
public LLVMI16StoreNode(SourceSection source) {
super(PrimitiveType.I16, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, short value) {
address.putI16(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, short value) {
LLVMMemory.putI16(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, short value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.I16_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, short value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putI16((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, short value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.I16), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMI32StoreNode extends LLVMStoreNode {
public LLVMI32StoreNode(SourceSection source) {
super(PrimitiveType.I32, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, int value) {
address.putI32(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, int value) {
LLVMMemory.putI32(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, int value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.I32_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, int value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putI32((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, int value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.I32), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMI64StoreNode extends LLVMStoreNode {
public LLVMI64StoreNode(SourceSection source) {
super(PrimitiveType.I64, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, long value) {
address.putI64(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, long value) {
LLVMMemory.putI64(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, long value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.I64_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, long value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putI64((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, long value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.I64), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMIVarBitStoreNode extends LLVMStoreNode {
public LLVMIVarBitStoreNode(VariableBitWidthType type, SourceSection source) {
super(type, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, LLVMIVarBit value) {
LLVMMemory.putIVarBit(address.getNativeLocation(), value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, LLVMIVarBit value) {
LLVMMemory.putIVarBit(address, value);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMFloatStoreNode extends LLVMStoreNode {
public LLVMFloatStoreNode(SourceSection source) {
super(PrimitiveType.FLOAT, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, float value) {
address.putFloat(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, float value) {
LLVMMemory.putFloat(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, float value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.FLOAT_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, float value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putFloat((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, float value, @Cached("getContext()") LLVMContext context) {
execute(new LLVMTruffleObject(address, PrimitiveType.FLOAT), value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMDoubleStoreNode extends LLVMStoreNode {
public LLVMDoubleStoreNode(SourceSection source) {
super(PrimitiveType.DOUBLE, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, double value) {
address.putDouble(value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, double value) {
LLVMMemory.putDouble(address, value);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, double value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.DOUBLE_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, double value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putDouble((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, double value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVM80BitFloatStoreNode extends LLVMStoreNode {
public LLVM80BitFloatStoreNode(SourceSection source) {
super(PrimitiveType.X86_FP80, source);
}
@Specialization
public Object execute(LLVMGlobalVariable address, LLVM80BitFloat value) {
LLVMMemory.put80BitFloat(address.getNativeLocation(), value);
return null;
}
@Specialization
public Object execute(LLVMAddress address, LLVM80BitFloat value) {
LLVMMemory.put80BitFloat(address, value);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMAddressStoreNode extends LLVMStoreNode {
public LLVMAddressStoreNode(Type type, SourceSection source) {
super(type, source);
}
@Specialization
public Object doAddress(LLVMAddress address, LLVMAddress value) {
LLVMMemory.putAddress(address, value);
return null;
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, LLVMAddress value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putAddress((long) address.getValue(), value);
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization
public Object execute(LLVMBoxedPrimitive address, LLVMGlobalVariable value) {
if (address.getValue() instanceof Long) {
LLVMMemory.putAddress(LLVMAddress.fromLong((long) address.getValue()), value.getNativeLocation());
return null;
} else {
CompilerDirectives.transferToInterpreter();
throw new IllegalAccessError("Cannot access address: " + address.getValue());
}
}
@Specialization
public Object doAddress(LLVMGlobalVariable address, LLVMAddress value) {
address.putAddress(value);
return null;
}
@Specialization
public Object doAddress(LLVMAddress address, LLVMGlobalVariable value) {
LLVMMemory.putAddress(address, value.getNativeLocation());
return null;
}
@Specialization
public Object doAddress(LLVMGlobalVariable address, LLVMGlobalVariable value) {
LLVMMemory.putAddress(address.getNativeLocation(), value.getNativeLocation());
return null;
}
@Specialization(guards = "notLLVM(value)")
public Object doAddress(LLVMGlobalVariable address, TruffleObject value) {
address.putTruffleObject(value);
return null;
}
@Specialization
public Object doAddress(LLVMGlobalVariable address, LLVMBoxedPrimitive value) {
address.putBoxedPrimitive(value);
return null;
}
@Specialization
public Object doAddress(LLVMGlobalVariable address, LLVMTruffleObject value) {
address.putLLVMTruffleObject(value);
return null;
}
@Specialization(guards = "notLLVM(value)")
public Object execute(LLVMAddress address, TruffleObject value, @Cached("getForceLLVMAddressNode()") LLVMForceLLVMAddressNode toLLVMAddress) {
LLVMMemory.putAddress(address, toLLVMAddress.executeWithTarget(value));
return null;
}
@Specialization(guards = "notLLVM(value)")
public Object execute(LLVMBoxedPrimitive address, TruffleObject value, @Cached("getForceLLVMAddressNode()") LLVMForceLLVMAddressNode convertAddress,
@Cached("getForceLLVMAddressNode()") LLVMForceLLVMAddressNode convertValue) {
LLVMMemory.putAddress(convertAddress.executeWithTarget(address), convertValue.executeWithTarget(value));
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, LLVMAddress value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES, new LLVMTruffleAddress(value, valueType, context), context);
return null;
}
@Specialization
public Object execute(LLVMTruffleObject address, Object value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES, value, context);
return null;
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, LLVMAddress value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, new LLVMTruffleAddress(value, valueType, context), context);
return null;
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, LLVMGlobalVariable value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, new LLVMSharedGlobalVariable(value, context), context);
return null;
}
@Specialization(guards = "notLLVM(address)")
public Object execute(TruffleObject address, Object value, @Cached("getContext()") LLVMContext context) {
doForeignAccess(address, value, context);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMGlobalVariableStoreNode extends LLVMExpressionNode {
protected final LLVMGlobalVariable descriptor;
private final SourceSection source;
public LLVMGlobalVariableStoreNode(LLVMGlobalVariable descriptor, SourceSection source) {
this.descriptor = descriptor;
this.source = source;
}
@Specialization
public Object executeNative(LLVMAddress value) {
descriptor.putAddress(value);
return null;
}
@Specialization
public Object executeNative(LLVMTruffleAddress value) {
descriptor.putAddress(value.getAddress());
return null;
}
@Specialization
public Object executeNative(LLVMFunctionHandle value) {
descriptor.putFunction(value);
return null;
}
@Specialization
public Object executeNative(LLVMFunctionDescriptor value) {
descriptor.putFunction(value);
return null;
}
@Specialization
public Object executeNative(LLVMGlobalVariable value) {
descriptor.putGlobal(value);
return null;
}
@Specialization
public Object executeNative(LLVMTruffleObject value) {
descriptor.putLLVMTruffleObject(value);
return null;
}
@Child private ToLLVMNode toLLVM = ToLLVMNode.createNode(long.class);
@Specialization
public Object executeLLVMBoxedPrimitive(LLVMBoxedPrimitive value) {
descriptor.putBoxedPrimitive(value);
return null;
}
@Specialization(guards = "notLLVM(value)")
public Object executeManaged(TruffleObject value) {
descriptor.putTruffleObject(value);
return null;
}
@Override
public SourceSection getSourceSection() {
return source;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
public abstract static class LLVMFunctionStoreNode extends LLVMStoreNode {
public LLVMFunctionStoreNode(Type type, SourceSection source) {
super(type, source);
}
@Specialization
public Object execute(LLVMAddress address, LLVMFunction function) {
LLVMHeap.putFunctionPointer(address, function.getFunctionPointer());
return null;
}
@Specialization
public Object execute(LLVMGlobalVariable address, LLVMFunction function) {
address.putFunction(function);
return null;
}
}
@NodeChild(type = LLVMExpressionNode.class, value = "valueNode")
@NodeField(type = int.class, name = "structSize")
public abstract static class LLVMStructStoreNode extends LLVMStoreNode {
@Child private MemCopyNode memCopy;
public abstract int getStructSize();
protected LLVMStructStoreNode(LLVMNativeFunctions heapFunctions, Type type, SourceSection source) {
super(type, source);
memCopy = heapFunctions.createMemCopyNode();
}
@Specialization
public Object execute(LLVMGlobalVariable address, LLVMGlobalVariable value) {
memCopy.execute(address.getNativeLocation(), value.getNativeLocation(), getStructSize());
return null;
}
@Specialization
public Object execute(LLVMAddress address, LLVMGlobalVariable value) {
memCopy.execute(address, value.getNativeLocation(), getStructSize());
return null;
}
@Specialization
public Object execute(LLVMGlobalVariable address, LLVMAddress value) {
memCopy.execute(address.getNativeLocation(), value, getStructSize());
return null;
}
@Specialization
public Object execute(LLVMAddress address, LLVMAddress value) {
memCopy.execute(address, value, getStructSize());
return null;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMI1ArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMI1ArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI8(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI8(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
boolean currentValue = values[i].executeI1(frame);
LLVMMemory.putI1(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMI8ArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMI8ArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI8(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI8(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
byte currentValue = values[i].executeI8(frame);
LLVMMemory.putI8(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMI16ArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMI16ArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI8(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI8(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
short currentValue = values[i].executeI16(frame);
LLVMMemory.putI16(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMI32ArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMI32ArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI32(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI32(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
int currentValue = values[i].executeI32(frame);
LLVMMemory.putI32(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMI64ArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMI64ArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI64(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI64(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
long currentValue = values[i].executeI64(frame);
LLVMMemory.putI64(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMFloatArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMFloatArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeI64(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeI64(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
float currentValue = values[i].executeFloat(frame);
LLVMMemory.putFloat(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMDoubleArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMDoubleArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeDouble(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeDouble(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
double currentValue = values[i].executeDouble(frame);
LLVMMemory.putDouble(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVM80BitFloatArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVM80BitFloatArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return write80BitFloat(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress write80BitFloat(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
try {
LLVM80BitFloat currentValue = values[i].executeLLVM80BitFloat(frame);
LLVMMemory.put80BitFloat(currentPtr, currentValue);
currentPtr += stride;
} catch (UnexpectedResultException e) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(e);
}
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMAddressArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
@Children private final LLVMForceLLVMAddressNode[] toLLVM;
private final int stride;
public LLVMAddressArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
this.toLLVM = getForceLLVMAddressNodes(values.length);
}
public LLVMExpressionNode[] getValues() {
return values;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeDouble(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeDouble(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
LLVMAddress currentValue = toLLVM[i].executeWithTarget(values[i].executeGeneric(frame));
LLVMMemory.putAddress(currentPtr, currentValue);
currentPtr += stride;
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMFunctionArrayLiteralNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
public LLVMFunctionArrayLiteralNode(LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeDouble(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeDouble(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
try {
LLVMFunctionDescriptor currentValue = (LLVMFunctionDescriptor) values[i].executeTruffleObject(frame);
LLVMHeap.putFunctionPointer(currentPtr, currentValue.getFunctionPointer());
currentPtr += stride;
} catch (UnexpectedResultException e) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(e);
}
}
return addr;
}
}
@NodeChild(value = "address", type = LLVMExpressionNode.class)
public abstract static class LLVMAddressArrayCopyNode extends LLVMExpressionNode {
@Children private final LLVMExpressionNode[] values;
private final int stride;
@Child private MemCopyNode memCopy;
public LLVMAddressArrayCopyNode(LLVMNativeFunctions heapFunctions, LLVMExpressionNode[] values, int stride) {
this.values = values;
this.stride = stride;
this.memCopy = heapFunctions.createMemCopyNode();
}
@Specialization
protected LLVMAddress write(VirtualFrame frame, LLVMGlobalVariable global) {
return writeDouble(frame, global.getNativeLocation());
}
@Specialization
@ExplodeLoop
protected LLVMAddress writeDouble(VirtualFrame frame, LLVMAddress addr) {
long currentPtr = addr.getVal();
for (int i = 0; i < values.length; i++) {
try {
LLVMAddress currentValue = values[i].executeLLVMAddress(frame);
memCopy.execute(LLVMAddress.fromLong(currentPtr), currentValue, stride);
currentPtr += stride;
} catch (UnexpectedResultException e) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException(e);
}
}
return addr;
}
}
}