Skip to content

Commit

Permalink
Fixes boxed compound assignment operators on array access expressions.
Browse files Browse the repository at this point in the history
	Change on 2015/07/07 by kstanger <kstanger@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=97671273
  • Loading branch information
kstanger committed Jul 7, 2015
1 parent 106fede commit fa3e6fa
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 93 deletions.
71 changes: 0 additions & 71 deletions jre_emul/Classes/J2ObjC_common.h
Expand Up @@ -388,75 +388,4 @@ __attribute__((always_inline)) inline unichar J2ObjCFpToUnichar(double d) {
return tmp > 0xFFFF || (tmp == 0 && d > 0) ? 0xFFFF : (unichar) tmp;
}

#define ADD_OP(a, b) a + b
#define MINUS_OP(a, b) a - b
#define TIMES_OP(a, b) a * b
#define DIVIDE_OP(a, b) a / b
#define REMAINDER_OP(a, b) a % b
#define FREMAINDER_OP(a, b) fmod(a, b)
#define BITAND_OP(a, b) a & b
#define BITOR_OP(a, b) a | b
#define BITXOR_OP(a, b) a ^ b
#define LSHIFT_32_OP(a, b) a << (b & 0x1f)
#define RSHIFT_32_OP(a, b) a >> (b & 0x1f)
#define LSHIFT_64_OP(a, b) a << (b & 0x3f)
#define RSHIFT_64_OP(a, b) a >> (b & 0x3f)

/*!
* Template for compound assign operators on boxed types.
*
* @define BOXED_COMPOUND_ASSIGN
* @param CNAME The capitalized name of the primitive type (eg. "Int").
* @param VALUE_METHOD The method on the boxed type that returns the value.
* @param TYPE The primitive type name (eg. "jint").
* @param BOXED_TYPE The boxed type name (eg. "JavaLangInteger").
* @param RTYPE The type of the right hand side of the assignment.
* @param OPNAME The name of the operator, used to construct the function name.
* @param OP A macro that takes two parameters and prints the operation.
* @param OP_LTYPE The cast type for the left hand side of the operation.
*/
#define BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, RTYPE, OPNAME, OP, OP_LTYPE) \
__attribute__((always_inline)) inline BOXED_TYPE *Boxed##OPNAME##Assign##CNAME( \
BOXED_TYPE **lhs, RTYPE rhs) { \
nil_chk(*lhs); \
return *lhs = BOXED_TYPE##_valueOfWith##CNAME##_( \
(TYPE)(OP((OP_LTYPE)[*lhs VALUE_METHOD], rhs))); \
} \
__attribute__((always_inline)) inline BOXED_TYPE *Boxed##OPNAME##AssignStrong##CNAME( \
BOXED_TYPE **lhs, RTYPE rhs) { \
nil_chk(*lhs); \
return JreStrongAssign(lhs, \
BOXED_TYPE##_valueOfWith##CNAME##_((TYPE)(OP((OP_LTYPE)[*lhs VALUE_METHOD], rhs)))); \
}

// This macros are used in the boxed primitive header files.
#define BOXED_COMPOUND_ASSIGN_ARITHMETIC(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Plus, ADD_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Minus, MINUS_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Times, TIMES_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Divide, DIVIDE_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_MOD(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Mod, REMAINDER_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_FPMOD(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Mod, FREMAINDER_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_BITWISE(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitAnd, BITAND_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitOr, BITOR_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitXor, BITXOR_OP, TYPE)
#define BOXED_SHIFT_ASSIGN_32(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, LShift, LSHIFT_32_OP, jint) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, RShift, RSHIFT_32_OP, jint) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, URShift, RSHIFT_32_OP, uint32_t)
#define BOXED_SHIFT_ASSIGN_64(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, LShift, LSHIFT_64_OP, jlong) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, RShift, RSHIFT_64_OP, jlong) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, URShift, RSHIFT_64_OP, uint64_t)

#endif // _J2OBJC_COMMON_H_
79 changes: 79 additions & 0 deletions jre_emul/Classes/J2ObjC_header.h
Expand Up @@ -30,6 +30,7 @@
return JreStrongAssign(value, TYPE##_valueOfWith##CNAME##_([*value VALUE_METHOD] OP 1)); \
} \
__attribute__((always_inline)) inline TYPE *BoxedPre##OPNAME##Array##CNAME(JreArrayRef ref) { \
nil_chk(*ref.pValue); \
return IOSObjectArray_SetRef( \
ref, TYPE##_valueOfWith##CNAME##_([*((TYPE **)ref.pValue) VALUE_METHOD] OP 1)); \
} \
Expand All @@ -46,6 +47,7 @@
return original; \
} \
__attribute__((always_inline)) inline TYPE *BoxedPost##OPNAME##Array##CNAME(JreArrayRef ref) { \
nil_chk(*ref.pValue); \
TYPE *original = *ref.pValue; \
IOSObjectArray_SetRef( \
ref, TYPE##_valueOfWith##CNAME##_([*((TYPE **)ref.pValue) VALUE_METHOD] OP 1)); \
Expand All @@ -65,4 +67,81 @@
BOXED_INC_AND_DEC_INNER(CNAME, VALUE_METHOD, TYPE, Incr, +) \
BOXED_INC_AND_DEC_INNER(CNAME, VALUE_METHOD, TYPE, Decr, -)

#define ADD_OP(a, b) a + b
#define MINUS_OP(a, b) a - b
#define TIMES_OP(a, b) a * b
#define DIVIDE_OP(a, b) a / b
#define REMAINDER_OP(a, b) a % b
#define FREMAINDER_OP(a, b) fmod(a, b)
#define BITAND_OP(a, b) a & b
#define BITOR_OP(a, b) a | b
#define BITXOR_OP(a, b) a ^ b
#define LSHIFT_32_OP(a, b) a << (b & 0x1f)
#define RSHIFT_32_OP(a, b) a >> (b & 0x1f)
#define LSHIFT_64_OP(a, b) a << (b & 0x3f)
#define RSHIFT_64_OP(a, b) a >> (b & 0x3f)

/*!
* Template for compound assign operators on boxed types.
*
* @define BOXED_COMPOUND_ASSIGN
* @param CNAME The capitalized name of the primitive type (eg. "Int").
* @param VALUE_METHOD The method on the boxed type that returns the value.
* @param TYPE The primitive type name (eg. "jint").
* @param BOXED_TYPE The boxed type name (eg. "JavaLangInteger").
* @param RTYPE The type of the right hand side of the assignment.
* @param OPNAME The name of the operator, used to construct the function name.
* @param OP A macro that takes two parameters and prints the operation.
* @param OP_LTYPE The cast type for the left hand side of the operation.
*/
#define BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, RTYPE, OPNAME, OP, OP_LTYPE) \
__attribute__((always_inline)) inline BOXED_TYPE *Boxed##OPNAME##Assign##CNAME( \
BOXED_TYPE **lhs, RTYPE rhs) { \
nil_chk(*lhs); \
return *lhs = BOXED_TYPE##_valueOfWith##CNAME##_( \
(TYPE)(OP((OP_LTYPE)[*lhs VALUE_METHOD], rhs))); \
} \
__attribute__((always_inline)) inline BOXED_TYPE *Boxed##OPNAME##AssignStrong##CNAME( \
BOXED_TYPE **lhs, RTYPE rhs) { \
nil_chk(*lhs); \
return JreStrongAssign(lhs, \
BOXED_TYPE##_valueOfWith##CNAME##_((TYPE)(OP((OP_LTYPE)[*lhs VALUE_METHOD], rhs)))); \
} \
__attribute__((always_inline)) inline BOXED_TYPE *Boxed##OPNAME##AssignArray##CNAME( \
JreArrayRef lhs, RTYPE rhs) { \
nil_chk(*lhs.pValue); \
return IOSObjectArray_SetRef(lhs, BOXED_TYPE##_valueOfWith##CNAME##_( \
(TYPE)(OP((OP_LTYPE)[*((BOXED_TYPE **)lhs.pValue) VALUE_METHOD], rhs)))); \
}

// This macros are used in the boxed primitive header files.
#define BOXED_COMPOUND_ASSIGN_ARITHMETIC(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Plus, ADD_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Minus, MINUS_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Times, TIMES_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Divide, DIVIDE_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_MOD(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Mod, REMAINDER_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_FPMOD(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, Mod, FREMAINDER_OP, TYPE)
#define BOXED_COMPOUND_ASSIGN_BITWISE(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitAnd, BITAND_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitOr, BITOR_OP, TYPE) \
BOXED_COMPOUND_ASSIGN(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, TYPE, BitXor, BITXOR_OP, TYPE)
#define BOXED_SHIFT_ASSIGN_32(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, LShift, LSHIFT_32_OP, jint) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, RShift, RSHIFT_32_OP, jint) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, URShift, RSHIFT_32_OP, uint32_t)
#define BOXED_SHIFT_ASSIGN_64(CNAME, VALUE_METHOD, TYPE, BOXED_TYPE) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, LShift, LSHIFT_64_OP, jlong) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, RShift, RSHIFT_64_OP, jlong) \
BOXED_COMPOUND_ASSIGN( \
CNAME, VALUE_METHOD, TYPE, BOXED_TYPE, jlong, URShift, RSHIFT_64_OP, uint64_t)

#endif // _J2OBJC_HEADER_H_
Expand Up @@ -150,20 +150,28 @@ private void rewriteBoxedAssignment(Assignment node) {
return;
}
ITypeBinding primitiveType = typeEnv.getPrimitiveType(type);
IVariableBinding var = TreeUtil.getVariableBinding(lhs);
assert var != null : "No variable binding for lhs of assignment.";
String funcName = "Boxed" + getAssignFunctionName(node.getOperator());
if (var.isField() && !BindingUtil.isWeakReference(var)) {
funcName += "Strong";
}
funcName += NameTable.capitalize(primitiveType.getName());
String funcName = "Boxed" + getAssignFunctionName(node.getOperator())
+ getOperatorFunctionModifier(lhs) + NameTable.capitalize(primitiveType.getName());
FunctionInvocation invocation = new FunctionInvocation(funcName, type, type, type);
invocation.getArguments().add(new PrefixExpression(
typeEnv.getPointerType(type), PrefixExpression.Operator.ADDRESS_OF, TreeUtil.remove(lhs)));
invocation.getArguments().add(unbox(rhs));
node.replaceWith(invocation);
}

private static String getOperatorFunctionModifier(Expression expr) {
IVariableBinding var = TreeUtil.getVariableBinding(expr);
if (var == null) {
assert TreeUtil.trimParentheses(expr) instanceof ArrayAccess
: "Expression cannot be resolved to a variable or array access.";
return "Array";
}
if (var.isField() && !BindingUtil.isWeakReference(var)) {
return "Strong";
}
return "";
}

private static String getAssignFunctionName(Assignment.Operator op) {
switch (op) {
case PLUS_ASSIGN:
Expand Down Expand Up @@ -366,17 +374,8 @@ private void rewriteBoxedPrefixOrPostfix(TreeNode node, Expression operand, Stri
if (!typeEnv.isBoxedPrimitive(type)) {
return;
}
IVariableBinding var = TreeUtil.getVariableBinding(operand);
if (var != null) {
if (var.isField() && !BindingUtil.isWeakReference(var)) {
funcName += "Strong";
}
} else {
assert TreeUtil.trimParentheses(operand) instanceof ArrayAccess
: "Operand cannot be resolved to a variable or array access.";
funcName += "Array";
}
funcName += NameTable.capitalize(typeEnv.getPrimitiveType(type).getName());
funcName += getOperatorFunctionModifier(operand)
+ NameTable.capitalize(typeEnv.getPrimitiveType(type).getName());
FunctionInvocation invocation = new FunctionInvocation(funcName, type, type, type);
invocation.getArguments().add(new PrefixExpression(
typeEnv.getPointerType(type), PrefixExpression.Operator.ADDRESS_OF,
Expand Down
Expand Up @@ -458,15 +458,14 @@ public void testNonWrapperObjectTypeCastToPrimitive() throws IOException {
}

public void testBoxedOperators() throws IOException {
// TODO(kstanger): Fix compound assign on array access.
String translation = translateSourceFile(
"class Test { Integer si; Long sl; Float sf; Double sd;"
+ " Integer[] ai; Long[] al; Float[] af; Double ad;"
+ " Integer[] ai; Long[] al; Float[] af; Double[] ad;"
+ " void test(Integer wi, Long wl, Float wf, Double wd) {"
+ " si++; wi++; ++sl; ++wl; sf--; wf--; --sd; --wd;"
+ " si += 5; wi += 5; sl &= 6l; wl &= 6l;"
+ " si <<= 2; wi <<= 2; sl >>>= 3; wl >>>= 3;"
+ " ai[0]++; --al[1]; } }", "Test", "Test.m");
+ " ai[0]++; --al[1]; af[2] += 9; ad[3] -= 8; } }", "Test", "Test.m");
assertTranslatedLines(translation,
"BoxedPostIncrStrongInt(&si_);",
"BoxedPostIncrInt(&wi);",
Expand All @@ -485,6 +484,8 @@ public void testBoxedOperators() throws IOException {
"BoxedURShiftAssignStrongLong(&sl_, 3);",
"BoxedURShiftAssignLong(&wl, 3);",
"BoxedPostIncrArrayInt(IOSObjectArray_GetRef(nil_chk(ai_), 0));",
"BoxedPreDecrArrayLong(IOSObjectArray_GetRef(nil_chk(al_), 1));");
"BoxedPreDecrArrayLong(IOSObjectArray_GetRef(nil_chk(al_), 1));",
"BoxedPlusAssignArrayFloat(IOSObjectArray_GetRef(nil_chk(af_), 2), 9);",
"BoxedMinusAssignArrayDouble(IOSObjectArray_GetRef(nil_chk(ad_), 3), 8);");
}
}

0 comments on commit fa3e6fa

Please sign in to comment.