Package com.strobel.assembler.ir

Examples of com.strobel.assembler.ir.InstructionCollection


    public MethodBody readBody() {
        final Buffer b = _code.getCode();

        b.position(0);

        final InstructionCollection body = _methodBody.getInstructions();
        final VariableDefinitionCollection variables = _methodBody.getVariables();

        final LocalVariableTableAttribute localVariableTable = SourceAttribute.find(
            AttributeNames.LocalVariableTable,
            _code.getAttributes()
        );

        final LocalVariableTableAttribute localVariableTypeTable = SourceAttribute.find(
            AttributeNames.LocalVariableTypeTable,
            _code.getAttributes()
        );

        final boolean hasThis = !Modifier.isStatic(_modifiers);
        final List<ParameterDefinition> parameters = _methodDefinition.getParameters();

        if (hasThis) {
            final VariableDefinition thisVariable = new VariableDefinition(
                0,
                "this",
                _methodDefinition,
                _declaringType
            );

            thisVariable.setScopeStart(0);
            thisVariable.setScopeEnd(_code.getCodeSize());
            thisVariable.setFromMetadata(true);

            variables.add(thisVariable);

            _methodBody.setThisParameter(new ParameterDefinition(0, "this", _declaringType));
        }

        for (int i = 0; i < parameters.size(); i++) {
            final ParameterDefinition parameter = parameters.get(i);
            final int variableSlot = parameter.getSlot();
            final VariableDefinition variable = variables.ensure(variableSlot, OpCode.NOP, 0);

            variable.setScopeStart(0);
            variable.setScopeEnd(_code.getCodeSize());
            variable.setTypeKnown(true);
            variable.setName(parameter.getName());
            variable.setFromMetadata(true);
            variable.setVariableType(parameter.getParameterType());
        }

        if (localVariableTable != null) {
            processLocalVariableTable(variables, localVariableTable, parameters);
        }

        if (localVariableTypeTable != null) {
            processLocalVariableTable(variables, localVariableTypeTable, parameters);
        }

        variables.mergeVariables();

        @SuppressWarnings("unchecked")
        final Fixup[] fixups = new Fixup[b.size()];

        while (b.position() < b.size()) {
            final int offset = b.position();

            int code = b.readUnsignedByte();

            if (code == OpCode.WIDE) {
                code = code << 8 | b.readUnsignedByte();
            }

            final OpCode op = OpCode.get(code);
            final Instruction instruction;

            switch (op.getOperandType()) {
                case None: {
                    if (op.isLoad() || op.isStore()) {
                        variables.ensure(OpCodeHelpers.getLoadStoreMacroArgumentIndex(op), op, offset);
                    }
                    instruction = Instruction.create(op);
                    break;
                }

                case PrimitiveTypeCode: {
                    instruction = Instruction.create(op, BuiltinTypes.fromPrimitiveTypeCode(b.readUnsignedByte()));
                    break;
                }

                case TypeReference: {
                    final int typeToken = b.readUnsignedShort();
                    instruction = Instruction.create(op, _scope.lookupType(typeToken));
                    break;
                }

                case TypeReferenceU1: {
                    instruction = Instruction.create(op, _scope.lookupType(b.readUnsignedShort()), b.readUnsignedByte());
                    break;
                }

                case DynamicCallSite: {
                    instruction = Instruction.create(op, _scope.lookupDynamicCallSite(b.readUnsignedShort()));
                    b.readUnsignedByte();
                    b.readUnsignedByte();
                    break;
                }

                case MethodReference: {
                    instruction = Instruction.create(op, _scope.lookupMethod(b.readUnsignedShort()));

                    if (op == OpCode.INVOKEINTERFACE) {
                        b.readUnsignedByte();
                        b.readUnsignedByte();
                    }

                    break;
                }

                case FieldReference: {
                    instruction = Instruction.create(op, _scope.lookupField(b.readUnsignedShort()));
                    break;
                }

                case BranchTarget: {
                    final int targetOffset;

                    instruction = new Instruction(op);

                    if (op.isWide()) {
                        targetOffset = offset + _scope.<Integer>lookupConstant(b.readUnsignedShort());
                    }
                    else {
                        targetOffset = offset + (int) b.readShort();
                    }

                    if (targetOffset < offset) {
                        final Instruction target = body.atOffset(targetOffset);

                        if (!target.hasLabel()) {
                            target.setLabel(new Label(targetOffset));
                        }

                        instruction.setOperand(target);
                    }
                    else if (targetOffset == offset) {
                        instruction.setOperand(instruction);
                        instruction.setLabel(new Label(offset));
                    }
                    else if (targetOffset > b.size()) {
                        //
                        // Target is a label after the last instruction.  Insert a dummy NOP.
                        //
                        instruction.setOperand(new Instruction(targetOffset, OpCode.NOP));
                    }
                    else {
                        final Fixup oldFixup = fixups[targetOffset];
                        final Fixup newFixup = new Fixup() {
                            @Override
                            public void fix(final Instruction target) {
                                instruction.setOperand(target);
                            }
                        };

                        fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                : newFixup;
                    }

                    break;
                }

                case I1: {
                    instruction = Instruction.create(op, b.readByte());
                    break;
                }

                case I2: {
                    instruction = Instruction.create(op, b.readShort());
                    break;
                }

                case I8: {
                    instruction = Instruction.create(op, b.readLong());
                    break;
                }

                case Constant: {
                    instruction = new Instruction(op, _scope.lookupConstant(b.readUnsignedByte()));
                    break;
                }

                case WideConstant: {
                    final int constantToken = b.readUnsignedShort();
                    instruction = new Instruction(op, _scope.lookupConstant(constantToken));
                    break;
                }

                case Switch: {
                    while (b.position() % 4 != 0) {
                        b.readByte();
                    }

                    final SwitchInfo switchInfo = new SwitchInfo();
                    final int defaultOffset = offset + b.readInt();

                    instruction = Instruction.create(op, switchInfo);

                    if (defaultOffset < offset) {
                        switchInfo.setDefaultTarget(body.atOffset(defaultOffset));
                    }
                    else if (defaultOffset == offset) {
                        switchInfo.setDefaultTarget(instruction);
                    }
                    else {
                        switchInfo.setDefaultTarget(new Instruction(defaultOffset, OpCode.NOP));

                        final Fixup oldFixup = fixups[defaultOffset];
                        final Fixup newFixup = new Fixup() {
                            @Override
                            public void fix(final Instruction target) {
                                switchInfo.setDefaultTarget(target);
                            }
                        };

                        fixups[defaultOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                 : newFixup;
                    }

                    if (op == OpCode.TABLESWITCH) {
                        final int low = b.readInt();
                        final int high = b.readInt();
                        final Instruction[] targets = new Instruction[high - low + 1];

                        switchInfo.setLowValue(low);
                        switchInfo.setHighValue(high);

                        for (int i = 0; i < targets.length; i++) {
                            final int targetIndex = i;
                            final int targetOffset = offset + b.readInt();

                            if (targetOffset < offset) {
                                targets[targetIndex] = body.atOffset(targetOffset);
                            }
                            else if (targetOffset == offset) {
                                targets[targetIndex] = instruction;
                            }
                            else {
                                targets[targetIndex] = new Instruction(targetOffset, OpCode.NOP);

                                final Fixup oldFixup = fixups[targetOffset];
                                final Fixup newFixup = new Fixup() {
                                    @Override
                                    public void fix(final Instruction target) {
                                        targets[targetIndex] = target;
                                    }
                                };

                                fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                        : newFixup;
                            }
                        }

                        switchInfo.setTargets(targets);
                    }
                    else {
                        final int pairCount = b.readInt();
                        final int[] keys = new int[pairCount];
                        final Instruction[] targets = new Instruction[pairCount];

                        for (int i = 0; i < pairCount; i++) {
                            final int targetIndex = i;

                            keys[targetIndex] = b.readInt();

                            final int targetOffset = offset + b.readInt();

                            if (targetOffset < offset) {
                                targets[targetIndex] = body.atOffset(targetOffset);
                            }
                            else if (targetOffset == offset) {
                                targets[targetIndex] = instruction;
                            }
                            else {
                                targets[targetIndex] = new Instruction(targetOffset, OpCode.NOP);

                                final Fixup oldFixup = fixups[targetOffset];
                                final Fixup newFixup = new Fixup() {
                                    @Override
                                    public void fix(final Instruction target) {
                                        targets[targetIndex] = target;
                                    }
                                };

                                fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                        : newFixup;
                            }
                        }

                        switchInfo.setKeys(keys);
                        switchInfo.setTargets(targets);
                    }

                    break;
                }

                case Local: {
                    final int variableSlot;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableDefinition variable = variables.ensure(variableSlot, op, offset);

                    if (variableSlot < 0) {
                        instruction = new Instruction(op, new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"));
                    }
                    else {
                        instruction = Instruction.create(op, variable);
                    }

                    break;
                }

                case LocalI1: {
                    final int variableSlot;
                    final int operand;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableDefinition variable = variables.ensure(variableSlot, op, offset);

                    operand = b.readByte();

                    if (variableSlot < 0) {
                        instruction = new Instruction(
                            op,
                            new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"),
                            operand
                        );
                    }
                    else {
                        instruction = Instruction.create(op, variable, operand);
                    }

                    break;
                }

                case LocalI2: {
                    final int variableSlot;
                    final int operand;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableDefinition variable = variables.ensure(variableSlot, op, offset);

                    operand = b.readShort();

                    if (variableSlot < 0) {
                        instruction = new Instruction(
                            op,
                            new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"),
                            operand
                        );
                    }
                    else {
                        instruction = Instruction.create(op, variable, operand);
                    }

                    break;
                }

                default: {
                    throw new IllegalStateException("Unrecognized opcode: " + code);
                }
            }

            instruction.setOffset(offset);
            body.add(instruction);

            final Fixup fixup = fixups[offset];

            if (fixup != null) {
                if (!instruction.hasLabel()) {
                    instruction.setLabel(new Label(offset));
                }
                fixup.fix(instruction);
            }
        }

        variables.updateScopes(_code.getCodeSize());
        variables.mergeVariables();
        variables.updateScopes(_code.getCodeSize());

        int labelCount = 0;

        for (int i = 0; i < body.size(); i++) {
            final Instruction instruction = body.get(i);
            final OpCode code = instruction.getOpCode();
            final Object operand = instruction.hasOperand() ? instruction.getOperand(0) : null;

            if (operand instanceof VariableDefinition) {
                final VariableDefinition currentVariable = (VariableDefinition) operand;
View Full Code Here


    private void createNodes() {
        //
        // Step 2a: Find basic blocks and create nodes for them.
        //

        final InstructionCollection instructions = _instructions;

        for (int i = 0, n = instructions.size(); i < n; i++) {
            final Instruction blockStart = instructions.get(i);
            final ExceptionTableEntry blockStartExceptionHandler = findInnermostExceptionHandler(blockStart.getOffset());

            //
            // See how big we can make that block...
            //
            for (; i + 1 < n; i++) {
                final Instruction instruction = instructions.get(i);
                final OpCode opCode = instruction.getOpCode();

                if (opCode.isUnconditionalBranch() /*|| opCode.canThrow()*/ || _hasIncomingJumps[i + 1]) {
                    break;
                }

                final Instruction next = instruction.getNext();

                if (next != null) {
                    //
                    // Ensure that blocks never contain instructions from different try blocks.
                    //
                    final ExceptionTableEntry innermostExceptionHandler = findInnermostExceptionHandler(next.getOffset());

                    if (innermostExceptionHandler != blockStartExceptionHandler) {
                        break;
                    }
                }
            }

            final ControlFlowNode node = new ControlFlowNode(_nodes.size(), blockStart, instructions.get(i));

            node.setUserData(blockStartExceptionHandler);

            _nodes.add(node);
        }
View Full Code Here

    private void createRegularControlFlow() {
        //
        // Step 3: Create edges for the normal control flow (assuming no exceptions thrown).
        //

        final InstructionCollection instructions = _instructions;

        createEdge(_entryPoint, instructions.get(0), JumpType.Normal);

        for (final ControlFlowNode node : _nodes) {
            final Instruction end = node.getEnd();

            if (end == null || end.getOffset() >= _instructions.get(_instructions.size() - 1).getEndOffset()) {
View Full Code Here

            }
            finally {
                output.unindent();
            }

            final InstructionCollection instructions = body.getInstructions();

            if (!instructions.isEmpty()) {
                final int[] lineNumbers;

                if (options.getSettings().getIncludeLineNumbersInBytecode()) {
                    final LineNumberTableAttribute lineNumbersAttribute = SourceAttribute.find(
                        AttributeNames.LineNumberTable,
View Full Code Here

    private List<Node> findConditions(final Set<ControlFlowNode> scopeNodes, final ControlFlowNode entryNode) {
        final List<Node> result = new ArrayList<>();
        final Set<ControlFlowNode> scope = new HashSet<>(scopeNodes);
        final Stack<ControlFlowNode> agenda = new Stack<>();
        final MethodBody methodBody = _context.getCurrentMethod().getBody();
        final InstructionCollection instructions = methodBody.getInstructions();

        agenda.push(entryNode);

        while (!agenda.isEmpty()) {
            final ControlFlowNode node = agenda.pop();

            if (node == null) {
                continue;
            }

            //
            // Find a block that represents a simple condition.
            //

            if (scope.contains(node)) {
                final BasicBlock block = (BasicBlock) node.getUserData();
                final List<Node> blockBody = block.getBody();

                final StrongBox<Label[]> caseLabels = new StrongBox<>();
                final StrongBox<Expression> switchArgument = new StrongBox<>();
                final StrongBox<Label> fallLabel = new StrongBox<>();
                final StrongBox<Label> tempTarget = new StrongBox<>();

                AstCode switchCode;

                if (matchLastAndBreak(block, switchCode = AstCode.TableSwitch, caseLabels, switchArgument, fallLabel) ||
                    matchLastAndBreak(block, switchCode = AstCode.LookupSwitch, caseLabels, switchArgument, fallLabel)) {

                    final Expression switchExpression = (Expression) blockBody.get(blockBody.size() - 2);
                    final Collection<Range> switchRanges = switchExpression.getArguments().get(0).getRanges();
                    final Instruction switchInstruction = instructions.atOffset(switchRanges.get(switchRanges.size() - 1).getStart());

                    //
                    // Replace the switch code with a Switch node.
                    //
View Full Code Here

    private int _maxLocals;
    private int _codeSize;

    public MethodBody(final MethodDefinition methodDefinition) {
        _method = VerifyArgument.notNull(methodDefinition, "methodDefinition");
        _instructions = new InstructionCollection();
        _variables = new VariableDefinitionCollection(methodDefinition);
        _exceptionHandlers = new Collection<>();
    }
View Full Code Here

    private void createNodes() {
        //
        // Step 2a: Find basic blocks and create nodes for them.
        //

        final InstructionCollection instructions = _instructions;

        for (int i = 0, n = instructions.size(); i < n; i++) {
            final Instruction blockStart = instructions.get(i);
            final ExceptionHandler blockStartExceptionHandler = findInnermostExceptionHandler(blockStart.getOffset());

            //
            // See how big we can make that block...
            //
            for (; i + 1 < n; i++) {
                final Instruction instruction = instructions.get(i);
                final OpCode opCode = instruction.getOpCode();

                if (opCode.isBranch() && !opCode.isJumpToSubroutine() /*|| opCode.canThrow()*/ || _hasIncomingJumps[i + 1]) {
                    break;
                }

                final Instruction next = instruction.getNext();

                if (next != null) {
                    //
                    // Ensure that blocks never contain instructions from different try blocks.
                    //
                    final ExceptionHandler innermostExceptionHandler = findInnermostExceptionHandler(next.getOffset());

                    if (innermostExceptionHandler != blockStartExceptionHandler) {
                        break;
                    }
                }
            }

            final ControlFlowNode node = new ControlFlowNode(_nodes.size(), blockStart, instructions.get(i));

            node.setUserData(blockStartExceptionHandler);

            _nodes.add(node);
        }
View Full Code Here

    private void createRegularControlFlow() {
        //
        // Step 3: Create edges for the normal control flow (assuming no exceptions thrown).
        //

        final InstructionCollection instructions = _instructions;

        createEdge(_entryPoint, instructions.get(0), JumpType.Normal);

        for (final ControlFlowNode node : _nodes) {
            final Instruction end = node.getEnd();

            if (end == null || end.getOffset() >= _instructions.get(_instructions.size() - 1).getEndOffset()) {
View Full Code Here

    public MethodBody readBody() {
        final Buffer b = _code.getCode();

        b.position(0);

        final InstructionCollection body = _methodBody.getInstructions();
        final VariableDefinitionCollection variables = _methodBody.getVariables();

        final LocalVariableTableAttribute localVariableTable = SourceAttribute.find(
            AttributeNames.LocalVariableTable,
            _code.getAttributes()
        );

        final LocalVariableTableAttribute localVariableTypeTable = SourceAttribute.find(
            AttributeNames.LocalVariableTypeTable,
            _code.getAttributes()
        );

        final boolean hasThis = !Modifier.isStatic(_modifiers);
        final List<ParameterDefinition> parameters = _methodDefinition.getParameters();

        if (hasThis) {
            final ParameterDefinition thisParameter = new ParameterDefinition(
                0,
                "this",
                _declaringType
            );

            final VariableDefinition thisVariable = new VariableDefinition(
                0,
                "this",
                _methodDefinition,
                _declaringType
            );

            thisVariable.setScopeStart(0);
            thisVariable.setScopeEnd(_code.getCodeSize());
            thisVariable.setFromMetadata(false);
            thisVariable.setParameter(thisParameter);

            variables.add(thisVariable);

            _methodBody.setThisParameter(thisParameter);
        }

        for (int i = 0; i < parameters.size(); i++) {
            final ParameterDefinition parameter = parameters.get(i);
            final int variableSlot = parameter.getSlot();

            final VariableDefinition variable = new VariableDefinition(
                variableSlot,
                parameter.getName(),
                _methodDefinition,
                parameter.getParameterType()
            );

            variable.setScopeStart(0);
            variable.setScopeEnd(_code.getCodeSize());
            variable.setTypeKnown(true);
            variable.setFromMetadata(false);
            variable.setParameter(parameter);

            variables.add(variable);
        }

        if (localVariableTable != null) {
            processLocalVariableTable(variables, localVariableTable, parameters);
        }

        if (localVariableTypeTable != null) {
            processLocalVariableTable(variables, localVariableTypeTable, parameters);
        }

        for (final VariableDefinition variable : variables) {
            if (!variable.isFromMetadata()) {
                variable.setScopeStart(-1);
                variable.setScopeEnd(-1);
            }
        }

        @SuppressWarnings("unchecked")
        final Fixup[] fixups = new Fixup[b.size()];

        while (b.position() < b.size()) {
            final int offset = b.position();

            int code = b.readUnsignedByte();

            if (code == OpCode.WIDE) {
                code = code << 8 | b.readUnsignedByte();
            }

            final OpCode op = OpCode.get(code);
            final Instruction instruction;

            switch (op.getOperandType()) {
                case None: {
                    if (op.isLoad() || op.isStore()) {
                        variables.reference(OpCodeHelpers.getLoadStoreMacroArgumentIndex(op), op, offset);
                    }
                    instruction = Instruction.create(op);
                    break;
                }

                case PrimitiveTypeCode: {
                    instruction = Instruction.create(op, BuiltinTypes.fromPrimitiveTypeCode(b.readUnsignedByte()));
                    break;
                }

                case TypeReference: {
                    final int typeToken = b.readUnsignedShort();
                    instruction = Instruction.create(op, _scope.lookupType(typeToken));
                    break;
                }

                case TypeReferenceU1: {
                    instruction = Instruction.create(op, _scope.lookupType(b.readUnsignedShort()), b.readUnsignedByte());
                    break;
                }

                case DynamicCallSite: {
                    instruction = Instruction.create(op, _scope.lookupDynamicCallSite(b.readUnsignedShort()));
                    b.readUnsignedByte();
                    b.readUnsignedByte();
                    break;
                }

                case MethodReference: {
                    instruction = Instruction.create(op, _scope.lookupMethod(b.readUnsignedShort()));

                    if (op == OpCode.INVOKEINTERFACE) {
                        b.readUnsignedByte();
                        b.readUnsignedByte();
                    }

                    break;
                }

                case FieldReference: {
                    instruction = Instruction.create(op, _scope.lookupField(b.readUnsignedShort()));
                    break;
                }

                case BranchTarget: {
                    final int targetOffset;

                    instruction = new Instruction(op);

                    if (op.isWide()) {
                        targetOffset = offset + _scope.<Integer>lookupConstant(b.readUnsignedShort());
                    }
                    else {
                        targetOffset = offset + (int) b.readShort();
                    }

                    if (targetOffset < offset) {
                        final Instruction target = body.atOffset(targetOffset);

                        if (!target.hasLabel()) {
                            target.setLabel(new Label(targetOffset));
                        }

                        instruction.setOperand(target);
                    }
                    else if (targetOffset == offset) {
                        instruction.setOperand(instruction);
                        instruction.setLabel(new Label(offset));
                    }
                    else if (targetOffset > b.size()) {
                        //
                        // Target is a label after the last instruction.  Insert a dummy NOP.
                        //
                        instruction.setOperand(new Instruction(targetOffset, OpCode.NOP));
                    }
                    else {
                        final Fixup oldFixup = fixups[targetOffset];
                        final Fixup newFixup = new Fixup() {
                            @Override
                            public void fix(final Instruction target) {
                                instruction.setOperand(target);
                            }
                        };

                        fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                : newFixup;
                    }

                    break;
                }

                case I1: {
                    instruction = Instruction.create(op, b.readByte());
                    break;
                }

                case I2: {
                    instruction = Instruction.create(op, b.readShort());
                    break;
                }

                case I8: {
                    instruction = Instruction.create(op, b.readLong());
                    break;
                }

                case Constant: {
                    //noinspection RedundantTypeArguments
                    instruction = new Instruction(op, _scope.<Object>lookupConstant(b.readUnsignedByte()));
                    break;
                }

                case WideConstant: {
                    final int constantToken = b.readUnsignedShort();
                    //noinspection RedundantTypeArguments
                    instruction = new Instruction(op, _scope.<Object>lookupConstant(constantToken));
                    break;
                }

                case Switch: {
                    while (b.position() % 4 != 0) {
                        b.readByte();
                    }

                    final SwitchInfo switchInfo = new SwitchInfo();
                    final int defaultOffset = offset + b.readInt();

                    instruction = Instruction.create(op, switchInfo);

                    if (defaultOffset < offset) {
                        switchInfo.setDefaultTarget(body.atOffset(defaultOffset));
                    }
                    else if (defaultOffset == offset) {
                        switchInfo.setDefaultTarget(instruction);
                    }
                    else {
                        switchInfo.setDefaultTarget(new Instruction(defaultOffset, OpCode.NOP));

                        final Fixup oldFixup = fixups[defaultOffset];
                        final Fixup newFixup = new Fixup() {
                            @Override
                            public void fix(final Instruction target) {
                                switchInfo.setDefaultTarget(target);
                            }
                        };

                        fixups[defaultOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                 : newFixup;
                    }

                    if (op == OpCode.TABLESWITCH) {
                        final int low = b.readInt();
                        final int high = b.readInt();
                        final Instruction[] targets = new Instruction[high - low + 1];

                        switchInfo.setLowValue(low);
                        switchInfo.setHighValue(high);

                        for (int i = 0; i < targets.length; i++) {
                            final int targetIndex = i;
                            final int targetOffset = offset + b.readInt();

                            if (targetOffset < offset) {
                                targets[targetIndex] = body.atOffset(targetOffset);
                            }
                            else if (targetOffset == offset) {
                                targets[targetIndex] = instruction;
                            }
                            else {
                                targets[targetIndex] = new Instruction(targetOffset, OpCode.NOP);

                                final Fixup oldFixup = fixups[targetOffset];
                                final Fixup newFixup = new Fixup() {
                                    @Override
                                    public void fix(final Instruction target) {
                                        targets[targetIndex] = target;
                                    }
                                };

                                fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                        : newFixup;
                            }
                        }

                        switchInfo.setTargets(targets);
                    }
                    else {
                        final int pairCount = b.readInt();
                        final int[] keys = new int[pairCount];
                        final Instruction[] targets = new Instruction[pairCount];

                        for (int i = 0; i < pairCount; i++) {
                            final int targetIndex = i;

                            keys[targetIndex] = b.readInt();

                            final int targetOffset = offset + b.readInt();

                            if (targetOffset < offset) {
                                targets[targetIndex] = body.atOffset(targetOffset);
                            }
                            else if (targetOffset == offset) {
                                targets[targetIndex] = instruction;
                            }
                            else {
                                targets[targetIndex] = new Instruction(targetOffset, OpCode.NOP);

                                final Fixup oldFixup = fixups[targetOffset];
                                final Fixup newFixup = new Fixup() {
                                    @Override
                                    public void fix(final Instruction target) {
                                        targets[targetIndex] = target;
                                    }
                                };

                                fixups[targetOffset] = oldFixup != null ? Fixup.combine(oldFixup, newFixup)
                                                                        : newFixup;
                            }
                        }

                        switchInfo.setKeys(keys);
                        switchInfo.setTargets(targets);
                    }

                    break;
                }

                case Local: {
                    final int variableSlot;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableReference variable = variables.reference(variableSlot, op, offset);

                    if (variableSlot < 0) {
                        instruction = new Instruction(op, new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"));
                    }
                    else {
                        instruction = Instruction.create(op, variable);
                    }

                    break;
                }

                case LocalI1: {
                    final int variableSlot;
                    final int operand;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableReference variable = variables.reference(variableSlot, op, offset);

                    operand = b.readByte();

                    if (variableSlot < 0) {
                        instruction = new Instruction(
                            op,
                            new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"),
                            operand
                        );
                    }
                    else {
                        instruction = Instruction.create(op, variable, operand);
                    }

                    break;
                }

                case LocalI2: {
                    final int variableSlot;
                    final int operand;

                    if (op.isWide()) {
                        variableSlot = b.readUnsignedShort();
                    }
                    else {
                        variableSlot = b.readUnsignedByte();
                    }

                    final VariableReference variable = variables.reference(variableSlot, op, offset);

                    operand = b.readShort();

                    if (variableSlot < 0) {
                        instruction = new Instruction(
                            op,
                            new ErrorOperand("!!! BAD LOCAL: " + variableSlot + " !!!"),
                            operand
                        );
                    }
                    else {
                        instruction = Instruction.create(op, variable, operand);
                    }

                    break;
                }

                default: {
                    throw new IllegalStateException("Unrecognized opcode: " + code);
                }
            }

            instruction.setOffset(offset);
            body.add(instruction);

            final Fixup fixup = fixups[offset];

            if (fixup != null) {
                if (!instruction.hasLabel()) {
                    instruction.setLabel(new Label(offset));
                }
                fixup.fix(instruction);
            }
        }

        int labelCount = 0;

        for (int i = 0; i < body.size(); i++) {
            final Instruction instruction = body.get(i);
            final OpCode code = instruction.getOpCode();
            final Object operand = instruction.hasOperand() ? instruction.getOperand(0) : null;

            if (operand instanceof VariableDefinition) {
                final VariableDefinition currentVariable = (VariableDefinition) operand;
View Full Code Here

TOP

Related Classes of com.strobel.assembler.ir.InstructionCollection

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.