public void generateCompoundAssignment(
     BlockScope currentScope,
     Expression expression,
     int operator,
     int assignmentImplicitConversion,
     boolean valueRequired) {
   this.receiver.generateCode(currentScope, true);
   if (this.receiver instanceof CastExpression // ((type[])null)[0]
       && ((CastExpression) this.receiver).innermostCastedExpression().resolvedType
           == TypeBinding.NULL) {}
   this.position.generateCode(currentScope, true);
   int operationTypeID;
   switch (operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
     case T_JavaLangString:
     case T_JavaLangObject:
     case T_undefined:
       break;
     default:
       // promote the array reference to the suitable operation type
       // generate the increment value (will by itself  be promoted to the operation value)
       if (expression == IntLiteral.One) { // prefix operation
       } else {
         expression.generateCode(currentScope, true);
       }
   }
 }
 /**
  * Die Methode generiert den Assembler-Code für diesen Ausdruck. Sie geht davon aus, dass die
  * Kontextanalyse vorher erfolgreich abgeschlossen wurde.
  *
  * @param code Der Strom, in den die Ausgabe erfolgt.
  */
 void generateCode(CodeStream code) {
   leftOperand.generateCode(code);
   rightOperand.generateCode(code);
 }
 /*
  * The APIs with an extra argument is used whenever there are two references to the same variable which
  * are optimized in one access: e.g "a = a + 1" optimized into "a++".
  */
 public void generateCompoundAssignment(
     BlockScope currentScope,
     MethodBinding writeAccessor,
     Expression expression,
     int operator,
     int assignmentImplicitConversion,
     boolean valueRequired) {
   switch (this.bits & ASTNode.RestrictiveFlagMASK) {
     case Binding.FIELD: // assigning to a field
       break;
     case Binding.LOCAL: // assigning to a local variable (cannot assign to outer local)
       LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
       // using incr bytecode if possible
       Constant assignConstant;
       switch (localBinding.type.id) {
         case T_JavaLangString:
           return;
         case T_int:
           assignConstant = expression.constant;
           if (localBinding.resolvedPosition == -1) {
             if (valueRequired) {
               /*
                * restart code gen because we either:
                * - need the value
                * - the constant can have potential side-effect
                */
               localBinding.useFlag = LocalVariableBinding.USED;
               throw new AbortMethod(null, null);
             } else if (assignConstant == Constant.NotAConstant) {
               // we only need to generate the value of the expression's constant if it is not a
               // constant expression
               expression.generateCode(currentScope, false);
             }
             return;
           }
           if ((assignConstant != Constant.NotAConstant)
               && (assignConstant.typeID() != TypeIds.T_float)
               // only for integral types
               && (assignConstant.typeID()
                   != TypeIds.T_double)) { // TODO (philippe) is this test needed ?
             switch (operator) {
               case PLUS:
                 int increment = assignConstant.intValue();
                 if (increment != (short) increment) break; // not representable as a 16-bits value
                 return;
               case MINUS:
                 increment = -assignConstant.intValue();
                 if (increment != (short) increment) break; // not representable as a 16-bits value
                 return;
             }
           }
           // $FALL-THROUGH$
         default:
           if (localBinding.resolvedPosition == -1) {
             assignConstant = expression.constant;
             if (valueRequired) {
               /*
                * restart code gen because we either:
                * - need the value
                * - the constant can have potential side-effect
                */
               localBinding.useFlag = LocalVariableBinding.USED;
               throw new AbortMethod(null, null);
             } else if (assignConstant == Constant.NotAConstant) {
               // we only need to generate the value of the expression's constant if it is not a
               // constant expression
               expression.generateCode(currentScope, false);
             }
             return;
           }
       }
   }
   switch ((this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
     case T_JavaLangString:
     case T_JavaLangObject:
     case T_undefined:
       // we enter here if the single name reference is a field of type java.lang.String or if the
       // type of the
       // operation is java.lang.Object
       // For example: o = o + ""; // where the compiled type of o is java.lang.Object.
       // no need for generic cast on previous #getfield since using Object string buffer methods.
       break;
     default:
       // promote the array reference to the suitable operation type
       // generate the increment value (will by itself  be promoted to the operation value)
       if (expression != IntLiteral.One) { // prefix operation
         expression.generateCode(currentScope, true);
       }
   }
   // store the result back into the variable
   switch (this.bits & ASTNode.RestrictiveFlagMASK) {
     case Binding.FIELD: // assigning to a field
       FieldBinding codegenField = ((FieldBinding) this.binding).original();
       fieldStore(
           currentScope,
           codegenField,
           writeAccessor,
           this.actualReceiverType,
           true /* implicit this*/,
           valueRequired);
       // no need for generic cast as value got dupped
       return;
     case Binding.LOCAL: // assigning to a local variable
       LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
       if (valueRequired) {
         switch (localBinding.type.id) {
           case TypeIds.T_long:
           case TypeIds.T_double:
             break;
           default:
             break;
         }
       }
   }
 }
Beispiel #4
0
 /**
  * Die Methode generiert den Assembler-Code für diesen Ausdruck. Sie geht davon aus, dass die
  * Kontextanalyse vorher erfolgreich abgeschlossen wurde.
  *
  * @param code Der Strom, in den die Ausgabe erfolgt.
  */
 void generateCode(CodeStream code) {
   if (identifier.declaration instanceof VarDeclaration) {
     VarDeclaration v = (VarDeclaration) identifier.declaration;
     if (v.isAttribute) {
       code.println("; Referenz auf Attribut " + identifier.name);
       code.println("MRM R5, (R2)");
       code.println("MRI R6, " + v.offset);
       code.println("ADD R5, R6");
       code.println("MMR (R2), R5");
     } else {
       code.println("; Referenz auf Variable " + identifier.name);
       code.println("MRI R5, " + v.offset);
       code.println("ADD R5, R3");
       code.println("ADD R2, R1");
       code.println("MMR (R2), R5");
     }
   } else if (identifier.declaration instanceof MethodDeclaration) {
     MethodDeclaration m = (MethodDeclaration) identifier.declaration;
     /** BEGIN Aufgabe (f): Methoden Parameter */
     code.println("; CALL " + m.self.type.name + "." + m.identifier.name);
     /** BEGIN Aufgabe (j): Garbage Collector */
     code.println("MRM R5, (R2) ; SELF von R2 nehmen");
     code.println("SUB R2, R1");
     code.println("ADD R4, R1");
     code.println("MMR (R4), R5 ; SELF auf R4 legen");
     /** END Aufgabe (j) */
     if (!params.isEmpty()) {
       for (int i = 0; i < params.size(); i++) {
         Expression p = params.get(i);
         code.println("; Parameter " + i + ":");
         p.generateCode(code);
         /** BEGIN Aufgabe (j): Garbage Collector */
         code.println("MRM R5, (R2) ; Parameter " + i + " von R2 nehmen");
         code.println("SUB R2, R1");
         code.println("ADD R4, R1");
         code.println("MMR (R4), R5 ; Parameter " + i + " auf R4 legen");
         /** END Aufgabe (j) */
       }
     }
     /** END Aufgabe (f) */
     String returnLabel = code.nextLabel();
     code.println("MRI R5, " + returnLabel);
     code.println("ADD R2, R1");
     code.println("MMR (R2), R5 ; Rücksprungadresse auf den Stapel");
     /** BEGIN Aufgabe (i): Vererbung */
     if (dynamicBind) {
       // dynamisches Binden
       code.println("; Dynamischer Aufruf von " + identifier.name);
       code.println("MRI R5, " + (m.self.offset + 1));
       /** BEGIN Aufgabe (j): Garbage Collector */
       // code.println("ADD R5, R2 ");
       code.println("ADD R5, R4 ");
       /** END Aufgabe (j) */
       code.println("MRM R5, (R5) ; Adresse von SELF auf dem Heap ");
       code.println("MRM R5, (R5) ; VMT Referenz ");
       code.println("MRI R6, " + m.index + " ; Methodenoffset");
       code.println("ADD R5, R6 ; Methodenoffset anwenden");
       code.println("MRM R5, (R5) ; Methodenadresse holen ");
       code.println("MRR R0, R5 ; Sprung zu " + m.identifier.name);
     } else {
       code.println("; Statischer Aufruf von " + identifier.name);
       code.println("MRI R0, " + m.self.type.name + "_" + m.identifier.name);
     }
     /** END Aufgabe (i) */
     // code.println("; Statischer Aufruf von " + identifier.name);
     // code.println("MRI R0, " + m.self.type.name + "_" + m.identifier.name);
     code.println(returnLabel + ":");
   } else {
     assert false;
   }
 }
 public void generateCompoundAssignment(
     BlockScope currentScope,
     CodeStream codeStream,
     Expression expression,
     int operator,
     int assignmentImplicitConversion,
     boolean valueRequired) {
   boolean isStatic;
   // check if compound assignment is the only usage of a private field
   reportOnlyUselesslyReadPrivateField(currentScope, this.binding, valueRequired);
   FieldBinding codegenBinding = this.binding.original();
   this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
   if (isStatic) {
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   } else {
     codeStream.dup();
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   }
   int operationTypeID;
   switch (operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
     case T_JavaLangString:
     case T_JavaLangObject:
     case T_undefined:
       codeStream.generateStringConcatenationAppend(currentScope, null, expression);
       break;
     default:
       if (this.genericCast != null) codeStream.checkcast(this.genericCast);
       // promote the array reference to the suitable operation type
       codeStream.generateImplicitConversion(this.implicitConversion);
       // generate the increment value (will by itself  be promoted to the operation value)
       if (expression == IntLiteral.One) { // prefix operation
         codeStream.generateConstant(expression.constant, this.implicitConversion);
       } else {
         expression.generateCode(currentScope, codeStream, true);
       }
       // perform the operation
       codeStream.sendOperator(operator, operationTypeID);
       // cast the value back to the array reference type
       codeStream.generateImplicitConversion(assignmentImplicitConversion);
   }
   fieldStore(
       currentScope,
       codeStream,
       codegenBinding,
       this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
       this.actualReceiverType,
       this.receiver.isImplicitThis(),
       valueRequired);
   // no need for generic cast as value got dupped
 }
Beispiel #6
0
  /** Code generation for a array initializer */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    // Flatten the values and compute the dimensions, by iterating in depth into nested array
    // initializers
    int pc = codeStream.position;
    int expressionLength = (this.expressions == null) ? 0 : this.expressions.length;
    codeStream.generateInlinedValue(expressionLength);
    codeStream.newArray(this.binding);
    if (this.expressions != null) {
      // binding is an ArrayType, so I can just deal with the dimension
      int elementsTypeID = this.binding.dimensions > 1 ? -1 : this.binding.leafComponentType.id;
      for (int i = 0; i < expressionLength; i++) {
        Expression expr;
        if ((expr = this.expressions[i]).constant != Constant.NotAConstant) {
          switch (elementsTypeID) { // filter out initializations to default values
            case T_int:
            case T_short:
            case T_byte:
            case T_char:
            case T_long:
              if (expr.constant.longValue() != 0) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            case T_float:
            case T_double:
              double constantValue = expr.constant.doubleValue();
              if (constantValue == -0.0 || constantValue != 0) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            case T_boolean:
              if (expr.constant.booleanValue() != false) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            default:
              if (!(expr instanceof NullLiteral)) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
          }
        } else if (!(expr instanceof NullLiteral)) {
          codeStream.dup();
          codeStream.generateInlinedValue(i);
          expr.generateCode(currentScope, codeStream, true);
          codeStream.arrayAtPut(elementsTypeID, false);
        }
      }
    }
    if (valueRequired) {
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else {
      codeStream.pop();
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }