use of de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef in project Bytecoder by mirkosertic.
the class NaiveProgramGenerator method initializeBlockWith.
private void initializeBlockWith(BytecodeClass aOwningClass, BytecodeMethod aMethod, RegionNode aTargetBlock, Function<BytecodeOpcodeAddress, BytecodeBasicBlock> aBlocksByAddress, ParsingHelper aHelper) {
// Finally we can start to parse the program
BytecodeBasicBlock theBytecodeBlock = aBlocksByAddress.apply(aTargetBlock.getStartAddress());
for (BytecodeInstruction theInstruction : theBytecodeBlock.getInstructions()) {
if (theInstruction instanceof BytecodeInstructionNOP) {
BytecodeInstructionNOP theINS = (BytecodeInstructionNOP) theInstruction;
// Completely ignored
} else if (theInstruction instanceof BytecodeInstructionMONITORENTER) {
BytecodeInstructionMONITORENTER theINS = (BytecodeInstructionMONITORENTER) theInstruction;
// Pop the reference for the lock from the stack
aHelper.pop();
// Completely ignored
} else if (theInstruction instanceof BytecodeInstructionMONITOREXIT) {
BytecodeInstructionMONITOREXIT theINS = (BytecodeInstructionMONITOREXIT) theInstruction;
// Pop the reference for the lock from the stack
aHelper.pop();
// Completely ignored
} else if (theInstruction instanceof BytecodeInstructionCHECKCAST) {
BytecodeInstructionCHECKCAST theINS = (BytecodeInstructionCHECKCAST) theInstruction;
Value theValue = aHelper.peek();
aTargetBlock.getExpressions().add(new CheckCastExpression(theValue, theINS.getTypeCheck()));
} else if (theInstruction instanceof BytecodeInstructionPOP) {
BytecodeInstructionPOP theINS = (BytecodeInstructionPOP) theInstruction;
aHelper.pop();
} else if (theInstruction instanceof BytecodeInstructionPOP2) {
BytecodeInstructionPOP2 theINS = (BytecodeInstructionPOP2) theInstruction;
Value theValue = aHelper.pop();
switch(theValue.resolveType().resolve()) {
case LONG:
break;
case DOUBLE:
break;
default:
aHelper.pop();
}
} else if (theInstruction instanceof BytecodeInstructionDUP) {
BytecodeInstructionDUP theINS = (BytecodeInstructionDUP) theInstruction;
Value theValue = aHelper.peek();
aHelper.push(theValue);
} else if (theInstruction instanceof BytecodeInstructionDUP2) {
BytecodeInstructionDUP2 theINS = (BytecodeInstructionDUP2) theInstruction;
Value theValue1 = aHelper.pop();
if (theValue1.resolveType().resolve() == TypeRef.Native.LONG || theValue1.resolveType().resolve() == TypeRef.Native.DOUBLE) {
// Category 2
aHelper.push(theValue1);
aHelper.push(theValue1);
} else {
// Category 1
Value theValue2 = aHelper.pop();
aHelper.push(theValue2);
aHelper.push(theValue1);
aHelper.push(theValue2);
aHelper.push(theValue1);
}
} else if (theInstruction instanceof BytecodeInstructionDUP2X1) {
BytecodeInstructionDUP2X1 theINS = (BytecodeInstructionDUP2X1) theInstruction;
Value theValue1 = aHelper.pop();
if (theValue1.resolveType().resolve() == TypeRef.Native.LONG || theValue1.resolveType().resolve() == TypeRef.Native.DOUBLE) {
Value theValue2 = aHelper.pop();
aHelper.push(theValue1);
aHelper.push(theValue2);
aHelper.push(theValue2);
} else {
Value theValue2 = aHelper.pop();
Value theValue3 = aHelper.pop();
aHelper.push(theValue2);
aHelper.push(theValue1);
aHelper.push(theValue3);
aHelper.push(theValue2);
aHelper.push(theValue2);
}
} else if (theInstruction instanceof BytecodeInstructionDUPX1) {
BytecodeInstructionDUPX1 theINS = (BytecodeInstructionDUPX1) theInstruction;
Value theValue1 = aHelper.pop();
Value theValue2 = aHelper.pop();
aHelper.push(theValue1);
aHelper.push(theValue2);
aHelper.push(theValue1);
} else if (theInstruction instanceof BytecodeInstructionDUPX2) {
BytecodeInstructionDUPX2 theINS = (BytecodeInstructionDUPX2) theInstruction;
Value theValue1 = aHelper.pop();
Value theValue2 = aHelper.pop();
if (theValue2.resolveType().resolve() == TypeRef.Native.LONG || theValue2.resolveType().resolve() == TypeRef.Native.DOUBLE) {
// Form 2
aHelper.push(theValue1);
aHelper.push(theValue2);
aHelper.push(theValue1);
} else {
// Form 1
Value theValue3 = aHelper.pop();
aHelper.push(theValue1);
aHelper.push(theValue3);
aHelper.push(theValue2);
aHelper.push(theValue1);
}
} else if (theInstruction instanceof BytecodeInstructionGETSTATIC) {
BytecodeInstructionGETSTATIC theINS = (BytecodeInstructionGETSTATIC) theInstruction;
GetStaticExpression theValue = new GetStaticExpression(theINS.getConstant());
Variable theVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getConstant().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().fieldType()), theValue);
aHelper.push(theVariable);
} else if (theInstruction instanceof BytecodeInstructionASTORE) {
BytecodeInstructionASTORE theINS = (BytecodeInstructionASTORE) theInstruction;
Value theValue = aHelper.pop();
aHelper.setLocalVariable(theInstruction.getOpcodeAddress(), theINS.getVariableIndex(), theValue);
} else if (theInstruction instanceof BytecodeInstructionGenericSTORE) {
BytecodeInstructionGenericSTORE theINS = (BytecodeInstructionGenericSTORE) theInstruction;
Value theValue = aHelper.pop();
Variable theOtherVariable = aTargetBlock.newVariable(theValue.resolveType().resolve(), theValue);
aHelper.setLocalVariable(theInstruction.getOpcodeAddress(), theINS.getVariableIndex(), theOtherVariable);
} else if (theInstruction instanceof BytecodeInstructionObjectArrayLOAD) {
BytecodeInstructionObjectArrayLOAD theINS = (BytecodeInstructionObjectArrayLOAD) theInstruction;
Value theIndex = aHelper.pop();
Value theTarget = aHelper.pop();
TypeRef theType = theTarget.resolveType();
if (theType instanceof TypeRef.ArrayTypeRef) {
TypeRef.ArrayTypeRef theArrayTypeRef = (TypeRef.ArrayTypeRef) theTarget.resolveType();
Variable theVariable = aTargetBlock.newVariable(TypeRef.toType(theArrayTypeRef.arrayType()), new ArrayEntryExpression(TypeRef.Native.REFERENCE, theTarget, theIndex));
aHelper.push(theVariable);
} else {
Variable theVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new ArrayEntryExpression(TypeRef.Native.REFERENCE, theTarget, theIndex));
aHelper.push(theVariable);
}
} else if (theInstruction instanceof BytecodeInstructionGenericArrayLOAD) {
BytecodeInstructionGenericArrayLOAD theINS = (BytecodeInstructionGenericArrayLOAD) theInstruction;
Value theIndex = aHelper.pop();
Value theTarget = aHelper.pop();
Variable theVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new ArrayEntryExpression(TypeRef.toType(theINS.getType()), theTarget, theIndex));
aHelper.push(theVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericArraySTORE) {
BytecodeInstructionGenericArraySTORE theINS = (BytecodeInstructionGenericArraySTORE) theInstruction;
Value theValue = aHelper.pop();
Value theIndex = aHelper.pop();
Value theTarget = aHelper.pop();
aTargetBlock.getExpressions().add(new ArrayStoreExpression(TypeRef.toType(theINS.getType()), theTarget, theIndex, theValue));
} else if (theInstruction instanceof BytecodeInstructionObjectArraySTORE) {
BytecodeInstructionObjectArraySTORE theINS = (BytecodeInstructionObjectArraySTORE) theInstruction;
Value theValue = aHelper.pop();
Value theIndex = aHelper.pop();
Value theTarget = aHelper.pop();
aTargetBlock.getExpressions().add(new ArrayStoreExpression(TypeRef.Native.REFERENCE, theTarget, theIndex, theValue));
} else if (theInstruction instanceof BytecodeInstructionACONSTNULL) {
BytecodeInstructionACONSTNULL theINS = (BytecodeInstructionACONSTNULL) theInstruction;
aHelper.push(new NullValue());
} else if (theInstruction instanceof BytecodeInstructionPUTFIELD) {
BytecodeInstructionPUTFIELD theINS = (BytecodeInstructionPUTFIELD) theInstruction;
Value theValue = aHelper.pop();
Value theTarget = aHelper.pop();
aTargetBlock.getExpressions().add(new PutFieldExpression(theINS.getFieldRefConstant(), theTarget, theValue));
} else if (theInstruction instanceof BytecodeInstructionGETFIELD) {
BytecodeInstructionGETFIELD theINS = (BytecodeInstructionGETFIELD) theInstruction;
Value theTarget = aHelper.pop();
Variable theVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getFieldRefConstant().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().fieldType()), new GetFieldExpression(theINS.getFieldRefConstant(), theTarget));
aHelper.push(theVariable);
} else if (theInstruction instanceof BytecodeInstructionPUTSTATIC) {
BytecodeInstructionPUTSTATIC theINS = (BytecodeInstructionPUTSTATIC) theInstruction;
Value theValue = aHelper.pop();
aTargetBlock.getExpressions().add(new PutStaticExpression(theINS.getConstant(), theValue));
} else if (theInstruction instanceof BytecodeInstructionGenericLDC) {
BytecodeInstructionGenericLDC theINS = (BytecodeInstructionGenericLDC) theInstruction;
BytecodeConstant theConstant = theINS.constant();
if (theConstant instanceof BytecodeDoubleConstant) {
BytecodeDoubleConstant theC = (BytecodeDoubleConstant) theConstant;
aHelper.push(new DoubleValue(theC.getDoubleValue()));
} else if (theConstant instanceof BytecodeLongConstant) {
BytecodeLongConstant theC = (BytecodeLongConstant) theConstant;
aHelper.push(new LongValue(theC.getLongValue()));
} else if (theConstant instanceof BytecodeFloatConstant) {
BytecodeFloatConstant theC = (BytecodeFloatConstant) theConstant;
aHelper.push(new FloatValue(theC.getFloatValue()));
} else if (theConstant instanceof BytecodeIntegerConstant) {
BytecodeIntegerConstant theC = (BytecodeIntegerConstant) theConstant;
aHelper.push(new IntegerValue(theC.getIntegerValue()));
} else if (theConstant instanceof BytecodeStringConstant) {
BytecodeStringConstant theC = (BytecodeStringConstant) theConstant;
Variable theVariable = aTargetBlock.newVariable(TypeRef.toType(BytecodeObjectTypeRef.fromRuntimeClass(String.class)), new StringValue(theC.getValue().stringValue()));
aHelper.push(theVariable);
} else if (theConstant instanceof BytecodeClassinfoConstant) {
BytecodeClassinfoConstant theC = (BytecodeClassinfoConstant) theConstant;
BytecodeUtf8Constant theUTF8 = theC.getConstant();
if (theUTF8.stringValue().startsWith("[")) {
aHelper.push(new ClassReferenceValue(BytecodeObjectTypeRef.fromRuntimeClass(Array.class)));
} else {
aHelper.push(new ClassReferenceValue(BytecodeObjectTypeRef.fromUtf8Constant(theC.getConstant())));
}
} else {
throw new IllegalArgumentException("Unsupported constant type : " + theConstant);
}
} else if (theInstruction instanceof BytecodeInstructionBIPUSH) {
BytecodeInstructionBIPUSH theINS = (BytecodeInstructionBIPUSH) theInstruction;
aHelper.push(new IntegerValue(theINS.getByteValue()));
} else if (theInstruction instanceof BytecodeInstructionSIPUSH) {
BytecodeInstructionSIPUSH theINS = (BytecodeInstructionSIPUSH) theInstruction;
aHelper.push(new IntegerValue(theINS.getShortValue()));
} else if (theInstruction instanceof BytecodeInstructionICONST) {
BytecodeInstructionICONST theINS = (BytecodeInstructionICONST) theInstruction;
aHelper.push(new IntegerValue(theINS.getIntConst()));
} else if (theInstruction instanceof BytecodeInstructionFCONST) {
BytecodeInstructionFCONST theINS = (BytecodeInstructionFCONST) theInstruction;
aHelper.push(new FloatValue(theINS.getFloatValue()));
} else if (theInstruction instanceof BytecodeInstructionDCONST) {
BytecodeInstructionDCONST theINS = (BytecodeInstructionDCONST) theInstruction;
aHelper.push(new DoubleValue(theINS.getDoubleConst()));
} else if (theInstruction instanceof BytecodeInstructionLCONST) {
BytecodeInstructionLCONST theINS = (BytecodeInstructionLCONST) theInstruction;
aHelper.push(new LongValue(theINS.getLongConst()));
} else if (theInstruction instanceof BytecodeInstructionGenericNEG) {
BytecodeInstructionGenericNEG theINS = (BytecodeInstructionGenericNEG) theInstruction;
Value theValue = aHelper.pop();
Variable theNegatedValue = aTargetBlock.newVariable(theValue.resolveType(), new NegatedExpression(theValue));
aHelper.push(theNegatedValue);
} else if (theInstruction instanceof BytecodeInstructionARRAYLENGTH) {
BytecodeInstructionARRAYLENGTH theINS = (BytecodeInstructionARRAYLENGTH) theInstruction;
Value theValue = aHelper.pop();
Variable theNegatedValue = aTargetBlock.newVariable(TypeRef.Native.INT, new ArrayLengthExpression(theValue));
aHelper.push(theNegatedValue);
} else if (theInstruction instanceof BytecodeInstructionGenericLOAD) {
BytecodeInstructionGenericLOAD theINS = (BytecodeInstructionGenericLOAD) theInstruction;
Value theValue = aHelper.getLocalVariable(theINS.getVariableIndex());
aHelper.push(theValue);
} else if (theInstruction instanceof BytecodeInstructionALOAD) {
BytecodeInstructionALOAD theINS = (BytecodeInstructionALOAD) theInstruction;
Value theValue = aHelper.getLocalVariable(theINS.getVariableIndex());
aHelper.push(theValue);
} else if (theInstruction instanceof BytecodeInstructionGenericCMP) {
BytecodeInstructionGenericCMP theINS = (BytecodeInstructionGenericCMP) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, new CompareExpression(theValue1, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionLCMP) {
BytecodeInstructionLCMP theINS = (BytecodeInstructionLCMP) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, new CompareExpression(theValue1, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionIINC) {
BytecodeInstructionIINC theINS = (BytecodeInstructionIINC) theInstruction;
Value theValueToIncrement = aHelper.getLocalVariable(theINS.getIndex());
Value theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, new BinaryExpression(TypeRef.Native.INT, theValueToIncrement, BinaryExpression.Operator.ADD, new IntegerValue(theINS.getConstant())));
aHelper.setLocalVariable(theInstruction.getOpcodeAddress(), theINS.getIndex(), theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericREM) {
BytecodeInstructionGenericREM theINS = (BytecodeInstructionGenericREM) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.REMAINDER, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericADD) {
BytecodeInstructionGenericADD theINS = (BytecodeInstructionGenericADD) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.ADD, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericDIV) {
BytecodeInstructionGenericDIV theINS = (BytecodeInstructionGenericDIV) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable;
Value theDivValue = new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.DIV, theValue2);
switch(theINS.getType()) {
case FLOAT:
theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), theDivValue);
break;
case DOUBLE:
theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), theDivValue);
break;
default:
theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new FloorExpression(theDivValue, TypeRef.toType(theINS.getType())));
break;
}
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericMUL) {
BytecodeInstructionGenericMUL theINS = (BytecodeInstructionGenericMUL) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.MUL, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericSUB) {
BytecodeInstructionGenericSUB theINS = (BytecodeInstructionGenericSUB) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.SUB, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericXOR) {
BytecodeInstructionGenericXOR theINS = (BytecodeInstructionGenericXOR) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYXOR, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericOR) {
BytecodeInstructionGenericOR theINS = (BytecodeInstructionGenericOR) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYOR, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericAND) {
BytecodeInstructionGenericAND theINS = (BytecodeInstructionGenericAND) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYAND, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericSHL) {
BytecodeInstructionGenericSHL theINS = (BytecodeInstructionGenericSHL) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYSHIFTLEFT, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericSHR) {
BytecodeInstructionGenericSHR theINS = (BytecodeInstructionGenericSHR) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYSHIFTRIGHT, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGenericUSHR) {
BytecodeInstructionGenericUSHR theINS = (BytecodeInstructionGenericUSHR) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getType()), new BinaryExpression(TypeRef.toType(theINS.getType()), theValue1, BinaryExpression.Operator.BINARYUNSIGNEDSHIFTRIGHT, theValue2));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionIFNULL) {
BytecodeInstructionIFNULL theINS = (BytecodeInstructionIFNULL) theInstruction;
Value theValue = aHelper.pop();
FixedBinaryExpression theBinaryValue = new FixedBinaryExpression(theValue, FixedBinaryExpression.Operator.ISNULL);
ExpressionList theExpressions = new ExpressionList();
theExpressions.add(new GotoExpression(theINS.getJumpTarget()));
aTargetBlock.getExpressions().add(new IFExpression(theINS.getOpcodeAddress(), theINS.getJumpTarget(), theBinaryValue, theExpressions));
} else if (theInstruction instanceof BytecodeInstructionIFNONNULL) {
BytecodeInstructionIFNONNULL theINS = (BytecodeInstructionIFNONNULL) theInstruction;
Value theValue = aHelper.pop();
FixedBinaryExpression theBinaryValue = new FixedBinaryExpression(theValue, FixedBinaryExpression.Operator.ISNONNULL);
ExpressionList theExpressions = new ExpressionList();
theExpressions.add(new GotoExpression(theINS.getJumpTarget()));
aTargetBlock.getExpressions().add(new IFExpression(theINS.getOpcodeAddress(), theINS.getJumpTarget(), theBinaryValue, theExpressions));
} else if (theInstruction instanceof BytecodeInstructionIFICMP) {
BytecodeInstructionIFICMP theINS = (BytecodeInstructionIFICMP) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
BinaryExpression theBinaryValue;
switch(theINS.getType()) {
case lt:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.LESSTHAN, theValue2);
break;
case eq:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.EQUALS, theValue2);
break;
case gt:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.GREATERTHAN, theValue2);
break;
case ge:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.GREATEROREQUALS, theValue2);
break;
case le:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.LESSTHANOREQUALS, theValue2);
break;
case ne:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.NOTEQUALS, theValue2);
break;
default:
throw new IllegalStateException("Not supported operation : " + theINS.getType());
}
ExpressionList theExpressions = new ExpressionList();
theExpressions.add(new GotoExpression(theINS.getJumpTarget()));
aTargetBlock.getExpressions().add(new IFExpression(theINS.getOpcodeAddress(), theINS.getJumpTarget(), theBinaryValue, theExpressions));
} else if (theInstruction instanceof BytecodeInstructionIFACMP) {
BytecodeInstructionIFACMP theINS = (BytecodeInstructionIFACMP) theInstruction;
Value theValue2 = aHelper.pop();
Value theValue1 = aHelper.pop();
BinaryExpression theBinaryValue;
switch(theINS.getType()) {
case eq:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.EQUALS, theValue2);
break;
case ne:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue1, BinaryExpression.Operator.NOTEQUALS, theValue2);
break;
default:
throw new IllegalStateException("Not supported operation : " + theINS.getType());
}
ExpressionList theExpressions = new ExpressionList();
theExpressions.add(new GotoExpression(theINS.getJumpTarget()));
aTargetBlock.getExpressions().add(new IFExpression(theINS.getOpcodeAddress(), theINS.getJumpTarget(), theBinaryValue, theExpressions));
} else if (theInstruction instanceof BytecodeInstructionIFCOND) {
BytecodeInstructionIFCOND theINS = (BytecodeInstructionIFCOND) theInstruction;
Value theValue = aHelper.pop();
BinaryExpression theBinaryValue;
switch(theINS.getType()) {
case lt:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.LESSTHAN, new IntegerValue(0));
break;
case eq:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.EQUALS, new IntegerValue(0));
break;
case gt:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.GREATERTHAN, new IntegerValue(0));
break;
case ge:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.GREATEROREQUALS, new IntegerValue(0));
break;
case le:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.LESSTHANOREQUALS, new IntegerValue(0));
break;
case ne:
theBinaryValue = new BinaryExpression(TypeRef.Native.BOOLEAN, theValue, BinaryExpression.Operator.NOTEQUALS, new IntegerValue(0));
break;
default:
throw new IllegalStateException("Not supported operation : " + theINS.getType());
}
ExpressionList theExpressions = new ExpressionList();
theExpressions.add(new GotoExpression(theINS.getJumpTarget()));
aTargetBlock.getExpressions().add(new IFExpression(theINS.getOpcodeAddress(), theINS.getJumpTarget(), theBinaryValue, theExpressions));
} else if (theInstruction instanceof BytecodeInstructionObjectRETURN) {
BytecodeInstructionObjectRETURN theINS = (BytecodeInstructionObjectRETURN) theInstruction;
Value theValue = aHelper.pop();
aTargetBlock.getExpressions().add(new ReturnValueExpression(theValue));
} else if (theInstruction instanceof BytecodeInstructionGenericRETURN) {
BytecodeInstructionGenericRETURN theINS = (BytecodeInstructionGenericRETURN) theInstruction;
Value theValue = aHelper.pop();
aTargetBlock.getExpressions().add(new ReturnValueExpression(theValue));
} else if (theInstruction instanceof BytecodeInstructionATHROW) {
BytecodeInstructionATHROW theINS = (BytecodeInstructionATHROW) theInstruction;
Value theValue = aHelper.pop();
aTargetBlock.getExpressions().add(new ThrowExpression(theValue));
} else if (theInstruction instanceof BytecodeInstructionRETURN) {
BytecodeInstructionRETURN theINS = (BytecodeInstructionRETURN) theInstruction;
aTargetBlock.getExpressions().add(new ReturnExpression());
} else if (theInstruction instanceof BytecodeInstructionNEW) {
BytecodeInstructionNEW theINS = (BytecodeInstructionNEW) theInstruction;
BytecodeClassinfoConstant theClassInfo = theINS.getClassInfoForObjectToCreate();
BytecodeObjectTypeRef theObjectType = BytecodeObjectTypeRef.fromUtf8Constant(theClassInfo.getConstant());
if (Objects.equals(theObjectType.name(), Address.class.getName())) {
// At this time the exact location is unknown, the value
// will be set at constructor invocation time
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT);
aHelper.push(theNewVariable);
} else {
if (Objects.equals(theObjectType, BytecodeObjectTypeRef.fromRuntimeClass(VM.RuntimeGeneratedType.class))) {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new RuntimeGeneratedTypeExpression());
aHelper.push(theNewVariable);
} else {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theObjectType), new NewObjectExpression(theClassInfo));
aHelper.push(theNewVariable);
}
}
} else if (theInstruction instanceof BytecodeInstructionNEWARRAY) {
BytecodeInstructionNEWARRAY theINS = (BytecodeInstructionNEWARRAY) theInstruction;
Value theLength = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new NewArrayExpression(theINS.getPrimitiveType(), theLength));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionNEWMULTIARRAY) {
BytecodeInstructionNEWMULTIARRAY theINS = (BytecodeInstructionNEWMULTIARRAY) theInstruction;
List<Value> theDimensions = new ArrayList<>();
for (int i = 0; i < theINS.getDimensions(); i++) {
theDimensions.add(aHelper.pop());
}
Collections.reverse(theDimensions);
BytecodeTypeRef theTypeRef = linkerContext.getSignatureParser().toFieldType(new BytecodeUtf8Constant(theINS.getTypeConstant().getConstant().stringValue()));
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new NewMultiArrayExpression(theTypeRef, theDimensions));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionANEWARRAY) {
BytecodeInstructionANEWARRAY theINS = (BytecodeInstructionANEWARRAY) theInstruction;
Value theLength = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new NewArrayExpression(theINS.getObjectType(), theLength));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionGOTO) {
BytecodeInstructionGOTO theINS = (BytecodeInstructionGOTO) theInstruction;
aTargetBlock.getExpressions().add(new GotoExpression(theINS.getJumpAddress()));
} else if (theInstruction instanceof BytecodeInstructionL2Generic) {
BytecodeInstructionL2Generic theINS = (BytecodeInstructionL2Generic) theInstruction;
Value theValue = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getTargetType()), new TypeConversionExpression(theValue, TypeRef.toType(theINS.getTargetType())));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionI2Generic) {
BytecodeInstructionI2Generic theINS = (BytecodeInstructionI2Generic) theInstruction;
Value theValue = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getTargetType()), new TypeConversionExpression(theValue, TypeRef.toType(theINS.getTargetType())));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionF2Generic) {
BytecodeInstructionF2Generic theINS = (BytecodeInstructionF2Generic) theInstruction;
Value theValue = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getTargetType()), new TypeConversionExpression(theValue, TypeRef.toType(theINS.getTargetType())));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionD2Generic) {
BytecodeInstructionD2Generic theINS = (BytecodeInstructionD2Generic) theInstruction;
Value theValue = aHelper.pop();
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theINS.getTargetType()), new TypeConversionExpression(theValue, TypeRef.toType(theINS.getTargetType())));
aHelper.push(theNewVariable);
} else if (theInstruction instanceof BytecodeInstructionINVOKESPECIAL) {
BytecodeInstructionINVOKESPECIAL theINS = (BytecodeInstructionINVOKESPECIAL) theInstruction;
BytecodeMethodSignature theSignature = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
List<Value> theArguments = new ArrayList<>();
BytecodeTypeRef[] theArgumentTypes = theSignature.getArguments();
for (BytecodeTypeRef theArgumentType : theArgumentTypes) {
theArguments.add(aHelper.pop());
}
Collections.reverse(theArguments);
Variable theTarget = (Variable) aHelper.pop();
BytecodeObjectTypeRef theType = BytecodeObjectTypeRef.fromUtf8Constant(theINS.getMethodReference().getClassIndex().getClassConstant().getConstant());
if (Objects.equals(theType, BytecodeObjectTypeRef.fromRuntimeClass(VM.RuntimeGeneratedType.class))) {
RuntimeGeneratedTypeExpression theValue = (RuntimeGeneratedTypeExpression) theTarget.incomingDataFlows().get(0);
theValue.setType(theArguments.get(0));
theValue.setMethodRef(theArguments.get(1));
} else if (Objects.equals(theType, BytecodeObjectTypeRef.fromRuntimeClass(Address.class))) {
theTarget.initializeWith(theArguments.get(0));
aTargetBlock.getExpressions().add(new VariableAssignmentExpression(theTarget, theArguments.get(0)));
} else {
String theMethodName = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue();
if ("getClass".equals(theMethodName) && BytecodeLinkedClass.GET_CLASS_SIGNATURE.metchesExactlyTo(theSignature)) {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), new TypeOfExpression(theTarget));
aHelper.push(theNewVariable);
} else {
DirectInvokeMethodExpression theExpression = new DirectInvokeMethodExpression(theType, theMethodName, theSignature, theTarget, theArguments);
if (theSignature.getReturnType().isVoid()) {
aTargetBlock.getExpressions().add(theExpression);
} else {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theExpression);
aHelper.push(theNewVariable);
}
}
}
} else if (theInstruction instanceof BytecodeInstructionINVOKEVIRTUAL) {
BytecodeInstructionINVOKEVIRTUAL theINS = (BytecodeInstructionINVOKEVIRTUAL) theInstruction;
BytecodeMethodSignature theSignature = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
if (theSignature.metchesExactlyTo(BytecodeLinkedClass.GET_CLASS_SIGNATURE) && "getClass".equals(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue())) {
Value theValue = new TypeOfExpression(aHelper.pop());
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theValue);
aHelper.push(theNewVariable);
continue;
}
List<Value> theArguments = new ArrayList<>();
BytecodeTypeRef[] theArgumentTypes = theSignature.getArguments();
for (BytecodeTypeRef theArgumentType : theArgumentTypes) {
theArguments.add(aHelper.pop());
}
Collections.reverse(theArguments);
Value theTarget = aHelper.pop();
InvokeVirtualMethodExpression theExpression = new InvokeVirtualMethodExpression(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType(), theTarget, theArguments);
if (theSignature.getReturnType().isVoid()) {
aTargetBlock.getExpressions().add(theExpression);
} else {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theExpression);
aHelper.push(theNewVariable);
}
} else if (theInstruction instanceof BytecodeInstructionINVOKEINTERFACE) {
BytecodeInstructionINVOKEINTERFACE theINS = (BytecodeInstructionINVOKEINTERFACE) theInstruction;
BytecodeMethodSignature theSignature = theINS.getMethodDescriptor().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
List<Value> theArguments = new ArrayList<>();
BytecodeTypeRef[] theArgumentTypes = theSignature.getArguments();
for (BytecodeTypeRef theArgumentType : theArgumentTypes) {
theArguments.add(aHelper.pop());
}
Collections.reverse(theArguments);
Value theTarget = aHelper.pop();
InvokeVirtualMethodExpression theExpression = new InvokeVirtualMethodExpression(theINS.getMethodDescriptor().getNameAndTypeIndex().getNameAndType(), theTarget, theArguments);
if (theSignature.getReturnType().isVoid()) {
aTargetBlock.getExpressions().add(theExpression);
} else {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theExpression);
aHelper.push(theNewVariable);
}
} else if (theInstruction instanceof BytecodeInstructionINVOKESTATIC) {
BytecodeInstructionINVOKESTATIC theINS = (BytecodeInstructionINVOKESTATIC) theInstruction;
BytecodeMethodSignature theSignature = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
List<Value> theArguments = new ArrayList<>();
BytecodeTypeRef[] theArgumentTypes = theSignature.getArguments();
for (BytecodeTypeRef theArgumentType : theArgumentTypes) {
theArguments.add(aHelper.pop());
}
Collections.reverse(theArguments);
BytecodeClassinfoConstant theTargetClass = theINS.getMethodReference().getClassIndex().getClassConstant();
BytecodeObjectTypeRef theObjectType = BytecodeObjectTypeRef.fromUtf8Constant(theTargetClass.getConstant());
if (Objects.equals(theObjectType.name(), MemoryManager.class.getName()) && "initTestMemory".equals(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue())) {
// This invocation can be skipped!!!
} else if (Objects.equals(theObjectType.name(), Address.class.getName())) {
String theMethodName = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue();
switch(theMethodName) {
case "setIntValue":
{
Value theTarget = theArguments.get(0);
Value theOffset = theArguments.get(1);
Value theNewValue = theArguments.get(2);
ComputedMemoryLocationWriteExpression theLocation = new ComputedMemoryLocationWriteExpression(theTarget, theOffset);
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, theLocation);
aTargetBlock.getExpressions().add(new SetMemoryLocationExpression(theNewVariable, theNewValue));
break;
}
case "getStart":
{
Value theTarget = theArguments.get(0);
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, theTarget);
aHelper.push(theNewVariable);
break;
}
case "getStackTop":
{
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, new StackTopExpression());
aHelper.push(theNewVariable);
break;
}
case "getMemorySize":
{
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, new MemorySizeExpression());
aHelper.push(theNewVariable);
break;
}
case "getIntValue":
{
Value theTarget = theArguments.get(0);
Value theOffset = theArguments.get(1);
ComputedMemoryLocationReadExpression theLocation = new ComputedMemoryLocationReadExpression(theTarget, theOffset);
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.Native.INT, theLocation);
aHelper.push(theNewVariable);
break;
}
case "unreachable":
{
aTargetBlock.getExpressions().add(new UnreachableExpression());
break;
}
default:
throw new IllegalStateException("Not implemented : " + theMethodName);
}
} else {
BytecodeObjectTypeRef theClassToInvoke = BytecodeObjectTypeRef.fromUtf8Constant(theINS.getMethodReference().getClassIndex().getClassConstant().getConstant());
linkerContext.resolveClass(theClassToInvoke).resolveStaticMethod(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue(), theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature());
BytecodeMethodSignature theCalledSignature = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
if ("sqrt".equals(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue()) && "java.lang.StrictMath".equals(theClassToInvoke.name())) {
Value theValue = new SqrtExpression(TypeRef.toType(theCalledSignature.getReturnType()), theArguments.get(0));
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theValue);
aHelper.push(theNewVariable);
} else if ("newInstance".equals(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue()) && "java.lang.reflect.Array".equals(theClassToInvoke.name())) {
Value theArrayType = theArguments.get(0);
Value theArraySize = theArguments.get(1);
Value theValue = new NewArrayExpression(BytecodeObjectTypeRef.fromRuntimeClass(Object.class), theArraySize);
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theValue);
aHelper.push(theNewVariable);
} else {
InvokeStaticMethodExpression theExpression = new InvokeStaticMethodExpression(theClassToInvoke, theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue(), theCalledSignature, theArguments);
if (theSignature.getReturnType().isVoid()) {
aTargetBlock.getExpressions().add(theExpression);
} else {
Variable theNewVariable = aTargetBlock.newVariable(TypeRef.toType(theSignature.getReturnType()), theExpression);
aHelper.push(theNewVariable);
}
}
}
} else if (theInstruction instanceof BytecodeInstructionINSTANCEOF) {
BytecodeInstructionINSTANCEOF theINS = (BytecodeInstructionINSTANCEOF) theInstruction;
Value theValueToCheck = aHelper.pop();
InstanceOfExpression theValue = new InstanceOfExpression(theValueToCheck, theINS.getTypeRef());
Variable theCheckResult = aTargetBlock.newVariable(TypeRef.Native.BOOLEAN, theValue);
aHelper.push(theCheckResult);
} else if (theInstruction instanceof BytecodeInstructionTABLESWITCH) {
BytecodeInstructionTABLESWITCH theINS = (BytecodeInstructionTABLESWITCH) theInstruction;
Value theValue = aHelper.pop();
ExpressionList theDefault = new ExpressionList();
theDefault.add(new GotoExpression(theINS.getDefaultJumpTarget()));
Map<Long, ExpressionList> theOffsets = new HashMap<>();
long[] theJumpTargets = theINS.getOffsets();
for (int i = 0; i < theJumpTargets.length; i++) {
ExpressionList theJump = new ExpressionList();
theJump.add(new GotoExpression(theINS.getOpcodeAddress().add((int) theJumpTargets[i])));
theOffsets.put((long) i, theJump);
}
aTargetBlock.getExpressions().add(new TableSwitchExpression(theValue, theINS.getLowValue(), theINS.getHighValue(), theDefault, theOffsets));
} else if (theInstruction instanceof BytecodeInstructionLOOKUPSWITCH) {
BytecodeInstructionLOOKUPSWITCH theINS = (BytecodeInstructionLOOKUPSWITCH) theInstruction;
Value theValue = aHelper.pop();
ExpressionList theDefault = new ExpressionList();
theDefault.add(new GotoExpression(theINS.getDefaultJumpTarget()));
Map<Long, ExpressionList> thePairs = new HashMap<>();
for (BytecodeInstructionLOOKUPSWITCH.Pair thePair : theINS.getPairs()) {
ExpressionList thePairExpressions = new ExpressionList();
thePairExpressions.add(new GotoExpression(theINS.getOpcodeAddress().add((int) thePair.getOffset())));
thePairs.put(thePair.getMatch(), thePairExpressions);
}
aTargetBlock.getExpressions().add(new LookupSwitchExpression(theValue, theDefault, thePairs));
} else if (theInstruction instanceof BytecodeInstructionINVOKEDYNAMIC) {
BytecodeInstructionINVOKEDYNAMIC theINS = (BytecodeInstructionINVOKEDYNAMIC) theInstruction;
BytecodeInvokeDynamicConstant theConstant = theINS.getCallSite();
BytecodeMethodSignature theInitSignature = theConstant.getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
BytecodeBootstrapMethodsAttributeInfo theBootStrapMethods = aOwningClass.getAttributes().getByType(BytecodeBootstrapMethodsAttributeInfo.class);
BytecodeBootstrapMethod theBootstrapMethod = theBootStrapMethods.methodByIndex(theConstant.getBootstrapMethodAttributeIndex().getIndex());
BytecodeMethodHandleConstant theMethodRef = theBootstrapMethod.getMethodRef();
BytecodeMethodRefConstant theBootstrapMethodToInvoke = (BytecodeMethodRefConstant) theMethodRef.getReferenceIndex().getConstant();
Program theProgram = new Program();
RegionNode theInitNode = theProgram.getControlFlowGraph().createAt(BytecodeOpcodeAddress.START_AT_ZERO, RegionNode.BlockType.NORMAL);
switch(theMethodRef.getReferenceKind()) {
case REF_invokeStatic:
{
BytecodeObjectTypeRef theClassWithBootstrapMethod = BytecodeObjectTypeRef.fromUtf8Constant(theBootstrapMethodToInvoke.getClassIndex().getClassConstant().getConstant());
BytecodeMethodSignature theSignature = theBootstrapMethodToInvoke.getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature();
List<Value> theArguments = new ArrayList<>();
// Add the three default constants
// TMethodHandles.Lookup aCaller,
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new MethodHandlesGeneratedLookupExpression(theClassWithBootstrapMethod)));
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new StringValue(theConstant.getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue())));
// TMethodType aInvokedType,
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new MethodTypeExpression(theInitSignature)));
// Revolve the static arguments
for (BytecodeConstant theArgumentConstant : theBootstrapMethod.getArguments()) {
if (theArgumentConstant instanceof BytecodeMethodTypeConstant) {
BytecodeMethodTypeConstant theMethodType = (BytecodeMethodTypeConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new MethodTypeExpression(theMethodType.getDescriptorIndex().methodSignature())));
continue;
}
if (theArgumentConstant instanceof BytecodeStringConstant) {
BytecodeStringConstant thePrimitive = (BytecodeStringConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new StringValue(thePrimitive.getValue().stringValue())));
continue;
}
if (theArgumentConstant instanceof BytecodeLongConstant) {
BytecodeLongConstant thePrimitive = (BytecodeLongConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.LONG, new LongValue(thePrimitive.getLongValue())));
continue;
}
if (theArgumentConstant instanceof BytecodeIntegerConstant) {
BytecodeIntegerConstant thePrimitive = (BytecodeIntegerConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.INT, new LongValue(thePrimitive.getIntegerValue())));
continue;
}
if (theArgumentConstant instanceof BytecodeFloatConstant) {
BytecodeFloatConstant thePrimitive = (BytecodeFloatConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.FLOAT, new FloatValue(thePrimitive.getFloatValue())));
continue;
}
if (theArgumentConstant instanceof BytecodeDoubleConstant) {
BytecodeDoubleConstant thePrimitive = (BytecodeDoubleConstant) theArgumentConstant;
theArguments.add(theInitNode.newVariable(TypeRef.Native.DOUBLE, new DoubleValue(thePrimitive.getDoubleValue())));
continue;
}
if (theArgumentConstant instanceof BytecodeMethodHandleConstant) {
BytecodeMethodHandleConstant theMethodHandle = (BytecodeMethodHandleConstant) theArgumentConstant;
BytecodeReferenceIndex theReference = theMethodHandle.getReferenceIndex();
BytecodeMethodRefConstant theReferenceConstant = (BytecodeMethodRefConstant) theReference.getConstant();
theArguments.add(theInitNode.newVariable(TypeRef.Native.REFERENCE, new MethodRefExpression(theReferenceConstant)));
continue;
}
throw new IllegalStateException("Unsupported argument type : " + theArgumentConstant);
}
// Ok, is the last argument of the bootstrap method a vararg argument
BytecodeTypeRef theLastArgument = theSignature.getArguments()[theSignature.getArguments().length - 1];
if (theLastArgument.isArray()) {
// Yes, so we have to wrap everything from this position on in an array
int theSignatureLength = theSignature.getArguments().length;
int theArgumentsLength = theArguments.size();
int theVarArgsLength = theArgumentsLength - theSignatureLength + 1;
Variable theNewVarargsArray = theInitNode.newVariable(TypeRef.Native.REFERENCE, new NewArrayExpression(BytecodeObjectTypeRef.fromRuntimeClass(Object.class), new IntegerValue(theVarArgsLength)));
for (int i = theSignatureLength - 1; i < theArgumentsLength; i++) {
Value theVariable = theArguments.get(i);
theArguments.remove(theVariable);
theInitNode.getExpressions().add(new ArrayStoreExpression(TypeRef.Native.REFERENCE, theNewVarargsArray, new IntegerValue(i - theSignatureLength + 1), theVariable));
}
theArguments.add(theNewVarargsArray);
}
InvokeStaticMethodExpression theInvokeStaticValue = new InvokeStaticMethodExpression(BytecodeObjectTypeRef.fromUtf8Constant(theBootstrapMethodToInvoke.getClassIndex().getClassConstant().getConstant()), theBootstrapMethodToInvoke.getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue(), theBootstrapMethodToInvoke.getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature(), theArguments);
Variable theNewVariable = theInitNode.newVariable(TypeRef.Native.REFERENCE, theInvokeStaticValue);
theInitNode.getExpressions().add(new ReturnValueExpression(theNewVariable));
// First step, we construct a callsite
ResolveCallsiteObjectExpression theValue = new ResolveCallsiteObjectExpression(aOwningClass.getThisInfo().getConstant().stringValue() + "_" + aMethod.getName().stringValue() + "_" + theINS.getOpcodeAddress().getAddress(), aOwningClass, theProgram, theInitNode);
Variable theCallsiteVariable = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, theValue);
List<Value> theInvokeArguments = new ArrayList<>();
Variable theArray = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, new NewArrayExpression(BytecodeObjectTypeRef.fromRuntimeClass(Object.class), new IntegerValue(theInitSignature.getArguments().length)));
for (int i = theInitSignature.getArguments().length - 1; i >= 0; i--) {
Value theIndex = new IntegerValue(i);
Value theStoredValue = aHelper.pop();
if (theStoredValue.resolveType() == TypeRef.Native.INT) {
// Create Integer object to contain int
BytecodeObjectTypeRef theType = BytecodeObjectTypeRef.fromRuntimeClass(Integer.class);
BytecodeTypeRef[] args_def = new BytecodeTypeRef[] { BytecodePrimitiveTypeRef.INT };
BytecodeMethodSignature sig = new BytecodeMethodSignature(theType, args_def);
List<Value> args = new ArrayList<>();
args.add(theStoredValue);
theStoredValue = new InvokeStaticMethodExpression(theType, "valueOf", sig, args);
theStoredValue = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, theStoredValue);
}
aTargetBlock.getExpressions().add(new ArrayStoreExpression(TypeRef.Native.REFERENCE, theArray, theIndex, theStoredValue));
}
theInvokeArguments.add(theArray);
InvokeVirtualMethodExpression theInvokeValue = new InvokeVirtualMethodExpression("invokeExact", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Object.class), new BytecodeTypeRef[] { new BytecodeArrayTypeRef(BytecodeObjectTypeRef.fromRuntimeClass(Object.class), 1) }), theCallsiteVariable, theInvokeArguments);
Variable theInvokeExactResult = aTargetBlock.newVariable(TypeRef.Native.REFERENCE, theInvokeValue);
aHelper.push(theInvokeExactResult);
break;
}
default:
throw new IllegalStateException("Nut supported reference kind for invoke dynamic : " + theMethodRef.getReferenceKind());
}
} else {
throw new IllegalArgumentException("Not implemented : " + theInstruction);
}
}
aHelper.finalizeExportState();
}
use of de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef in project Bytecoder by mirkosertic.
the class JSSSACompilerBackend method generateCodeFor.
@Override
public JSCompileResult generateCodeFor(CompileOptions aOptions, BytecodeLinkerContext aLinkerContext, Class aEntryPointClass, String aEntryPointMethodName, BytecodeMethodSignature aEntryPointSignatue) {
BytecodeLinkedClass theExceptionRethrower = aLinkerContext.resolveClass(BytecodeObjectTypeRef.fromRuntimeClass(ExceptionRethrower.class));
theExceptionRethrower.resolveStaticMethod("registerExceptionOutcome", registerExceptionOutcomeSignature);
theExceptionRethrower.resolveStaticMethod("getLastOutcomeOrNullAndReset", getLastExceptionOutcomeSignature);
StringWriter theStrWriter = new StringWriter();
PrintWriter theWriter = new PrintWriter(theStrWriter);
theWriter.println("'use strict';");
theWriter.println();
theWriter.println("var bytecoderGlobalMemory = [];");
theWriter.println();
theWriter.println("var bytecoder = {");
theWriter.println();
theWriter.println(" logDebug : function(aValue) { ");
theWriter.println(" console.log(aValue);");
theWriter.println(" }, ");
theWriter.println();
theWriter.println(" logByteArrayAsString : function(aArray) { ");
theWriter.println(" var theResult = '';");
theWriter.println(" for (var i=0;i<aArray.data.length;i++) {");
theWriter.println(" theResult += String.fromCharCode(aArray.data[i]);");
theWriter.println(" }");
theWriter.println(" console.log(theResult);");
theWriter.println(" }, ");
theWriter.println();
theWriter.println(" newString : function(aByteArray) { ");
BytecodeObjectTypeRef theStringTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(String.class);
BytecodeObjectTypeRef theArrayTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
BytecodeMethodSignature theStringConstructorSignature = new BytecodeMethodSignature(BytecodePrimitiveTypeRef.VOID, new BytecodeTypeRef[] { new BytecodeArrayTypeRef(BytecodePrimitiveTypeRef.BYTE, 1) });
// Construct a String
theWriter.println(" var theNewString = new " + JSWriterUtils.toClassName(theStringTypeRef) + ".Create();");
theWriter.println(" var theBytes = new " + JSWriterUtils.toClassName(theArrayTypeRef) + ".Create();");
theWriter.println(" theBytes.data = aByteArray;");
theWriter.println(" " + JSWriterUtils.toClassName(theStringTypeRef) + '.' + JSWriterUtils.toMethodName("init", theStringConstructorSignature) + "(theNewString, theBytes);");
theWriter.println(" return theNewString;");
theWriter.println(" },");
theWriter.println();
theWriter.println(" newMultiArray : function(aDimensions, aDefault) {");
theWriter.println(" var theLength = aDimensions[0];");
theWriter.println(" var theArray = bytecoder.newArray(theLength, aDefault);");
theWriter.println(" if (aDimensions.length > 1) {");
theWriter.println(" var theNewDimensions = aDimensions.slice(0);");
theWriter.println(" theNewDimensions.shift();");
theWriter.println(" for (var i=0;i<theLength;i++) {");
theWriter.println(" theArray.data[i] = bytecoder.newMultiArray(theNewDimensions, aDefault);");
theWriter.println(" }");
theWriter.println(" }");
theWriter.println(" return theArray;");
theWriter.println(" },");
theWriter.println();
theWriter.println(" newArray : function(aLength, aDefault) {");
BytecodeObjectTypeRef theArrayType = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
theWriter.println(" var theInstance = new " + JSWriterUtils.toClassName(theArrayType) + ".Create();");
theWriter.println(" theInstance.data = [];");
theWriter.println(" theInstance.data.length = aLength;");
theWriter.println(" for (var i=0;i<aLength;i++) {");
theWriter.println(" theInstance.data[i] = aDefault;");
theWriter.println(" }");
theWriter.println(" return theInstance;");
theWriter.println(" },");
theWriter.println();
theWriter.println(" dynamicType : function(aFunction) { ");
theWriter.println(" return new Proxy({}, {");
theWriter.println(" get: function(target, name) {");
theWriter.println(" return function(inst, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9) {");
theWriter.println(" return aFunction(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);");
theWriter.println(" }");
theWriter.println(" }");
theWriter.println(" });");
theWriter.println(" }, ");
theWriter.println();
theWriter.println(" resolveStaticCallSiteObject: function(aWhere, aKey, aProducerFunction) {");
theWriter.println(" var resolvedCallsiteObject = aWhere.__staticCallSites[aKey];");
theWriter.println(" if (resolvedCallsiteObject == null) {");
theWriter.println(" resolvedCallsiteObject = aProducerFunction();");
theWriter.println(" aWhere.__staticCallSites[aKey] = resolvedCallsiteObject;");
theWriter.println(" }");
theWriter.println(" return resolvedCallsiteObject;");
theWriter.println(" },");
theWriter.println();
theWriter.println(" imports : [],");
theWriter.println();
theWriter.println(" stringpool : [],");
theWriter.println();
theWriter.println("};");
theWriter.println();
ConstantPool thePool = new ConstantPool();
aLinkerContext.linkedClasses().forEach(theEntry -> {
BytecodeLinkedClass theLinkedClass = theEntry.targetNode();
// Here we collect everything that is required for class initialization
// this includes the super class, all implementing interfaces and also static
// dependencies of the class initialization code
List<BytecodeObjectTypeRef> theInitDependencies = new ArrayList<>();
BytecodeLinkedClass theSuperClass = theLinkedClass.getSuperClass();
if (theSuperClass != null) {
theInitDependencies.add(theSuperClass.getClassName());
}
for (BytecodeLinkedClass theInterface : theLinkedClass.getImplementingTypes()) {
if (!theInitDependencies.contains(theInterface.getClassName())) {
theInitDependencies.add(theInterface.getClassName());
}
}
BytecodeResolvedMethods theMethods = theLinkedClass.resolvedMethods();
String theJSClassName = JSWriterUtils.toClassName(theEntry.edgeType().objectTypeRef());
theWriter.println("var " + theJSClassName + " = {");
// First of all, we add static fields required by the framework
theWriter.println(" __initialized : false,");
theWriter.println(" __staticCallSites : [],");
theWriter.print(" __typeId : ");
theWriter.print(theLinkedClass.getUniqueId());
theWriter.println(",");
theWriter.print(" __implementedTypes : [");
{
boolean first = true;
for (BytecodeLinkedClass theType : theLinkedClass.getImplementingTypes()) {
if (!first) {
theWriter.print(",");
}
first = false;
theWriter.print(theType.getUniqueId());
}
}
theWriter.println("],");
// then we add class specific static fields
BytecodeResolvedFields theStaticFields = theLinkedClass.resolvedFields();
theStaticFields.streamForStaticFields().forEach(aFieldEntry -> {
BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
if (theFieldType.isPrimitive()) {
BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
switch(thePrimitive) {
case BOOLEAN:
{
theWriter.print(" ");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" : false, // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
break;
}
default:
{
theWriter.print(" ");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" : 0, // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
break;
}
}
} else {
theWriter.print(" ");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" : null, // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
}
});
theWriter.println();
if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
// The Constructor function initializes all object members with null
// Only non abstract classes can be instantiated
BytecodeResolvedFields theInstanceFields = theLinkedClass.resolvedFields();
theWriter.println(" Create : function() {");
theInstanceFields.streamForInstanceFields().forEach(aFieldEntry -> {
BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
if (theFieldType.isPrimitive()) {
BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
switch(thePrimitive) {
case BOOLEAN:
{
theWriter.print(" this.");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" = false; // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
break;
}
default:
{
theWriter.print(" this.");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" = 0; // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
break;
}
}
} else {
theWriter.print(" this.");
theWriter.print(aFieldEntry.getValue().getName().stringValue());
theWriter.print(" = null; // declared in ");
theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
}
});
theWriter.println(" },");
theWriter.println();
}
if (!theLinkedClass.getBytecodeClass().getAccessFlags().isInterface()) {
theWriter.println(" instanceOf : function(aType) {");
theWriter.print(" return ");
theWriter.print(theJSClassName);
theWriter.println(".__implementedTypes.includes(aType.__typeId);");
theWriter.println(" },");
theWriter.println();
theWriter.println(" ClassgetClass : function() {");
theWriter.print(" return ");
theWriter.print(theJSClassName);
theWriter.println(";");
theWriter.println(" },");
theWriter.println();
theWriter.println(" BOOLEANdesiredAssertionStatus : function() {");
theWriter.println(" return false;");
theWriter.println(" },");
theWriter.println();
theWriter.println(" A1jlObjectgetEnumConstants : function(aClazz) {");
theWriter.println(" return aClazz.$VALUES;");
theWriter.println(" },");
}
theMethods.stream().forEach(aEntry -> {
BytecodeMethod theMethod = aEntry.getValue();
BytecodeMethodSignature theCurrentMethodSignature = theMethod.getSignature();
// If the method is provided by the runtime, we do not need to generate the implementation
if (theMethod.getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
return;
}
// Do not generate code for abstract methods
if (theMethod.getAccessFlags().isAbstract()) {
return;
}
if (!(aEntry.getProvidingClass() == theLinkedClass)) {
// But include static methods, as they are inherited from the base classes
if (aEntry.getValue().getAccessFlags().isStatic() && !aEntry.getValue().isClassInitializer()) {
StringBuilder theArguments = new StringBuilder();
;
for (int i = 0; i < theCurrentMethodSignature.getArguments().length; i++) {
if (i > 0) {
theArguments.append(',');
}
theArguments.append('p');
theArguments.append(i);
}
// Static methods will just delegate to the implementation in the class
theWriter.println();
theWriter.println(" " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
if (!theCurrentMethodSignature.getReturnType().isVoid()) {
theWriter.print(" return ");
} else {
theWriter.print(" ");
}
theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
theWriter.print(".");
theWriter.print(JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature));
theWriter.print("(");
theWriter.print(theArguments);
theWriter.println(");");
theWriter.println(" },");
}
return;
}
aLinkerContext.getLogger().info("Compiling {}.{}", theLinkedClass.getClassName().name(), theMethod.getName().stringValue());
ProgramGenerator theGenerator = programGeneratorFactory.createFor(aLinkerContext);
Program theSSAProgram = theGenerator.generateFrom(aEntry.getProvidingClass().getBytecodeClass(), theMethod);
// Run optimizer
aOptions.getOptimizer().optimize(theSSAProgram.getControlFlowGraph(), aLinkerContext);
StringBuilder theArguments = new StringBuilder();
for (Program.Argument theArgument : theSSAProgram.getArguments()) {
if (theArguments.length() > 0) {
theArguments.append(',');
}
theArguments.append(theArgument.getVariable().getName());
}
if (theMethod.getAccessFlags().isNative()) {
if (theLinkedClass.getBytecodeClass().getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
return;
}
BytecodeImportedLink theLink = theLinkedClass.linkfor(theMethod);
theWriter.println();
theWriter.println(" " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
theWriter.print(" return bytecoder.imports.");
theWriter.print(theLink.getModuleName());
theWriter.print(".");
theWriter.print(theLink.getLinkName());
theWriter.print("(");
theWriter.print(theArguments);
theWriter.println(");");
theWriter.println(" },");
return;
}
theWriter.println();
theWriter.println(" " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
if (Objects.equals(theMethod.getName().stringValue(), "<clinit>")) {
for (BytecodeObjectTypeRef theRef : theSSAProgram.getStaticReferences()) {
if (!theInitDependencies.contains(theRef)) {
theInitDependencies.add(theRef);
}
}
}
if (aOptions.isDebugOutput()) {
theWriter.println(" /**");
theWriter.println(" " + theSSAProgram.getControlFlowGraph().toDOT());
theWriter.println(" */");
}
JSSSAWriter theVariablesWriter = new JSSSAWriter(aOptions, theSSAProgram, " ", theWriter, aLinkerContext, thePool);
for (Variable theVariable : theSSAProgram.globalVariables()) {
if (!theVariable.isSynthetic()) {
theVariablesWriter.print("var ");
theVariablesWriter.print(theVariable.getName());
theVariablesWriter.print(" = null;");
theVariablesWriter.print(" // type is ");
theVariablesWriter.print(theVariable.resolveType().resolve().name());
theVariablesWriter.print(" # of inits = " + theVariable.incomingDataFlows().size());
theVariablesWriter.println();
}
}
// Try to reloop it!
try {
Relooper theRelooper = new Relooper();
Relooper.Block theReloopedBlock = theRelooper.reloop(theSSAProgram.getControlFlowGraph());
theVariablesWriter.printRelooped(theReloopedBlock);
} catch (Exception e) {
System.out.println(theSSAProgram.getControlFlowGraph().toDOT());
throw new IllegalStateException("Error relooping cfg for " + theLinkedClass.getClassName().name() + '.' + theMethod.getName().stringValue(), e);
}
theWriter.println(" },");
});
theWriter.println();
theWriter.println(" classInitCheck : function() {");
theWriter.println(" if (!" + theJSClassName + ".__initialized) {");
theWriter.println(" " + theJSClassName + ".__initialized = true;");
if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
// Now we have to setup the prototype
// Only in case this class can be instantiated of course
theWriter.println(" var thePrototype = " + theJSClassName + ".Create.prototype;");
theWriter.println(" thePrototype.instanceOf = " + theJSClassName + ".instanceOf;");
theWriter.println(" thePrototype.ClassgetClass = " + theJSClassName + ".ClassgetClass;");
List<BytecodeResolvedMethods.MethodEntry> theEntries = theMethods.stream().collect(Collectors.toList());
Set<String> theVisitedMethods = new HashSet<>();
for (int i = theEntries.size() - 1; i >= 0; i--) {
BytecodeResolvedMethods.MethodEntry aEntry = theEntries.get(i);
BytecodeMethod theMethod = aEntry.getValue();
String theMethodName = JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theMethod.getSignature());
if (!theMethod.getAccessFlags().isStatic() && !theMethod.getAccessFlags().isAbstract() && !theMethod.isConstructor() && !theMethod.isClassInitializer()) {
if (theVisitedMethods.add(theMethodName)) {
theWriter.print(" thePrototype.");
theWriter.print(theMethodName);
theWriter.print(" = ");
theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
theWriter.print(".");
theWriter.print(theMethodName);
theWriter.println(";");
}
}
}
}
for (BytecodeObjectTypeRef theRef : theInitDependencies) {
if (!Objects.equals(theRef, theEntry.edgeType().objectTypeRef())) {
theWriter.print(" ");
theWriter.print(JSWriterUtils.toClassName(theRef));
theWriter.println(".classInitCheck();");
}
}
if (theLinkedClass.hasClassInitializer()) {
theWriter.println(" " + theJSClassName + ".VOIDclinit();");
}
theWriter.println(" }");
theWriter.println(" },");
theWriter.println();
theWriter.println("};");
theWriter.println();
});
theWriter.println();
theWriter.println("bytecoder.bootstrap = function() {");
List<StringValue> theValues = thePool.stringValues();
for (int i = 0; i < theValues.size(); i++) {
StringValue theValue = theValues.get(i);
theWriter.print(" bytecoder.stringpool[");
theWriter.print(i);
theWriter.print("] = bytecoder.newString(");
theWriter.print(JSWriterUtils.toArray(theValue.getStringValue().getBytes()));
theWriter.println(");");
}
aLinkerContext.linkedClasses().forEach(aEntry -> {
if (!aEntry.targetNode().getBytecodeClass().getAccessFlags().isInterface()) {
theWriter.print(" ");
theWriter.print(JSWriterUtils.toClassName(aEntry.edgeType().objectTypeRef()));
theWriter.println(".classInitCheck();");
}
});
theWriter.println("}");
theWriter.flush();
return new JSCompileResult(theStrWriter.toString());
}
use of de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef in project Bytecoder by mirkosertic.
the class InvokeVirtualOptimizer method visit.
private Optional<DirectInvokeMethodExpression> visit(InvokeVirtualMethodExpression aExpression, BytecodeLinkerContext aLinkerContext) {
String theMethodName = aExpression.getMethodName();
BytecodeMethodSignature theSignature = aExpression.getSignature();
BytecodeVirtualMethodIdentifier theIdentifier = aLinkerContext.getMethodCollection().toIdentifier(theMethodName, theSignature);
List<BytecodeLinkedClass> theLinkedClasses = aLinkerContext.getClassesImplementingVirtualMethod(theIdentifier);
if (theLinkedClasses.size() == 1) {
// There is only one class implementing this method, so we can make a direct call
BytecodeLinkedClass theLinked = theLinkedClasses.get(0);
if (!theLinked.emulatedByRuntime()) {
BytecodeMethod theMethod = theLinked.getBytecodeClass().methodByNameAndSignatureOrNull(theMethodName, theSignature);
if (!theMethod.getAccessFlags().isAbstract()) {
BytecodeObjectTypeRef theClazz = theLinked.getClassName();
DirectInvokeMethodExpression theNewExpression = new DirectInvokeMethodExpression(theClazz, theMethodName, theSignature);
aExpression.routeIncomingDataFlowsTo(theNewExpression);
return Optional.of(theNewExpression);
}
}
}
return Optional.empty();
}
use of de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef in project Bytecoder by mirkosertic.
the class Program method getStaticReferences.
public Set<BytecodeObjectTypeRef> getStaticReferences() {
Set<BytecodeObjectTypeRef> theResult = new HashSet<>();
for (RegionNode theNode : controlFlowGraph.getKnownNodes()) {
for (Expression theExpression : theNode.getExpressions().toList()) {
if (theExpression instanceof PutStaticExpression) {
PutStaticExpression theE = (PutStaticExpression) theExpression;
theResult.add(BytecodeObjectTypeRef.fromUtf8Constant(theE.getField().getClassIndex().getClassConstant().getConstant()));
}
}
}
for (Variable theVariable : variables) {
for (Value theValue : theVariable.incomingDataFlows()) {
if (theValue instanceof InvokeStaticMethodExpression) {
InvokeStaticMethodExpression theInvokeStatic = (InvokeStaticMethodExpression) theValue;
theResult.add(theInvokeStatic.getClassName());
}
if (theValue instanceof GetStaticExpression) {
GetStaticExpression theStaticValue = (GetStaticExpression) theValue;
theResult.add(BytecodeObjectTypeRef.fromUtf8Constant(theStaticValue.getField().getClassIndex().getClassConstant().getConstant()));
}
if (theValue instanceof StringValue) {
theResult.add(BytecodeObjectTypeRef.fromRuntimeClass(String.class));
}
if (theValue instanceof ClassReferenceValue) {
ClassReferenceValue theClassRef = (ClassReferenceValue) theValue;
theResult.add(theClassRef.getType());
}
if (theValue instanceof NewArrayExpression) {
NewArrayExpression theNewArray = (NewArrayExpression) theValue;
if (theNewArray.getType() instanceof BytecodeObjectTypeRef) {
theResult.add((BytecodeObjectTypeRef) theNewArray.getType());
}
}
if (theValue instanceof NewMultiArrayExpression) {
NewMultiArrayExpression theNewArray = (NewMultiArrayExpression) theValue;
BytecodeTypeRef theTypeRef = theNewArray.getType();
if (theTypeRef instanceof BytecodeObjectTypeRef) {
theResult.add((BytecodeObjectTypeRef) theTypeRef);
}
}
if (theValue instanceof NewObjectExpression) {
NewObjectExpression theNewObjectValue = (NewObjectExpression) theValue;
theResult.add(BytecodeObjectTypeRef.fromUtf8Constant(theNewObjectValue.getType().getConstant()));
}
}
}
return theResult;
}
use of de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef in project Bytecoder by mirkosertic.
the class BytecoderUnitTestRunner method testWASMBackendFrameworkMethod.
private void testWASMBackendFrameworkMethod(FrameworkMethod aFrameworkMethod, RunNotifier aRunNotifier) {
Description theDescription = Description.createTestDescription(testClass.getJavaClass(), aFrameworkMethod.getName() + " WASM Backend ");
aRunNotifier.fireTestStarted(theDescription);
WebDriver theDriver = null;
try {
CompileTarget theCompileTarget = new CompileTarget(testClass.getJavaClass().getClassLoader(), CompileTarget.BackendType.wasm);
BytecodeMethodSignature theSignature = theCompileTarget.toMethodSignature(aFrameworkMethod.getMethod());
BytecodeObjectTypeRef theTypeRef = new BytecodeObjectTypeRef(testClass.getName());
CompileOptions theOptions = new CompileOptions(LOGGER, true, KnownOptimizer.ALL);
WASMCompileResult theResult = (WASMCompileResult) theCompileTarget.compileToJS(theOptions, testClass.getJavaClass(), aFrameworkMethod.getName(), theSignature);
String theFileName = theCompileTarget.toClassName(theTypeRef) + "." + theCompileTarget.toMethodName(aFrameworkMethod.getName(), theSignature) + ".html";
File theWorkingDirectory = new File(".");
initializeSeleniumDriver();
File theMavenTargetDir = new File(theWorkingDirectory, "target");
File theGeneratedFilesDir = new File(theMavenTargetDir, "bytecoderwat");
theGeneratedFilesDir.mkdirs();
File theGeneratedFile = new File(theGeneratedFilesDir, theFileName);
// Copy WABT Tools
File theWABTFile = new File(theGeneratedFilesDir, "libwabt.js");
try (FileOutputStream theOS = new FileOutputStream(theWABTFile)) {
IOUtils.copy(getClass().getResourceAsStream("/libwabt.js"), theOS);
}
PrintWriter theWriter = new PrintWriter(theGeneratedFile);
theWriter.println("<html>");
theWriter.println(" <body>");
theWriter.println(" <h1>Module code</h1>");
theWriter.println(" <pre id=\"modulecode\">");
theWriter.println(theResult.getData());
theWriter.println(" </pre>");
theWriter.println(" <h1>Compilation result</h1>");
theWriter.println(" <pre id=\"compileresult\">");
theWriter.println(" </pre>");
theWriter.println(" <script src=\"libwabt.js\">");
theWriter.println(" </script>");
theWriter.println(" <script>");
theWriter.println(" var runningInstance;");
theWriter.println(" var runningInstanceMemory;");
theWriter.println();
theWriter.println(" function bytecoder_IntInMemory(value) {");
theWriter.println(" return runningInstanceMemory[value]");
theWriter.println(" + (runningInstanceMemory[value + 1] * 256)");
theWriter.println(" + (runningInstanceMemory[value + 2] * 256 * 256)");
theWriter.println(" + (runningInstanceMemory[value + 3] * 256 * 256 * 256);");
theWriter.println(" }");
theWriter.println();
theWriter.println(" function bytecoder_logByteArrayAsString(acaller, value) {");
theWriter.println(" var theLength = bytecoder_IntInMemory(value + 16);");
theWriter.println(" var theData = '';");
theWriter.println(" value = value + 20;");
theWriter.println(" for (var i=0;i<theLength;i++) {");
theWriter.println(" var theCharCode = bytecoder_IntInMemory(value);");
theWriter.println(" value = value + 4;");
theWriter.println(" theData+= String.fromCharCode(theCharCode);");
theWriter.println(" }");
theWriter.println(" console.log(theData);");
theWriter.println(" }");
theWriter.println();
theWriter.println(" function bytecoder_logDebug(caller,value) {");
theWriter.println(" console.log(value);");
theWriter.println(" }");
theWriter.println();
theWriter.println(" function compile() {");
theWriter.println(" console.log('Test started');");
theWriter.println(" try {");
theWriter.println(" var module = wabt.parseWat('test.wast', document.getElementById(\"modulecode\").innerText);");
theWriter.println(" module.resolveNames();");
theWriter.println(" module.validate();");
theWriter.println(" var binaryOutput = module.toBinary({log: true, write_debug_names:true});");
theWriter.println(" document.getElementById(\"compileresult\").innerText = binaryOutput.log;");
theWriter.println(" var binaryBuffer = binaryOutput.buffer;");
theWriter.println(" console.log('Size of compiled WASM binary is ' + binaryBuffer.length);");
theWriter.println();
theWriter.println(" var theInstantiatePromise = WebAssembly.instantiate(binaryBuffer, {");
theWriter.println(" system: {");
theWriter.println(" currentTimeMillis: function() {return Date.now();},");
theWriter.println(" nanoTime: function() {return Date.now() * 1000000;},");
theWriter.println(" logDebug: bytecoder_logDebug,");
theWriter.println(" writeByteArrayToConsole: bytecoder_logByteArrayAsString,");
theWriter.println(" },");
theWriter.println(" printstream: {");
theWriter.println(" logDebug: bytecoder_logDebug,");
theWriter.println(" },");
theWriter.println(" math: {");
theWriter.println(" floor: function (thisref, p1) {return Math.floor(p1);},");
theWriter.println(" ceil: function (thisref, p1) {return Math.ceil(p1);},");
theWriter.println(" sin: function (thisref, p1) {return Math.sin(p1);},");
theWriter.println(" cos: function (thisref, p1) {return Math.cos(p1);},");
theWriter.println(" round: function (thisref, p1) {return Math.round(p1);},");
theWriter.println(" float_rem: function(a, b) {return a % b;},");
theWriter.println(" sqrt: function(thisref, p1) {return Math.sqrt(p1);},");
theWriter.println(" add: function(thisref, p1, p2) {return p1 + p2;},");
theWriter.println(" float_rem: function(a, b) {return a % b;},");
theWriter.println(" max: function(p1, p2) { return Math.max(p1, p2);},");
theWriter.println(" min: function(p1, p2) { return Math.min(p1, p2);},");
theWriter.println(" },");
theWriter.println(" strictmath: {");
theWriter.println(" floor: function (thisref, p1) {return Math.floor(p1);},");
theWriter.println(" ceil: function (thisref, p1) {return Math.ceil(p1);},");
theWriter.println(" sin: function (thisref, p1) {return Math.sin(p1);},");
theWriter.println(" cos: function (thisref, p1) {return Math.cos(p1);},");
theWriter.println(" round: function (thisref, p1) {return Math.round(p1);},");
theWriter.println(" float_rem: function(a, b) {return a % b;},");
theWriter.println(" sqrt: function(thisref, p1) {return Math.sqrt(p1);},");
theWriter.println(" add: function(thisref, p1, p2) {return p1 + p2;},");
theWriter.println(" },");
theWriter.println(" profiler: {");
theWriter.println(" logMemoryLayoutBlock: function(aCaller, aStart, aUsed, aNext) {");
theWriter.println(" if (aUsed == 1) return;");
theWriter.println(" console.log(' Block at ' + aStart + ' status is ' + aUsed + ' points to ' + aNext);");
theWriter.println(" console.log(' Block size is ' + bytecoder_IntInMemory(aStart));");
theWriter.println(" console.log(' Object type ' + bytecoder_IntInMemory(aStart + 12));");
theWriter.println(" }");
theWriter.println(" }");
theWriter.println(" });");
theWriter.println(" theInstantiatePromise.then(");
theWriter.println(" function (resolved) {");
theWriter.println(" var wasmModule = resolved.module;");
theWriter.println(" runningInstance = resolved.instance;");
theWriter.println(" runningInstanceMemory = new Uint8Array(runningInstance.exports.memory.buffer);");
theWriter.println(" runningInstance.exports.initMemory(0);");
theWriter.println(" console.log(\"Memory initialized\")");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" console.log(\"Used memory in bytes \" + runningInstance.exports.usedMem());");
theWriter.println(" console.log(\"Free memory in bytes \" + runningInstance.exports.freeMem());");
theWriter.println(" runningInstance.exports.bootstrap(0);");
theWriter.println(" console.log(\"Used memory after bootstrap in bytes \" + runningInstance.exports.usedMem());");
theWriter.println(" console.log(\"Free memory after bootstrap in bytes \" + runningInstance.exports.freeMem());");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" console.log(\"Creating test instance\")");
theWriter.print(" var theTest = runningInstance.exports.newObject(0,");
theWriter.print(theResult.getSizeOf(theTypeRef));
theWriter.print(",");
theWriter.print(theResult.getTypeIDFor(theTypeRef));
theWriter.print(",");
theWriter.print(theResult.getVTableIndexOf(theTypeRef));
theWriter.println(", 0);");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" console.log(\"Bootstrapped\")");
theWriter.println(" try {");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" console.log(\"Starting main method\")");
theWriter.println(" runningInstance.exports.main(theTest);");
theWriter.println(" console.log(\"Main finished\")");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" wasmHexDump(runningInstanceMemory);");
theWriter.println(" console.log(\"Test finished OK\")");
theWriter.println(" } catch (e) {");
theWriter.println(" console.log(\"Test threw error\")");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" wasmHexDump(runningInstanceMemory);");
theWriter.println(" throw e;");
theWriter.println(" }");
theWriter.println(" },");
theWriter.println(" function (rejected) {");
theWriter.println(" console.log(\"Error instantiating webassembly\");");
theWriter.println(" console.log(rejected);");
theWriter.println(" }");
theWriter.println(" );");
theWriter.println(" } catch (e) {");
theWriter.println(" document.getElementById(\"compileresult\").innerText = e.toString();");
theWriter.println(" console.log(e.toString());");
theWriter.println(" console.log(e.stack);");
theWriter.println(" if (runningInstance) {");
theWriter.println(" runningInstance.exports.logMemoryLayout(0);");
theWriter.println(" wasmHexDump(runningInstanceMemory);");
theWriter.println(" }");
theWriter.println(" }");
theWriter.println(" }");
theWriter.println();
theWriter.println(" function wasmHexDump(memory) {");
theWriter.println(" var theStart = 0;");
theWriter.println(" console.log('HEX DUMP');");
theWriter.println(" console.log('=================================================================================');");
theWriter.println(" for (var i=0;i<200;i++) {");
theWriter.println(" var theLine = '' + theStart;");
theWriter.println(" while(theLine.length < 15) {");
theWriter.println(" theLine+= ' ';");
theWriter.println(" }");
theWriter.println(" theLine+= ' : ';");
theWriter.println(" for (var j=0;j<32;j++) {");
theWriter.println(" var theByte = memory[theStart++];");
theWriter.println(" var theData = '' + theByte;");
theWriter.println(" while(theData.length < 3) {");
theWriter.println(" theData = ' ' + theData;");
theWriter.println(" }");
theWriter.println(" theLine += theData;");
theWriter.println(" theLine += ' ';");
theWriter.println(" }");
theWriter.println(" console.log(theLine);");
theWriter.println(" }");
theWriter.println(" console.log('DONE');");
theWriter.println(" }");
theWriter.println();
theWriter.println(" compile();");
theWriter.println(" </script>");
theWriter.println(" </body>");
theWriter.println("</html>");
theWriter.flush();
theWriter.close();
try (PrintWriter theWATWriter = new PrintWriter(new FileWriter(new File(theGeneratedFilesDir, theCompileTarget.toClassName(theTypeRef) + "." + theCompileTarget.toMethodName(aFrameworkMethod.getName(), theSignature) + ".wat")))) {
theWATWriter.println(theResult.getData());
}
// Invoke test in browser
theDriver = newDriverForTest();
theDriver.get(theGeneratedFile.toURI().toURL().toString());
long theStart = System.currentTimeMillis();
boolean theTestSuccedded = false;
while (!theTestSuccedded && System.currentTimeMillis() - theStart < 10 * 1000) {
List<LogEntry> theAll = theDriver.manage().logs().get(LogType.BROWSER).getAll();
for (LogEntry theEntry : theAll) {
String theMessage = theEntry.getMessage();
System.out.println(theMessage);
if (theMessage.contains("Test finished OK")) {
theTestSuccedded = true;
}
}
if (!theTestSuccedded) {
Thread.sleep(100);
}
}
if (!theTestSuccedded) {
aRunNotifier.fireTestFailure(new Failure(theDescription, new RuntimeException("Test did not succeed!")));
}
} catch (ControlFlowProcessingException e) {
System.out.println(e.getGraph().toDOT());
aRunNotifier.fireTestFailure(new Failure(theDescription, e));
} catch (Exception e) {
aRunNotifier.fireTestFailure(new Failure(theDescription, e));
} finally {
if (theDriver != null) {
theDriver.close();
}
aRunNotifier.fireTestFinished(theDescription);
}
}
Aggregations