Skip to content

Instantly share code, notes, and snippets.

@Deamon5550
Last active November 6, 2016 06:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Deamon5550/d48f81ec8aad3360576b61071b958fb7 to your computer and use it in GitHub Desktop.
Save Deamon5550/d48f81ec8aad3360576b61071b958fb7 to your computer and use it in GitHub Desktop.
private static enum CompareOps {
AND,
OR,
MID,
MID_OR
}
private static class ConditionResult {
public Condition condition;
int end;
int block_end;
}
private ConditionResult makeCondition(int index) {
int condition_start = index;
int condition_end = index;
for (; condition_end < this.intermediates.size(); condition_end++) {
IntermediateOpcode onext = this.intermediates.get(condition_end);
if (onext instanceof IntermediateStatement) {
condition_end--;
break;
}
}
Set<LabelNode> seen_labels = Sets.newHashSet();
List<IntermediateOpcode> group = Lists.newArrayList();
int farthest = 0;
for (int i = condition_start; i < condition_end; i++) {
IntermediateOpcode cnext = this.intermediates.get(i);
if (cnext instanceof IntermediateLabel) {
if (i == condition_end - 1) {
break;
}
boolean sharing = false;
for (int o = i + 1; o < condition_end; o++) {
IntermediateOpcode onext = this.intermediates.get(o);
if (onext instanceof IntermediateJump) {
LabelNode label = ((IntermediateJump) onext).getNode().label;
if (seen_labels.contains(label)) {
sharing = true;
break;
}
if (this.label_indices.get(label.getLabel()) > farthest) {
sharing = true;
break;
}
} else if (onext instanceof IntermediateLabel) {
break;
}
}
if (!sharing) {
for (int c = condition_start; c < i; c++) {
group.add(this.intermediates.get(c));
}
condition_end = i;
farthest = -1;
break;
}
} else if (cnext instanceof IntermediateJump) {
LabelNode label = ((IntermediateJump) cnext).getNode().label;
seen_labels.add(label);
int target = this.label_indices.get(label.getLabel());
if (target > farthest) {
farthest = target;
}
}
}
if (farthest != -1) {
for (int c = condition_start; c < condition_end; c++) {
group.add(this.intermediates.get(c));
}
}
Condition condition = makeCondition(group);
LabelNode break_node = ((IntermediateJump) group.get(group.size() - 1)).getNode().label;
int block_end = this.label_indices.get(break_node.getLabel());
ConditionResult result = new ConditionResult();
result.condition = condition;
result.end = condition_end;
result.block_end = block_end;
return result;
}
private Condition makeCondition(List<IntermediateOpcode> group) {
int start = this.intermediates.indexOf(group.get(0));
IntermediateOpcode last = group.get(group.size() - 1);
int end = this.intermediates.indexOf(last);
LabelNode break_node = ((IntermediateJump) group.get(group.size() - 1)).getNode().label;
Deque<Condition> stack = Queues.newArrayDeque();
Deque<CompareOps> ops_stack = Queues.newArrayDeque();
for (int i = 0; i < group.size(); i++) {
IntermediateOpcode next = group.get(i);
if (next instanceof IntermediateJump) {
JumpInsnNode node = ((IntermediateJump) next).getNode();
if (node.label == break_node) {
if (next instanceof IntermediateConditionalJump) {
if (node.getOpcode() == IFEQ) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), false));
} else if (node.getOpcode() == IFNE) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), true));
} else if (node.getOpcode() == IFNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.NOT_EQUAL));
} else if (node.getOpcode() == IFNONNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.EQUAL));
} else {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new IntConstantArg(0),
CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
} else {
IntermediateCompareJump cmp = (IntermediateCompareJump) next;
stack.push(new CompareCondition(cmp.getLeft(), cmp.getRight(), CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
if (!ops_stack.isEmpty()) {
CompareOps op = ops_stack.peek();
if (op == CompareOps.AND) {
ops_stack.pop();
Condition left = stack.pop();
Condition right = stack.pop();
AndCondition cond = new AndCondition(right, left);
stack.push(cond);
}
if (i < group.size() - 1) {
if (group.get(i + 1) instanceof IntermediateLabel) {
CompareOps nop = ops_stack.peek();
if (nop == CompareOps.OR || nop == CompareOps.MID) {
ops_stack.pop();
Condition left = stack.pop();
Condition right = new InverseCondition(stack.pop());
OrCondition cond = new OrCondition(right, left);
stack.push(cond);
ops_stack.push(CompareOps.AND);
}
} else {
ops_stack.push(CompareOps.AND);
}
}
} else if (i < group.size() - 1) {
ops_stack.push(CompareOps.AND);
}
} else {
int jump_target = this.label_indices.get(node.label.getLabel());
if (jump_target <= end && jump_target >= start) {
if (next instanceof IntermediateConditionalJump) {
if (node.getOpcode() == IFEQ) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), false));
} else if (node.getOpcode() == IFNE) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), true));
} else if (node.getOpcode() == IFNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.NOT_EQUAL));
} else if (node.getOpcode() == IFNONNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.EQUAL));
} else {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new IntConstantArg(0),
CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
} else {
IntermediateCompareJump cmp = (IntermediateCompareJump) next;
stack.push(new CompareCondition(cmp.getLeft(), cmp.getRight(), CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
if (ops_stack.peek() == CompareOps.MID) {
ops_stack.pop();
Condition left = stack.pop();
Condition right = new InverseCondition(stack.pop());
OrCondition cond = new OrCondition(right, left);
stack.push(cond);
}
ops_stack.push(CompareOps.MID);
} else {
if (next instanceof IntermediateConditionalJump) {
if (node.getOpcode() == IFEQ) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), true));
} else if (node.getOpcode() == IFNE) {
stack.push(new BooleanCondition(((IntermediateConditionalJump) next).getCondition(), false));
} else if (node.getOpcode() == IFNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.NOT_EQUAL));
} else if (node.getOpcode() == IFNONNULL) {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new NullConstantArg(),
CompareOp.EQUAL));
} else {
stack.push(new CompareCondition(((IntermediateConditionalJump) next).getCondition(), new IntConstantArg(0),
CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
} else {
IntermediateCompareJump cmp = (IntermediateCompareJump) next;
stack.push(new CompareCondition(cmp.getLeft(), cmp.getRight(), CompareCondition.fromOpcode(node.getOpcode()).inverse()));
}
if (ops_stack.peek() == CompareOps.MID) {
if (i < group.size() - 1 && group.get(i + 1) instanceof IntermediateLabel) {
ops_stack.pop();
Condition left = stack.pop();
Condition right = stack.pop();
AndCondition cond = new AndCondition(right, left);
stack.push(cond);
} else {
ops_stack.pop();
ops_stack.push(CompareOps.MID_OR);
}
} else if (ops_stack.peek() == CompareOps.MID_OR) {
ops_stack.pop();
Condition left = stack.pop();
Condition right = stack.pop();
OrCondition cond = new OrCondition(right, left);
Condition right2 = stack.pop();
AndCondition cond2 = new AndCondition(right2, cond);
stack.push(cond2);
} else {
ops_stack.push(CompareOps.OR);
}
}
}
}
}
while (!ops_stack.isEmpty()) {
Condition left = stack.pop();
Condition right = stack.pop();
CompareOps op = ops_stack.pop();
if (op == CompareOps.AND) {
AndCondition cond = new AndCondition(right, left);
stack.push(cond);
} else if (op == CompareOps.OR) {
OrCondition cond = new OrCondition(right, left);
stack.push(cond);
}
}
if (stack.size() == 2) {
Condition left = stack.pop();
Condition right = stack.pop();
OrCondition cond = new OrCondition(right, left);
stack.push(cond);
}
return stack.pop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment