package com.oracle.truffle.llvm.runtime.types;
import java.math.BigInteger;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.llvm.runtime.CommonNodeFactory;
import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory;
import com.oracle.truffle.llvm.runtime.NodeFactory;
import com.oracle.truffle.llvm.runtime.datalayout.DataLayout;
import com.oracle.truffle.llvm.runtime.except.LLVMParserException;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.types.visitors.TypeVisitor;
public final class VariableBitWidthType extends Type {
public static final int MIN_INT_BITS = 1;
public static final int MAX_INT_BITS = (1 << 24) - 1;
private final int bitWidth;
private final Object constant;
public VariableBitWidthType(int bitWidth) {
this(bitWidth, null);
}
VariableBitWidthType(int bitWidth, Object constant) {
if (bitWidth < MIN_INT_BITS || bitWidth > MAX_INT_BITS) {
throw new LLVMParserException(getClass().getSimpleName() + " out of range: " + bitWidth);
}
this.bitWidth = bitWidth;
this.constant = constant;
}
public Object getConstant() {
return constant;
}
public boolean isConstant() {
return constant != null;
}
@Override
public long getBitSize() {
return bitWidth;
}
public int getBitSizeInt() {
return bitWidth;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + bitWidth;
result = prime * result + ((constant == null) ? 0 : constant.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
VariableBitWidthType other = (VariableBitWidthType) obj;
if (bitWidth != other.bitWidth) {
return false;
}
if (constant == null) {
if (other.constant != null) {
return false;
}
} else if (!constant.equals(other.constant)) {
return false;
}
return true;
}
@Override
public void accept(TypeVisitor visitor) {
visitor.visit(this);
}
@Override
public int getAlignment(DataLayout targetDataLayout) {
if (targetDataLayout != null) {
return targetDataLayout.getBitAlignment(this) / Byte.SIZE;
} else if (bitWidth <= Byte.SIZE) {
return Byte.BYTES;
} else if (bitWidth <= Short.SIZE) {
return Short.BYTES;
} else if (bitWidth <= Integer.SIZE) {
return Integer.BYTES;
} else {
return Long.BYTES;
}
}
@Override
public long getSize(DataLayout targetDataLayout) {
try {
return targetDataLayout.getSize(this);
} catch (TypeOverflowException e) {
throw new AssertionError(e);
}
}
public int getSizeInt(DataLayout targetDataLayout) {
long size = getSize(targetDataLayout);
assert (int) size == size;
return (int) size;
}
@Override
@TruffleBoundary
public String toString() {
if (getConstant() != null) {
return String.format("i%d %s", getBitSize(), getConstant());
} else {
return String.format("i%d", getBitSize());
}
}
@Override
public LLVMExpressionNode createNullConstant(NodeFactory nodeFactory, DataLayout dataLayout, GetStackSpaceFactory stackFactory) {
return CommonNodeFactory.createSimpleConstantNoArray(BigInteger.ZERO, this);
}
}