package com.oracle.truffle.llvm.parser.metadata;
import com.oracle.truffle.llvm.parser.listeners.Metadata;
import com.oracle.truffle.llvm.parser.model.symbols.constants.NullConstant;
import com.oracle.truffle.llvm.parser.model.symbols.constants.UndefinedConstant;
import com.oracle.truffle.llvm.parser.model.symbols.constants.integer.BigIntegerConstant;
import com.oracle.truffle.llvm.parser.model.symbols.constants.integer.IntegerConstant;
import com.oracle.truffle.llvm.runtime.except.LLVMParserException;
import com.oracle.truffle.llvm.runtime.types.MetaType;
import com.oracle.truffle.llvm.runtime.types.Type;
import com.oracle.truffle.llvm.runtime.types.VoidType;
import com.oracle.truffle.llvm.parser.model.SymbolImpl;
public final class ParseUtil {
private ParseUtil() {
}
public static int checkInt(long value) {
if (value != (int) value) {
throw new LLVMParserException("value in 'int' range expected");
}
return (int) value;
}
public static boolean isInteger(long[] args, int index, Metadata md) {
final int typeIndex = index << 1;
final Type type = md.getTypeById(args[typeIndex]);
if (type == MetaType.METADATA || VoidType.INSTANCE.equals(type)) {
return false;
}
final int valueIndex = typeIndex + 1;
final SymbolImpl value = md.getScope().getSymbols().getOrNull((int) args[valueIndex]);
return value instanceof IntegerConstant || value instanceof BigIntegerConstant || value instanceof NullConstant || value instanceof UndefinedConstant;
}
private static final long DEFAULT_NUMBER = 0L;
public static long asLong(long[] args, int index, Metadata md) {
final int typeIndex = index << 1;
if (typeIndex >= args.length) {
return DEFAULT_NUMBER;
}
final Type type = md.getTypeById(args[typeIndex]);
if (type == MetaType.METADATA || VoidType.INSTANCE.equals(type)) {
return DEFAULT_NUMBER;
}
final int valueIndex = typeIndex + 1;
final SymbolImpl value = md.getScope().getSymbols().getOrNull((int) args[valueIndex]);
if (value instanceof IntegerConstant) {
return ((IntegerConstant) value).getValue();
} else if (value instanceof BigIntegerConstant) {
return ((BigIntegerConstant) value).getValue().longValue();
} else if (value instanceof NullConstant || value instanceof UndefinedConstant) {
return 0L;
} else {
return DEFAULT_NUMBER;
}
}
public static int asInt(long[] args, int index, Metadata md) {
return (int) asLong(args, index, md);
}
static boolean asBoolean(long[] args, int index, Metadata md) {
return asLong(args, index, md) != 0L;
}
static MDBaseNode resolveReference(long[] args, int index, MDBaseNode dependent, Metadata md) {
final int typeIndex = index << 1;
if (typeIndex >= args.length) {
return MDVoidNode.INSTANCE;
}
final int valueIndex = typeIndex + 1;
final Type type = md.getTypeById(args[typeIndex]);
final long value = args[valueIndex];
if (type == MetaType.METADATA) {
return md.getScope().getMetadata().getNonNullable(value, dependent);
} else if (type != VoidType.INSTANCE) {
return MDValue.create(value, md.getScope());
} else {
return MDVoidNode.INSTANCE;
}
}
static MDBaseNode resolveSymbol(long[] args, int index, Metadata md) {
final int typeIndex = index << 1;
if (typeIndex >= args.length) {
return MDVoidNode.INSTANCE;
}
final int valueIndex = typeIndex + 1;
final Type type = md.getTypeById(args[typeIndex]);
final long value = (int) args[valueIndex];
if (type != MetaType.METADATA && !VoidType.INSTANCE.equals(type)) {
return MDValue.create(value, md.getScope());
} else {
return MDVoidNode.INSTANCE;
}
}
private static final long BYTE_MASK = 0xFF;
public static String longArrayToString(int startIndex, long[] chars) {
final byte[] bytes = new byte[chars.length - startIndex];
for (int from = startIndex, to = 0; to < bytes.length; from++, to++) {
bytes[to] = (byte) (chars[from] & BYTE_MASK);
}
return new String(bytes);
}
static long unrotateSign(long u) {
return (u & 1) == 1 ? ~(u >> 1) : u >> 1;
}
}