package com.oracle.truffle.llvm.parser.metadata.debuginfo;
import static com.oracle.truffle.llvm.parser.metadata.DwarfOpcode.LLVM_FRAGMENT;
import static com.oracle.truffle.llvm.parser.metadata.DwarfOpcode.hasOp;
import static com.oracle.truffle.llvm.parser.metadata.DwarfOpcode.numElements;
import java.util.List;
import com.oracle.truffle.llvm.parser.metadata.MDExpression;
public final class ValueFragment implements Comparable<ValueFragment> {
private static final ValueFragment COMPLETE_VALUE = new ValueFragment(-1, -1);
private static final int EXPRESSION_SIZE = 3;
private static final int EXPRESSION_INDEX_OFFSET = 1;
private static final int EXPRESSION_INDEX_LENGTH = 2;
public static boolean describesFragment(MDExpression expression) {
return hasOp(expression, LLVM_FRAGMENT);
}
public static ValueFragment create(int offset, int length) {
return new ValueFragment(offset, length);
}
public static ValueFragment parse(MDExpression expression) {
final int elementCount = expression.getElementCount();
int i = 0;
while (i < elementCount) {
final long op = expression.getOperand(i);
if (op == LLVM_FRAGMENT) {
if (i + EXPRESSION_SIZE <= elementCount) {
final int offset = (int) expression.getOperand(i + EXPRESSION_INDEX_OFFSET);
final int length = (int) expression.getOperand(i + EXPRESSION_INDEX_LENGTH);
return new ValueFragment(offset, length);
}
}
i += numElements(op);
}
return COMPLETE_VALUE;
}
public static int getPartIndex(ValueFragment fragment, List<ValueFragment> siblings, List<Integer> clearParts) {
int partIndex = -1;
for (int i = 0; i < siblings.size(); i++) {
final ValueFragment sibling = siblings.get(i);
if (sibling.equals(fragment)) {
partIndex = i;
} else if (!ValueFragment.COMPLETE_VALUE.equals(sibling) && fragment.hides(sibling)) {
clearParts.add(i);
}
}
return partIndex;
}
private final int offset;
private final int length;
private ValueFragment(int offset, int length) {
this.offset = offset;
this.length = length;
}
public int getOffset() {
return offset;
}
public int getLength() {
return length;
}
public int getStart() {
return offset;
}
public int getEnd() {
return offset + length;
}
public boolean isComplete() {
return COMPLETE_VALUE.equals(this);
}
private boolean hides(ValueFragment other) {
return getStart() <= other.getStart() && other.getEnd() <= getEnd();
}
@Override
public int compareTo(ValueFragment o) {
if (offset == o.offset) {
return Integer.compare(length, o.length);
} else {
return Integer.compare(offset, o.offset);
}
}
@Override
public int hashCode() {
return (offset << Short.SIZE) | length;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ValueFragment other = (ValueFragment) obj;
return offset == other.offset && length == other.length;
}
}