public void writeMethod(MethodCall _methodCall, MethodEntry _methodEntry) throws CodeGenException { boolean noCL = _methodEntry .getOwnerClassModel() .getNoCLMethods() .contains(_methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); if (noCL) { return; } if (_methodCall instanceof VirtualMethodCall) { final Instruction instanceInstruction = ((VirtualMethodCall) _methodCall).getInstanceReference(); if (!(instanceInstruction instanceof I_ALOAD_0)) { writeInstruction(instanceInstruction); write("."); } else { writeThisRef(); } } final int argc = _methodEntry.getStackConsumeCount(); write(_methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); write("("); for (int arg = 0; arg < argc; arg++) { if (arg != 0) { write(", "); } writeInstruction(_methodCall.getArg(arg)); } write(")"); }
public void writeInstruction(Instruction _instruction) throws CodeGenException { if (_instruction instanceof CompositeIfElseInstruction) { write("("); final Instruction lhs = writeConditional(((CompositeInstruction) _instruction).getBranchSet()); write(")?"); writeInstruction(lhs); write(":"); writeInstruction(lhs.getNextExpr().getNextExpr()); } else if (_instruction instanceof CompositeInstruction) { writeComposite((CompositeInstruction) _instruction); } else if (_instruction instanceof AssignToLocalVariable) { final AssignToLocalVariable assignToLocalVariable = (AssignToLocalVariable) _instruction; final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo(); if (assignToLocalVariable.isDeclaration()) { final String descriptor = localVariableInfo.getVariableDescriptor(); // Arrays always map to __global arrays if (descriptor.startsWith("[")) { write(" __global "); } write(convertType(descriptor, true)); } if (localVariableInfo == null) { throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = "); } else { write(localVariableInfo.getVariableName() + " = "); } for (Instruction operand = _instruction.getFirstChild(); operand != null; operand = operand.getNextExpr()) { writeInstruction(operand); } } else if (_instruction instanceof AssignToArrayElement) { final AssignToArrayElement arrayAssignmentInstruction = (AssignToArrayElement) _instruction; writeInstruction(arrayAssignmentInstruction.getArrayRef()); write("["); writeInstruction(arrayAssignmentInstruction.getArrayIndex()); write("]"); write(" "); write(" = "); writeInstruction(arrayAssignmentInstruction.getValue()); } else if (_instruction instanceof AccessArrayElement) { // we're getting an element from an array // if the array is a primitive then we just return the value // so the generated code looks like // arrayName[arrayIndex]; // but if the array is an object, or multidimensional array, then we want to return // a pointer to our index our position in the array. The code will look like // &(arrayName[arrayIndex * this->arrayNameLen_dimension] // final AccessArrayElement arrayLoadInstruction = (AccessArrayElement) _instruction; // object array, get address if (arrayLoadInstruction instanceof I_AALOAD) { write("(&"); } writeInstruction(arrayLoadInstruction.getArrayRef()); write("["); writeInstruction(arrayLoadInstruction.getArrayIndex()); // object array, find the size of each object in the array // for 2D arrays, this size is the size of a row. if (arrayLoadInstruction instanceof I_AALOAD) { int dim = 0; Instruction load = arrayLoadInstruction.getArrayRef(); while (load instanceof I_AALOAD) { load = load.getFirstChild(); dim++; } String arrayName = ((AccessInstanceField) load) .getConstantPoolFieldEntry() .getNameAndTypeEntry() .getNameUTF8Entry() .getUTF8(); write(" * this->" + arrayName + arrayDimMangleSuffix + dim); } write("]"); // object array, close parentheses if (arrayLoadInstruction instanceof I_AALOAD) { write(")"); } } else if (_instruction instanceof AccessField) { final AccessField accessField = (AccessField) _instruction; if (accessField instanceof AccessInstanceField) { Instruction accessInstanceField = ((AccessInstanceField) accessField).getInstance(); if (accessInstanceField instanceof CloneInstruction) { accessInstanceField = ((CloneInstruction) accessInstanceField).getReal(); } if (!(accessInstanceField instanceof I_ALOAD_0)) { writeInstruction(accessInstanceField); write("."); } else { writeThisRef(); } } write( accessField .getConstantPoolFieldEntry() .getNameAndTypeEntry() .getNameUTF8Entry() .getUTF8()); } else if (_instruction instanceof I_ARRAYLENGTH) { // getting the length of an array. // if this is a primitive array, then this is trivial // if we're getting an object array, then we need to find what dimension // we're looking at int dim = 0; Instruction load = _instruction.getFirstChild(); while (load instanceof I_AALOAD) { load = load.getFirstChild(); dim++; } final AccessInstanceField child = (AccessInstanceField) load; final String arrayName = child.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8(); write("this->" + arrayName + arrayLengthMangleSuffix + dim); } else if (_instruction instanceof AssignToField) { final AssignToField assignedField = (AssignToField) _instruction; if (assignedField instanceof AssignToInstanceField) { final Instruction accessInstanceField = ((AssignToInstanceField) assignedField).getInstance().getReal(); if (!(accessInstanceField instanceof I_ALOAD_0)) { writeInstruction(accessInstanceField); write("."); } else { writeThisRef(); } } write( assignedField .getConstantPoolFieldEntry() .getNameAndTypeEntry() .getNameUTF8Entry() .getUTF8()); write("="); writeInstruction(assignedField.getValueToAssign()); } else if (_instruction instanceof Constant<?>) { final Constant<?> constantInstruction = (Constant<?>) _instruction; final Object value = constantInstruction.getValue(); if (value instanceof Float) { final Float f = (Float) value; if (f.isNaN()) { write("NAN"); } else if (f.isInfinite()) { if (f < 0) { write("-"); } write("INFINITY"); } else { write(value.toString()); write("f"); } } else if (value instanceof Double) { final Double d = (Double) value; if (d.isNaN()) { write("NAN"); } else if (d.isInfinite()) { if (d < 0) { write("-"); } write("INFINITY"); } else { write(value.toString()); } } else { write(value.toString()); if (value instanceof Long) { write("L"); } } } else if (_instruction instanceof AccessLocalVariable) { final AccessLocalVariable localVariableLoadInstruction = (AccessLocalVariable) _instruction; final LocalVariableInfo localVariable = localVariableLoadInstruction.getLocalVariableInfo(); write(localVariable.getVariableName()); } else if (_instruction instanceof I_IINC) { final I_IINC location = (I_IINC) _instruction; final LocalVariableInfo localVariable = location.getLocalVariableInfo(); final int adjust = location.getAdjust(); write(localVariable.getVariableName()); if (adjust == 1) { write("++"); } else if (adjust == -1) { write("--"); } else if (adjust > 1) { write("+=" + adjust); } else if (adjust < -1) { write("-=" + (-adjust)); } } else if (_instruction instanceof BinaryOperator) { final BinaryOperator binaryInstruction = (BinaryOperator) _instruction; final Instruction parent = binaryInstruction.getParentExpr(); boolean needsParenthesis = true; if (parent instanceof AssignToLocalVariable) { needsParenthesis = false; } else if (parent instanceof AssignToField) { needsParenthesis = false; } else if (parent instanceof AssignToArrayElement) { needsParenthesis = false; } else { /** * if (parent instanceof BinaryOperator) { BinaryOperator parentBinaryOperator = * (BinaryOperator) parent; if (parentBinaryOperator.getOperator().ordinal() > * binaryInstruction.getOperator().ordinal()) { needsParenthesis = false; } } */ } if (needsParenthesis) { write("("); } writeInstruction(binaryInstruction.getLhs()); write(" " + binaryInstruction.getOperator().getText() + " "); writeInstruction(binaryInstruction.getRhs()); if (needsParenthesis) { write(")"); } } else if (_instruction instanceof CastOperator) { final CastOperator castInstruction = (CastOperator) _instruction; // write("("); write(convertCast(castInstruction.getOperator().getText())); writeInstruction(castInstruction.getUnary()); // write(")"); } else if (_instruction instanceof UnaryOperator) { final UnaryOperator unaryInstruction = (UnaryOperator) _instruction; // write("("); write(unaryInstruction.getOperator().getText()); writeInstruction(unaryInstruction.getUnary()); // write(")"); } else if (_instruction instanceof Return) { final Return ret = (Return) _instruction; write("return"); if (ret.getStackConsumeCount() > 0) { write("("); writeInstruction(ret.getFirstChild()); write(")"); } } else if (_instruction instanceof MethodCall) { final MethodCall methodCall = (MethodCall) _instruction; final MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry(); writeMethod(methodCall, methodEntry); } else if (_instruction.getByteCode().equals(ByteCode.CLONE)) { final CloneInstruction cloneInstruction = (CloneInstruction) _instruction; writeInstruction(cloneInstruction.getReal()); } else if (_instruction.getByteCode().equals(ByteCode.INCREMENT)) { final IncrementInstruction incrementInstruction = (IncrementInstruction) _instruction; if (incrementInstruction.isPre()) { if (incrementInstruction.isInc()) { write("++"); } else { write("--"); } } writeInstruction(incrementInstruction.getFieldOrVariableReference()); if (!incrementInstruction.isPre()) { if (incrementInstruction.isInc()) { write("++"); } else { write("--"); } } } else if (_instruction.getByteCode().equals(ByteCode.MULTI_ASSIGN)) { final MultiAssignInstruction multiAssignInstruction = (MultiAssignInstruction) _instruction; AssignToLocalVariable from = (AssignToLocalVariable) multiAssignInstruction.getFrom(); final AssignToLocalVariable last = (AssignToLocalVariable) multiAssignInstruction.getTo(); final Instruction common = multiAssignInstruction.getCommon(); final Stack<AssignToLocalVariable> stack = new Stack<AssignToLocalVariable>(); while (from != last) { stack.push(from); from = (AssignToLocalVariable) ((Instruction) from).getNextExpr(); } for (AssignToLocalVariable alv = stack.pop(); alv != null; alv = stack.size() > 0 ? stack.pop() : null) { final LocalVariableInfo localVariableInfo = alv.getLocalVariableInfo(); if (alv.isDeclaration()) { write(convertType(localVariableInfo.getVariableDescriptor(), true)); } if (localVariableInfo == null) { throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = "); } else { write(localVariableInfo.getVariableName() + " = "); } } writeInstruction(common); } else if (_instruction.getByteCode().equals(ByteCode.INLINE_ASSIGN)) { final InlineAssignInstruction inlineAssignInstruction = (InlineAssignInstruction) _instruction; final AssignToLocalVariable assignToLocalVariable = inlineAssignInstruction.getAssignToLocalVariable(); final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo(); if (assignToLocalVariable.isDeclaration()) { // this is bad! we need a general way to hoist up a required declaration throw new CodeGenException( "/* we can't declare this " + convertType(localVariableInfo.getVariableDescriptor(), true) + " here */"); } write(localVariableInfo.getVariableName()); write("="); writeInstruction(inlineAssignInstruction.getRhs()); } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_ASSIGN)) { final FieldArrayElementAssign inlineAssignInstruction = (FieldArrayElementAssign) _instruction; final AssignToArrayElement arrayAssignmentInstruction = inlineAssignInstruction.getAssignToArrayElement(); writeInstruction(arrayAssignmentInstruction.getArrayRef()); write("["); writeInstruction(arrayAssignmentInstruction.getArrayIndex()); write("]"); write(" "); write(" = "); writeInstruction(inlineAssignInstruction.getRhs()); } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_INCREMENT)) { final FieldArrayElementIncrement fieldArrayElementIncrement = (FieldArrayElementIncrement) _instruction; final AssignToArrayElement arrayAssignmentInstruction = fieldArrayElementIncrement.getAssignToArrayElement(); if (fieldArrayElementIncrement.isPre()) { if (fieldArrayElementIncrement.isInc()) { write("++"); } else { write("--"); } } writeInstruction(arrayAssignmentInstruction.getArrayRef()); write("["); writeInstruction(arrayAssignmentInstruction.getArrayIndex()); write("]"); if (!fieldArrayElementIncrement.isPre()) { if (fieldArrayElementIncrement.isInc()) { write("++"); } else { write("--"); } } } else if (_instruction.getByteCode().equals(ByteCode.NONE)) { // we are done } else if (_instruction instanceof Branch) { throw new CodeGenException( String.format( "%s -> %04d", _instruction.getByteCode().toString().toLowerCase(), ((Branch) _instruction).getTarget().getThisPC())); } else if (_instruction instanceof I_POP) { // POP discarded void call return? writeInstruction(_instruction.getFirstChild()); } else { throw new CodeGenException( String.format("%s", _instruction.getByteCode().toString().toLowerCase())); } }