deep-c-rsc/JCGO/jtrsrc/com/ivmaisoft/jcgo/Assignment.java
2021-07-16 17:12:20 -05:00

1047 lines
44 KiB
Java

/*
* @(#) $(JCGO)/jtrsrc/com/ivmaisoft/jcgo/Assignment.java --
* a part of JCGO translator.
**
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
* Copyright (C) 2001-2012 Ivan Maidanski <ivmai@mail.ru>
* All rights reserved.
*/
/*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
**
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License (GPL) for more details.
**
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
**
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package com.ivmaisoft.jcgo;
/**
* Grammar production for assignments (simple and compound).
**
* Formats: LeftHandSide EQUALS AssignmentExpression LeftHandSide FLSHIFT_EQUALS
* AssignmentExpression LeftHandSide SHRIGHT_EQUALS AssignmentExpression
* LeftHandSide SHLEFT_EQUALS AssignmentExpression LeftHandSide XOR_EQUALS
* AssignmentExpression LeftHandSide BITOR_EQUALS AssignmentExpression
* LeftHandSide BITAND_EQUALS AssignmentExpression LeftHandSide MOD_EQUALS
* AssignmentExpression LeftHandSide DIVIDE_EQUALS AssignmentExpression
* LeftHandSide TIMES_EQUALS AssignmentExpression LeftHandSide MINUS_EQUALS
* AssignmentExpression LeftHandSide PLUS_EQUALS AssignmentExpression
*/
final class Assignment extends LexNode {
private ExpressionType exprType0;
private ExpressionType exprType2;
private ExpressionType actualType2;
private boolean isString;
private int forceVmExc;
private int rcvr1;
private int rcvr2;
private int rcvr3;
private boolean isVoidExpr;
Assignment(Term a, Term b, Term c) {
super(a, b, c);
}
void assignedVarNames(ObjQueue names, boolean recursive) {
if (recursive) {
terms[0].assignedVarNames(names, true);
terms[2].assignedVarNames(names, true);
}
if (terms[1].getSym() == LexTerm.EQUALS) {
String id = terms[0].dottedName();
if (id != null) {
names.addLast(id);
}
}
}
void processPass1(Context c) {
if (exprType0 == null) {
int sym = terms[1].getSym();
c.lvalue = true;
if (sym == LexTerm.EQUALS) {
c.setOnly = true;
}
forceVmExc = c.forceVmExc;
BranchContext oldBranch = c.saveBranch();
terms[0].processPass1(c);
oldBranch = c.swapBranch(oldBranch);
c.lvalue = false;
c.setOnly = false;
terms[2].processPass1(c);
c.unionBranch(oldBranch);
exprType0 = terms[0].exprType();
exprType2 = terms[2].exprType();
int s0 = exprType0.objectSize();
int s2 = exprType2.objectSize();
if (s2 == Type.VOID) {
fatalError(c, "Incompatible types in assignment expression");
}
VariableDefinition v = terms[0].getVariable(false);
if (sym == LexTerm.PLUS_EQUALS
&& exprType0.receiverClass().isStringOrNull()) {
isString = true;
if (!exprType2.receiverClass().isStringOrNull()) {
exprType2 = (terms[2] = BinaryOp.wrapInValueOf(c, terms[2]))
.exprType();
}
actualType2 = exprType2;
Main.dict.get(Names.JAVA_LANG_VMSYSTEM).markMethod(
Names.SIGN_CONCAT0X);
if (v != null) {
c.setVarNotNull(v);
v.setStrLiteralValue(strLiteralValueGuess());
}
} else {
actualType2 = exprType2;
if (v != null && sym == LexTerm.EQUALS && v.isLocalOrParam()) {
v.setUnassigned(false);
}
if (s0 == Type.BOOLEAN) {
if (s2 != Type.BOOLEAN) {
fatalError(c,
"Incompatible types in assignment expression");
}
if (sym != LexTerm.EQUALS && sym != LexTerm.XOR_EQUALS
&& sym != LexTerm.BITOR_EQUALS
&& sym != LexTerm.BITAND_EQUALS) {
fatalError(c, "Illegal assignment operator");
}
} else if (s0 < Type.CLASSINTERFACE) {
if ((s0 >= Type.FLOAT || s2 >= Type.FLOAT)
&& sym != LexTerm.EQUALS
&& sym != LexTerm.PLUS_EQUALS
&& sym != LexTerm.MINUS_EQUALS
&& sym != LexTerm.TIMES_EQUALS
&& sym != LexTerm.DIVIDE_EQUALS
&& sym != LexTerm.MOD_EQUALS) {
fatalError(c, "Illegal assignment operator");
}
if (s2 <= Type.BOOLEAN
|| s2 >= Type.CLASSINTERFACE
|| (sym == LexTerm.EQUALS && s2 >= Type.LONG && s0 < s2)) {
fatalError(c,
"Incompatible types in assignment expression");
}
} else {
if (sym != LexTerm.EQUALS) {
fatalError(c, "Illegal assignment operator");
}
if (s2 >= Type.BOOLEAN && s2 <= Type.VOID) {
fatalError(c,
"Incompatible types in assignment expression");
}
actualType2 = terms[2].actualExprType();
if (v != null) {
if (terms[2].isNotNull()) {
c.setVarNotNull(v);
} else {
c.clearVarNotNull(v);
}
c.setActualType(v, actualType2);
v.setClassNewInstanceCall(terms[2]
.getClassNewInstanceCall());
v.setConstructorInstanceSign(terms[2]
.getConstructorInstanceSign());
v.setClassLiteralValGuess(terms[2]
.classLiteralValGuess());
v.setStrLiteralValue(terms[2].strLiteralValueGuess());
ObjVector parmSig = new ObjVector();
if (terms[2].storeClassLiteralsGuess(parmSig, false)) {
v.setStoredClassLiteralsGuess(parmSig, false);
}
if (parmSig.size() != 0) {
parmSig = new ObjVector();
}
if (terms[2].storeClassLiteralsGuess(parmSig, true)) {
v.setStoredClassLiteralsGuess(parmSig, true);
}
}
}
}
}
}
int tokenCount() {
return terms[0].tokenCount() + terms[2].tokenCount()
+ (terms[0].isSafeExpr() || terms[2].isSafeExpr() ? 1 : 2);
}
void allocRcvr(int[] curRcvrs) {
assertCond(exprType0 != null);
int sym = terms[1].getSym();
Term t0 = terms[0];
Term t1 = t0.getArgumentTerm(1);
Term t2 = terms[2];
int[] curRcvrs2;
if (t1 != null) {
t0 = t0.getArgumentTerm(0);
int rmask = 0;
if (t0.isSafeExpr() ? (t2.isSafeExpr() ? !t1.isSafeWithThrow()
&& (t0.isFieldAccessed(null) || t2.isFieldAccessed(null)
|| t1.isAnyLocalVarChanged(t0) || t1
.isAnyLocalVarChanged(t2))
&& (!t0.isImmutable() || !t2.isImmutable()) : !t0
.isImmutable()
|| !t1.isImmutable()
|| (sym != LexTerm.EQUALS && !t2.isSafeWithThrow())) : !t2
.isSafeExpr()
|| !t1.isSafeExpr()
|| (!t0.isSafeWithThrow()
&& (t1.isFieldAccessed(null)
|| t2.isFieldAccessed(null)
|| t0.isAnyLocalVarChanged(t1) || t0
.isAnyLocalVarChanged(t2)) && (!t1
.isImmutable() || !t2.isImmutable()))) {
rmask = 1;
if (!t2.isSafeExpr()
|| (!t1.isSafeWithThrow() && !t2.isImmutable())) {
rmask = 2;
if (sym == LexTerm.EQUALS
&& exprType2.objectSize() >= Type.CLASSINTERFACE
&& exprType0.signatureClass()
.hasInstantatedSubclasses(true)) {
if (t2.isSafeWithThrow() && t0.isSafeExpr()
&& t1.isSafeExpr()) {
rmask = 0;
} else if (!t0.isImmutable()
&& (!t2.isSafeWithThrow()
|| !t1.isSafeWithThrow() || !t0
.isSafeExpr())) {
rmask = 1;
if (!t1.isImmutable()
&& (!t1.isSafeExpr() || !t2
.isSafeWithThrow())) {
rmask = 3;
}
}
} else if (t2.isSafeExpr()) {
if (!t0.isImmutable()) {
rmask = 3;
}
} else if (sym != LexTerm.EQUALS && t2.isSafeWithThrow()) {
if (!t1.isSafeWithThrow()
|| (!t0.isSafeExpr() && (!t1.isSafeExpr() || !t0
.isSafeWithThrow()))) {
rmask = 3;
}
} else {
rmask = 6;
if (sym == LexTerm.EQUALS) {
if (t2.isSafeWithThrow()
&& t1.isSafeWithThrow()
&& (t0.isSafeExpr() || (t1.isSafeExpr() && t0
.isSafeWithThrow()))) {
rmask = 4;
} else if (t1.isImmutable()
|| (t1.isSafeExpr() && t2.isSafeWithThrow())) {
rmask = 5;
} else if (!t0.isImmutable()) {
rmask = 7;
}
} else if (!t0.isImmutable()
&& !t1.isImmutable()
&& (!t1.isSafeWithThrow() || (!t0.isSafeExpr() && (!t1
.isSafeExpr() || !t0.isSafeWithThrow())))) {
rmask = 7;
}
}
}
if ((rmask & 1) != 0) {
rcvr1 = ++curRcvrs[Type.NULLREF];
}
}
int s0 = exprType0.objectSize();
int s2;
if ((rmask & 2) != 0
|| (rmask == 0 && (isString || sym == LexTerm.DIVIDE_EQUALS
|| sym == LexTerm.MOD_EQUALS
|| sym == LexTerm.FLSHIFT_EQUALS
|| sym == LexTerm.SHRIGHT_EQUALS
|| sym == LexTerm.SHLEFT_EQUALS || (sym != LexTerm.EQUALS
&& (s2 = exprType2.objectSize()) >= Type.FLOAT && s0 < s2)))) {
rcvr2 = ++curRcvrs[sym != LexTerm.EQUALS ? Type.NULLREF
: Type.INT];
}
if (rmask > 3) {
rcvr3 = ++curRcvrs[s0 < Type.VOID ? s0 : Type.NULLREF];
}
int[] curRcvrs1 = OutputContext.copyRcvrs(curRcvrs);
t0.allocRcvr(curRcvrs);
curRcvrs2 = OutputContext.copyRcvrs(curRcvrs1);
t1.allocRcvr(curRcvrs1);
OutputContext.joinRcvrs(curRcvrs, curRcvrs1);
} else {
curRcvrs2 = OutputContext.copyRcvrs(curRcvrs);
t0.allocRcvr(curRcvrs);
int s2;
VariableDefinition leftVar;
if (sym != LexTerm.EQUALS
&& (leftVar = t0.getVariable(true)) != null
&& leftVar.used() && leftVar.isThreadVolatile()) {
rcvr1 = ++curRcvrs2[Type.NULLREF];
rcvr2 = ++curRcvrs2[isString ? Type.NULLREF : exprType0
.objectSize()];
} else if (t0.isSafeWithThrow() ? !t2.isSafeExpr()
&& (!t0.isSafeExpr() || (sym != LexTerm.EQUALS
&& !t2.isSafeWithThrow() && (t0
.isFieldAccessed(null) || t2
.isAnyLocalVarChanged(t0)))) : !t2.isImmutable()) {
rcvr1 = ++curRcvrs2[Type.NULLREF];
int s0;
if (sym != LexTerm.EQUALS && !t2.isSafeWithThrow()) {
rcvr2 = ++curRcvrs2[(s0 = exprType0.objectSize()) < Type.VOID ? s0
: Type.NULLREF];
}
} else if ((isString || sym == LexTerm.DIVIDE_EQUALS
|| sym == LexTerm.MOD_EQUALS
|| sym == LexTerm.FLSHIFT_EQUALS
|| sym == LexTerm.SHRIGHT_EQUALS
|| sym == LexTerm.SHLEFT_EQUALS || (sym != LexTerm.EQUALS
&& (s2 = exprType2.objectSize()) >= Type.FLOAT && exprType0
.objectSize() < s2))
&& (!t0.isSafeExpr() || (!t2.isSafeWithThrow() && (t0
.isFieldAccessed(null) || t2
.isAnyLocalVarChanged(t0))))) {
rcvr1 = ++curRcvrs2[Type.NULLREF];
}
}
t2.allocRcvr(curRcvrs2);
OutputContext.joinRcvrs(curRcvrs, curRcvrs2);
}
ExpressionType exprType() {
assertCond(exprType0 != null);
return exprType0;
}
ExpressionType actualExprType() {
assertCond(exprType0 != null);
return actualType2;
}
boolean isNotNull() {
return isString || terms[2].isNotNull();
}
VariableDefinition getVariable(boolean allowInstance) {
return terms[1].getSym() == LexTerm.EQUALS ? terms[0]
.getVariable(allowInstance) : null;
}
boolean isBoolAssign() {
assertCond(exprType0 != null);
return terms[1].getSym() == LexTerm.EQUALS
&& exprType0.objectSize() == Type.BOOLEAN;
}
boolean isSwitchMapAssign(boolean isMethodCall) {
assertCond(exprType0 != null);
if (isMethodCall || terms[1].getSym() != LexTerm.EQUALS
|| exprType0.objectSize() != Type.INT)
return false;
Term t1 = terms[0].getArgumentTerm(1);
if (t1 == null)
return false;
VariableDefinition v = terms[0].getArgumentTerm(0).getVariable(false);
return v != null && v.isClassVariable() && v.isFinalVariable()
&& v.id().startsWith("$SwitchMap$")
&& terms[2].evaluateConstValue() != null
&& t1.isSwitchMapAssign(true);
}
String strLiteralValueGuess() {
if (isString) {
String str0 = terms[0].strLiteralValueGuess();
String str2 = terms[2].strLiteralValueGuess();
return str0 != null ? (str2 != null ? str0 + str2 : str0) : str2;
}
return terms[1].getSym() == LexTerm.EQUALS ? terms[2]
.strLiteralValueGuess() : null;
}
ExpressionType classLiteralValGuess() {
return terms[1].getSym() == LexTerm.EQUALS ? terms[2]
.classLiteralValGuess() : null;
}
boolean storeClassLiteralsGuess(ObjVector parmSig, boolean isActual) {
return terms[1].getSym() == LexTerm.EQUALS
&& terms[2].storeClassLiteralsGuess(parmSig, isActual);
}
MethodInvocation getClassNewInstanceCall() {
return terms[1].getSym() == LexTerm.EQUALS ? terms[2]
.getClassNewInstanceCall() : null;
}
MethodSignature getConstructorInstanceSign() {
return terms[1].getSym() == LexTerm.EQUALS ? terms[2]
.getConstructorInstanceSign() : null;
}
void discoverObjLeaks() {
terms[0].discoverObjLeaks();
terms[2].discoverObjLeaks();
if (isString
|| (terms[1].getSym() == LexTerm.EQUALS && exprType2
.objectSize() >= Type.CLASSINTERFACE)) {
terms[2].setObjLeaks(terms[0].getVariable(false));
}
}
void setStackObjVolatile() {
if (isString) {
terms[0].setStackObjVolatile();
}
terms[2].setStackObjVolatile();
}
void setObjLeaks(VariableDefinition v) {
if (isString) {
terms[0].setObjLeaks(v);
}
terms[2].setObjLeaks(v);
}
boolean isAtomary() {
return (rcvr1 | rcvr2 | rcvr3) > 0;
}
void setVoidExpression() {
isVoidExpr = true;
}
private boolean isFinalFieldSetToZero() {
VariableDefinition v = terms[0].getVariable(false);
ConstValue constVal2;
return v != null
&& (!v.used() || (v.isFinalVariable() && !v.isLocalOrParam()
&& (constVal2 = terms[2].evaluateConstValue()) != null && !constVal2
.isNonZero()));
}
void processOutput(OutputContext oc) {
int sym = terms[1].getSym();
int s0 = exprType0.objectSize();
int s2 = exprType2.objectSize();
String cname = exprType0.castName();
String rcvrStr1 = null;
String rcvrStr2 = null;
String rcvrStr3 = null;
Term t0 = terms[0];
Term t1 = t0.getArgumentTerm(1);
VariableDefinition leftVar = null;
boolean isVolatile = false;
if (t1 != null) {
t0 = t0.getArgumentTerm(0);
} else if ((leftVar = t0.getVariable(true)) != null && leftVar.used()) {
isVolatile = leftVar.isThreadVolatile();
}
Term t2 = terms[2];
ExpressionType oldAssignmentRightType = oc.assignmentRightType;
oc.assignmentRightType = null;
if ((rcvr1 | rcvr2 | rcvr3) > 0) {
oc.cPrint("(");
if (t1 != null) {
rcvrStr1 = rcvr1 > 0 ? OutputContext.getRcvrName(rcvr1,
Type.CLASSINTERFACE) : rcvr2 > 0 ? OutputContext
.getRcvrName(rcvr2,
sym != LexTerm.EQUALS ? Type.CLASSINTERFACE
: Type.INT) : OutputContext
.getRcvrName(rcvr3, s0);
if ((rcvr1 > 0 && (rcvr2 | rcvr3) > 0)
|| (rcvr2 > 0 && rcvr3 > 0)) {
rcvrStr2 = rcvr1 > 0 && rcvr2 > 0 ? OutputContext
.getRcvrName(rcvr2,
sym != LexTerm.EQUALS ? Type.CLASSINTERFACE
: Type.INT) : OutputContext
.getRcvrName(rcvr3, s0);
if (rcvr1 > 0 && rcvr2 > 0 && rcvr3 > 0) {
rcvrStr3 = OutputContext.getRcvrName(rcvr3, s0);
}
}
if (rcvr1 > 0 || sym == LexTerm.EQUALS) {
oc.cPrint(rcvrStr1);
oc.cPrint("= ");
if (rcvr1 > 0) {
oc.cPrint("(");
oc.cPrint(Type.cName[Type.CLASSINTERFACE]);
oc.cPrint(")");
t0.processOutput(oc);
} else if (rcvr2 > 0) {
t1.processOutput(oc);
} else if (s2 >= Type.FLOAT && s0 < s2
&& s0 <= Type.FLOAT) {
if (s0 < Type.INT) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0]);
oc.cPrint(")");
}
CastExpression.outputFloatCast(oc, s0, s2);
t2.processOutput(oc);
oc.cPrint(")");
} else {
if (s0 >= Type.CLASSINTERFACE || s0 < s2
|| (s0 >= Type.LONG && s0 > s2)) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 < Type.CLASSINTERFACE ? s0
: Type.CLASSINTERFACE]);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
t2.processOutput(oc);
}
}
oc.cPrint(", ");
}
if ((rcvr2 | rcvr3) > 0) {
if (sym != LexTerm.EQUALS) {
if (rcvr2 > 0 && rcvr3 > 0) {
oc.cPrint(rcvr1 > 0 ? rcvrStr3 : rcvrStr2);
oc.cPrint("= *(");
oc.cPrint(Type.cName[s0]);
oc.cPrint("*)(");
}
oc.cPrint(rcvr1 > 0 ? rcvrStr2 : rcvrStr1);
oc.cPrint("= (void*)&");
boolean forceCheck = ArrayAccess.outputArrAccess(oc,
forceVmExc, s0, t0);
if (rcvr1 > 0) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 >= Type.CLASSINTERFACE ? Type.OBJECTARRAY
: s0 + Type.CLASSINTERFACE]);
oc.cPrint(")");
oc.cPrint(rcvrStr1);
} else {
t0.processOutput(oc);
}
oc.cPrint(", ");
t1.processOutput(oc);
oc.cPrint(")");
if (forceCheck) {
oc.cPrint("[0]");
}
if (rcvr2 > 0 && rcvr3 > 0) {
oc.cPrint(")");
}
oc.cPrint(", ");
} else if (rcvr1 > 0 || (rcvr2 > 0 && rcvr3 > 0)) {
oc.cPrint(rcvrStr2);
oc.cPrint("= ");
if (rcvr1 > 0 && rcvr2 > 0) {
t1.processOutput(oc);
if (rcvr3 > 0) {
oc.cPrint(", ");
oc.cPrint(rcvrStr3);
oc.cPrint("= ");
}
}
if (rcvr3 > 0) {
if (s2 >= Type.FLOAT && s0 < s2
&& s0 <= Type.FLOAT) {
if (s0 < Type.INT) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0]);
oc.cPrint(")");
}
CastExpression.outputFloatCast(oc, s0, s2);
t2.processOutput(oc);
oc.cPrint(")");
} else if (s0 >= Type.CLASSINTERFACE || s0 < s2
|| (s0 >= Type.LONG && s0 > s2)) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 < Type.CLASSINTERFACE ? s0
: Type.CLASSINTERFACE]);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
t2.processOutput(oc);
}
}
oc.cPrint(", ");
}
}
} else {
rcvrStr1 = OutputContext
.getRcvrName(rcvr1, Type.CLASSINTERFACE);
if (rcvr2 > 0) {
rcvrStr2 = OutputContext.getRcvrName(rcvr2, s0);
oc.cPrint(rcvrStr2);
oc.cPrint("= ");
if (isVolatile) {
if (s0 >= Type.CLASSINTERFACE) {
oc.cPrint("JCGO_VLT_LFETCH(");
oc.cPrint(Type.cName[Type.CLASSINTERFACE]);
oc.cPrint(", ");
oc.cPrint("((");
oc.cPrint(Type.cName[Type.CLASSINTERFACE]);
oc.cPrint(" JCGO_THRD_VOLATILE");
} else {
oc.cPrint("JCGO_VLT_FETCH");
oc.cPrint(Type.sig[s0]);
oc.cPrint("(((JCGO_THRD_VOLATILE ");
oc.cPrint(cname);
}
} else {
oc.cPrint("*(");
oc.cPrint(Type.cName[s0 < Type.CLASSINTERFACE ? s0
: Type.CLASSINTERFACE]);
}
oc.cPrint("*)(");
}
oc.cPrint(rcvrStr1);
oc.cPrint("= (void*)&");
t0.atomaryOutput(oc);
if (rcvr2 > 0) {
oc.cPrint(")");
if (isVolatile) {
oc.cPrint(")[0])");
}
}
oc.cPrint(", ");
}
}
VariableDefinition oldAssignmentVar = oc.assignmentVar;
oc.assignmentVar = leftVar;
if (oldAssignmentVar != oc.assignmentVar
&& oldAssignmentRightType != null) {
oc.assignmentVar = null;
}
ExpressionType assignRightType = oldAssignmentRightType == exprType0
|| oldAssignmentRightType == null ? exprType0
: Main.dict.classTable[Type.VOID];
if (sym == LexTerm.EQUALS) {
if (t1 == null) {
boolean castToVoid = false;
if (isVolatile) {
if (s0 >= Type.CLASSINTERFACE) {
oc.cPrint("JCGO_VLT_LSTORE(");
oc.cPrint(isVoidExpr ? Type.cName[Type.VOID] : cname);
oc.cPrint(", ");
} else {
oc.cPrint("JCGO_VLT_STORE");
oc.cPrint(Type.sig[s0]);
oc.cPrint("((");
if (rcvr1 > 0) {
oc.cPrint("JCGO_THRD_VOLATILE ");
oc.cPrint(cname);
oc.cPrint("*)");
}
}
if (rcvr1 > 0) {
oc.cPrint(rcvrStr1);
} else {
oc.cPrint("&");
t0.processOutput(oc);
if (s0 < Type.CLASSINTERFACE) {
oc.cPrint(")");
}
}
oc.cPrint(", ");
} else if (rcvr1 > 0) {
oc.cPrint("*(");
oc.cPrint(cname);
oc.cPrint("*)");
oc.cPrint(rcvrStr1);
oc.cPrint("= ");
} else {
castToVoid = isVoidExpr;
if (!isFinalFieldSetToZero()) {
t0.processOutput(oc);
castToVoid = false;
oc.cPrint("= ");
}
}
if (castToVoid) {
assertCond(!isVolatile);
oc.cPrint("(");
oc.cPrint(Type.cName[Type.VOID]);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
oc.assignmentRightType = assignRightType;
if (s0 == Type.BOOLEAN
|| (exprType0 != exprType2 && (!isVolatile || s0 < Type.CLASSINTERFACE))) {
oc.cPrint("(");
oc.cPrint(exprType0.castName());
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
t2.processOutput(oc);
}
if (isVolatile) {
oc.cPrint(")");
}
}
} else if (exprType2.objectSize() >= Type.CLASSINTERFACE
&& exprType0.signatureClass()
.hasInstantatedSubclasses(true)) {
boolean forceCheck = false;
boolean isNotNull0;
if ((forceVmExc & (ClassDefinition.ARR_STORE_EXC | ClassDefinition.INDEX_OUT_EXC)) != 0
|| (!(isNotNull0 = t0.isNotNull()) && (forceVmExc & ClassDefinition.NULL_PTR_EXC) != 0)) {
if (!isVoidExpr) {
oc.cPrint("(");
oc.cPrint(cname);
oc.cPrint(")");
}
oc.cPrint("jcgo_objArraySet(");
forceCheck = true;
} else {
oc.cPrint(isNotNull0 ? "JCGO_ARRAY_NZOBJSET("
: "JCGO_ARRAY_OBJSET(");
oc.cPrint(isVoidExpr ? Type.cName[Type.VOID] : cname);
oc.cPrint(", ");
}
if (rcvr1 > 0) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 >= Type.CLASSINTERFACE ? Type.OBJECTARRAY
: s0 + Type.CLASSINTERFACE]);
oc.cPrint(")");
oc.cPrint(rcvrStr1);
} else {
t0.processOutput(oc);
}
oc.cPrint(", ");
if (rcvr2 > 0) {
oc.cPrint(rcvr1 > 0 ? rcvrStr2 : rcvrStr1);
} else {
t1.processOutput(oc);
}
oc.cPrint(", ");
if (rcvr3 > 0) {
oc.cPrint(rcvr1 > 0 && rcvr2 > 0 ? rcvrStr3
: (rcvr1 | rcvr2) > 0 ? rcvrStr2 : rcvrStr1);
} else {
oc.assignmentRightType = assignRightType;
if (forceCheck) {
oc.cPrint("(");
oc.cPrint(Type.cName[Type.CLASSINTERFACE]);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
t2.processOutput(oc);
}
}
oc.cPrint(")");
} else {
if (s0 >= Type.CLASSINTERFACE) {
oc.cPrint("*(");
oc.cPrint(cname);
oc.cPrint("*)&");
}
boolean forceCheck = ArrayAccess.outputArrAccess(oc,
forceVmExc, s0, t0);
if (rcvr1 > 0) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 >= Type.CLASSINTERFACE ? Type.OBJECTARRAY
: s0 + Type.CLASSINTERFACE]);
oc.cPrint(")");
oc.cPrint(rcvrStr1);
} else {
t0.processOutput(oc);
}
oc.cPrint(", ");
if (rcvr2 > 0) {
oc.cPrint(rcvr1 > 0 ? rcvrStr2 : rcvrStr1);
} else {
t1.processOutput(oc);
}
oc.cPrint(")");
if (forceCheck) {
oc.cPrint("[0]");
}
oc.cPrint("= ");
if (rcvr3 > 0 ? s0 >= Type.CLASSINTERFACE : s0 == Type.BOOLEAN
|| exprType0 != exprType2) {
oc.cPrint("(");
oc.cPrint(exprType0.castName());
oc.cPrint(")");
}
if (rcvr3 > 0) {
oc.cPrint(rcvr1 > 0 && rcvr2 > 0 ? rcvrStr3
: (rcvr1 | rcvr2) > 0 ? rcvrStr2 : rcvrStr1);
} else {
oc.assignmentRightType = assignRightType;
t2.atomaryOutput(oc);
}
}
} else {
if (isString || (s2 >= Type.FLOAT && s0 < s2 && s0 <= Type.FLOAT)
|| sym == LexTerm.DIVIDE_EQUALS
|| sym == LexTerm.MOD_EQUALS
|| sym == LexTerm.FLSHIFT_EQUALS
|| sym == LexTerm.SHRIGHT_EQUALS
|| sym == LexTerm.SHLEFT_EQUALS) {
if ((rcvr1 | rcvr2 | rcvr3) > 0) {
if (isVolatile) {
if (isString) {
oc.cPrint("JCGO_VLT_LSTORE(");
oc.cPrint(isVoidExpr ? Type.cName[Type.VOID]
: cname);
oc.cPrint(", ");
} else {
oc.cPrint("JCGO_VLT_STORE");
oc.cPrint(Type.sig[s0]);
oc.cPrint("((JCGO_THRD_VOLATILE ");
oc.cPrint(cname);
oc.cPrint("*)");
}
} else {
oc.cPrint("*(");
oc.cPrint(cname);
oc.cPrint("*)");
}
oc.cPrint(t1 == null || rcvr1 == 0 || rcvr2 == 0 ? rcvrStr1
: rcvrStr2);
} else {
assertCond(!isVolatile);
rcvrStr1 = t0.stringOutput();
oc.cPrint(rcvrStr1);
}
oc.cPrint(isVolatile ? ", " : "= ");
if (isString) {
MethodDefinition md = Main.dict.get(
Names.JAVA_LANG_VMSYSTEM).getMethod(
Names.SIGN_CONCAT0X);
oc.cPrint(md != null ? md.routineCName()
: MethodDefinition.UNKNOWN_NAME);
oc.cPrint("(\010 (");
oc.cPrint(Main.dict.get(Names.JAVA_LANG_STRING).castName());
oc.cPrint(")");
Main.dict.normalCalls++;
} else {
if (s0 < Type.INT || s0 < s2) {
if (s0 < Type.INT
|| (s2 == Type.LONG && (sym == LexTerm.DIVIDE_EQUALS || sym == LexTerm.MOD_EQUALS))) {
oc.cPrint("(");
oc.cPrint(cname);
oc.cPrint(")");
}
if (s2 >= Type.FLOAT) {
CastExpression.outputFloatCast(oc, s0, s2);
}
}
if (sym != LexTerm.MINUS_EQUALS
&& sym != LexTerm.PLUS_EQUALS
&& sym != LexTerm.TIMES_EQUALS) {
BinaryOp.outputDivShift(
oc,
sym == LexTerm.DIVIDE_EQUALS ? LexTerm.DIVIDE
: sym == LexTerm.MOD_EQUALS ? LexTerm.MOD
: sym == LexTerm.FLSHIFT_EQUALS ? LexTerm.FILLSHIFT_RIGHT
: sym == LexTerm.SHLEFT_EQUALS ? LexTerm.SHIFT_LEFT
: LexTerm.SHIFT_RIGHT,
s0 >= s2
|| (sym != LexTerm.DIVIDE_EQUALS && sym != LexTerm.MOD_EQUALS) ? s0
: s2);
}
if (s2 >= Type.LONG && s0 < s2
&& sym != LexTerm.FLSHIFT_EQUALS
&& sym != LexTerm.SHRIGHT_EQUALS
&& sym != LexTerm.SHLEFT_EQUALS) {
oc.cPrint("(");
oc.cPrint(Type.cName[s2]);
oc.cPrint(")");
}
}
if (rcvr2 > 0 && (t1 == null || rcvr3 > 0)) {
oc.cPrint(rcvr1 == 0 || rcvr3 == 0 ? rcvrStr2 : rcvrStr3);
} else {
if ((rcvr1 | rcvr2 | rcvr3) > 0) {
oc.cPrint("*(");
oc.cPrint(isString ? Type.cName[Type.CLASSINTERFACE]
: cname);
oc.cPrint("*)");
}
oc.cPrint((rcvr1 > 0 && rcvr2 > 0) || rcvr3 > 0 ? rcvrStr2
: rcvrStr1);
}
oc.assignmentRightType = assignRightType;
if (isString) {
oc.cPrint(", ");
t2.processOutput(oc);
} else {
oc.cPrint(sym == LexTerm.MINUS_EQUALS ? "- "
: sym == LexTerm.PLUS_EQUALS ? "+ "
: sym == LexTerm.TIMES_EQUALS ? "* " : ", ");
if (sym == LexTerm.FLSHIFT_EQUALS
|| sym == LexTerm.SHRIGHT_EQUALS
|| sym == LexTerm.SHLEFT_EQUALS) {
if (exprType2.objectSize() == Type.LONG) {
oc.cPrint("(");
oc.cPrint(Type.cName[Type.INT]);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else {
t2.processOutput(oc);
}
} else {
if (s0 >= Type.LONG && s0 > s2) {
oc.cPrint("(");
oc.cPrint(cname);
oc.cPrint(")");
t2.atomaryOutput(oc);
} else if (sym == LexTerm.DIVIDE_EQUALS
|| sym == LexTerm.MOD_EQUALS) {
t2.processOutput(oc);
} else {
t2.atomaryOutput(oc);
}
}
}
oc.cPrint(")");
if (!isString
&& s2 >= Type.FLOAT
&& s0 < s2
&& (sym == LexTerm.DIVIDE_EQUALS || sym == LexTerm.MOD_EQUALS)) {
oc.cPrint(")");
}
} else {
if (t1 == null && rcvr1 == 0) {
assertCond(!isVolatile);
t0.processOutput(oc);
} else if (t1 != null && (rcvr2 | rcvr3) == 0) {
assertCond(!isVolatile);
boolean forceCheck = ArrayAccess.outputArrAccess(oc,
forceVmExc, s0, t0);
if ((rcvr1 | rcvr2 | rcvr3) > 0) {
oc.cPrint("(");
oc.cPrint(Type.cName[s0 >= Type.CLASSINTERFACE ? Type.OBJECTARRAY
: s0 + Type.CLASSINTERFACE]);
oc.cPrint(")");
oc.cPrint(rcvrStr1);
} else {
t0.processOutput(oc);
}
oc.cPrint(", ");
t1.processOutput(oc);
oc.cPrint(")");
if (forceCheck) {
oc.cPrint("[0]");
}
} else {
if (isVolatile) {
oc.cPrint("JCGO_VLT_STORE");
oc.cPrint(Type.sig[s0]);
oc.cPrint("((JCGO_THRD_VOLATILE ");
} else {
oc.cPrint("*(");
}
oc.cPrint(cname);
oc.cPrint("*)");
oc.cPrint(t1 == null || rcvr1 == 0 || rcvr2 == 0 ? rcvrStr1
: rcvrStr2);
}
if (rcvr2 > 0 && (t1 == null || rcvr3 > 0)) {
oc.cPrint(isVolatile ? ", " : "= ");
if (s0 < Type.INT) {
oc.cPrint("(");
oc.cPrint(cname);
oc.cPrint(")(");
}
oc.cPrint(rcvr1 > 0 && rcvr3 > 0 ? rcvrStr3 : rcvrStr2);
if (sym == LexTerm.XOR_EQUALS) {
oc.cPrint("^");
} else if (sym == LexTerm.BITOR_EQUALS) {
oc.cPrint("|");
} else if (sym == LexTerm.BITAND_EQUALS) {
oc.cPrint("&");
} else if (sym == LexTerm.MINUS_EQUALS) {
oc.cPrint("-");
} else if (sym == LexTerm.PLUS_EQUALS) {
oc.cPrint("+");
} else if (sym == LexTerm.TIMES_EQUALS) {
oc.cPrint("*");
}
} else {
assertCond(!isVolatile);
terms[1].processOutput(oc);
}
oc.cPrint(" ");
oc.assignmentRightType = assignRightType;
if (s0 == Type.BOOLEAN || exprType0 != exprType2) {
oc.cPrint("(");
oc.cPrint(cname);
oc.cPrint(")");
t2.atomaryOutput(oc);
if (s0 < Type.INT && rcvr2 > 0 && (t1 == null || rcvr3 > 0)) {
oc.cPrint(")");
}
} else if (rcvr2 > 0 && (t1 == null || rcvr3 > 0)) {
t2.atomaryOutput(oc);
if (s0 < Type.INT) {
oc.cPrint(")");
}
} else {
t2.processOutput(oc);
}
}
if (isVolatile) {
oc.cPrint(")");
}
}
oc.assignmentVar = oldAssignmentVar;
oc.assignmentRightType = oldAssignmentRightType;
if ((rcvr1 | rcvr2 | rcvr3) > 0) {
oc.cPrint(")");
}
}
ExpressionType traceClassInit() {
terms[0].traceClassInit();
ExpressionType curTraceType2 = terms[2].traceClassInit();
if (isString) {
MethodDefinition md = Main.dict.get(Names.JAVA_LANG_VMSYSTEM)
.getMethod(Names.SIGN_CONCAT0X);
if (md != null) {
md.methodTraceClassInit(false, null, null);
}
return null;
}
if (terms[1].getSym() != LexTerm.EQUALS
|| exprType0.objectSize() < Type.CLASSINTERFACE)
return null;
VariableDefinition v = terms[0].getVariable(false);
if (v != null) {
v.setTraceExprType(curTraceType2 != null ? curTraceType2
: actualType2, false);
}
return curTraceType2;
}
}