summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-08-04 14:56:12 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-08-04 14:56:12 -0700
commit304176c90984efc0bda9d01ad07ea0c92af822bb (patch)
tree075d05182182a25950efd2b9c2f12cd87a007132
parent2b9a6ce08e765874c8114884a680103453d78091 (diff)
parentb61545096d2f55f76b22b7ef734e7cdb0c5eaf97 (diff)
downloadsystem_core-304176c90984efc0bda9d01ad07ea0c92af822bb.zip
system_core-304176c90984efc0bda9d01ad07ea0c92af822bb.tar.gz
system_core-304176c90984efc0bda9d01ad07ea0c92af822bb.tar.bz2
Merge change 20014
* changes: Implement arrays.
-rw-r--r--libacc/acc.cpp211
-rw-r--r--libacc/tests/data/array.c77
-rw-r--r--libacc/tests/test.py10
3 files changed, 262 insertions, 36 deletions
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 313bf1c..0a16489 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -139,16 +139,17 @@ class Compiler : public ErrorSink {
TY_VOID, // 3
TY_FLOAT, // 4
TY_DOUBLE, // 5
- TY_POINTER, // 6
- TY_ARRAY, // 7
- TY_STRUCT, // 8
- TY_FUNC, // 9
- TY_PARAM // 10
+ TY_POINTER, // 6
+ TY_ARRAY, // 7
+ TY_STRUCT, // 8
+ TY_FUNC, // 9
+ TY_PARAM // 10
};
struct Type {
TypeTag tag;
- tokenid_t id; // For function arguments (stores length for array)
+ tokenid_t id; // For function arguments, local vars
+ int length; // length of array
Type* pHead;
Type* pTail;
};
@@ -405,7 +406,16 @@ class Compiler : public ErrorSink {
/**
* Convert R0 to the given type.
*/
- virtual void convertR0(Type* pType) = 0;
+
+ void convertR0(Type* pType) {
+ convertR0Imp(pType, false);
+ }
+
+ void castR0(Type* pType) {
+ convertR0Imp(pType, true);
+ }
+
+ virtual void convertR0Imp(Type* pType, bool isCast) = 0;
/* Emit code to adjust the stack for a function call. Return the
* label for the address of the instruction that adjusts the
@@ -622,14 +632,40 @@ class Compiler : public ErrorSink {
return collapseType(getR0Type()->tag);
}
- bool isFloatType(Type* pType) {
+ static bool isFloatType(Type* pType) {
return isFloatTag(pType->tag);
}
- bool isFloatTag(TypeTag tag) {
+ static bool isFloatTag(TypeTag tag) {
return tag == TY_FLOAT || tag == TY_DOUBLE;
}
+ static bool isPointerType(Type* pType) {
+ return isPointerTag(pType->tag);
+ }
+
+ static bool isPointerTag(TypeTag tag) {
+ return tag == TY_POINTER || tag == TY_ARRAY;
+ }
+
+ Type* getPointerArithmeticResultType(Type* a, Type* b) {
+ TypeTag aTag = a->tag;
+ TypeTag bTag = b->tag;
+ if (aTag == TY_POINTER) {
+ return a;
+ }
+ if (bTag == TY_POINTER) {
+ return b;
+ }
+ if (aTag == TY_ARRAY) {
+ return a->pTail;
+ }
+ if (bTag == TY_ARRAY) {
+ return b->pTail;
+ }
+ return NULL;
+ }
+
Type* mkpInt;
private:
@@ -848,8 +884,8 @@ class Compiler : public ErrorSink {
bool isFloatTOS = isFloatTag(tagTOS);
if (!isFloatR0 && !isFloatTOS) {
setupIntPtrArgs();
- bool isPtrR0 = tagR0 == TY_POINTER;
- bool isPtrTOS = tagTOS == TY_POINTER;
+ bool isPtrR0 = isPointerTag(tagR0);
+ bool isPtrTOS = isPointerTag(tagTOS);
if (isPtrR0 || isPtrTOS) {
if (isPtrR0 && isPtrTOS) {
if (op != OP_MINUS) {
@@ -871,7 +907,8 @@ class Compiler : public ErrorSink {
if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
error("Unsupported pointer-scalar operation %d", op);
}
- Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
+ Type* pPtrType = getPointerArithmeticResultType(
+ pR0Type, pTOSType);
int size = sizeOf(pPtrType->pHead);
if (size != 1) {
// TODO: Optimize for power-of-two.
@@ -1131,7 +1168,8 @@ class Compiler : public ErrorSink {
virtual void loadR0FromR0() {
Type* pPointerType = getR0Type();
assert(pPointerType->tag == TY_POINTER);
- switch (pPointerType->pHead->tag) {
+ TypeTag tag = pPointerType->pHead->tag;
+ switch (tag) {
case TY_POINTER:
case TY_INT:
case TY_FLOAT:
@@ -1147,7 +1185,7 @@ class Compiler : public ErrorSink {
o4(0xE1C000D0); // ldrd r0, [r0]
break;
default:
- error("loadR0FromR0: unimplemented type");
+ error("loadR0FromR0: unimplemented type %d", tag);
break;
}
setR0Type(pPointerType->pHead);
@@ -1197,9 +1235,27 @@ class Compiler : public ErrorSink {
return result;
}
- virtual void convertR0(Type* pType){
+ virtual void convertR0Imp(Type* pType, bool isCast){
Type* pR0Type = getR0Type();
- if (bitsSame(pType, pR0Type)) {
+ if (isPointerType(pType) && isPointerType(pR0Type)) {
+ Type* pA = pR0Type;
+ Type* pB = pType;
+ // Array decays to pointer
+ if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) {
+ pA = pA->pTail;
+ }
+ if (typeEqual(pA, pB)) {
+ return; // OK
+ }
+ if (pB->pHead->tag == TY_VOID) {
+ return; // convert to void* is OK.
+ }
+ if (pA->tag == TY_POINTER && pB->tag == TY_POINTER
+ && isCast) {
+ return; // OK
+ }
+ error("Incompatible pointer or array types");
+ } else if (bitsSame(pType, pR0Type)) {
// do nothing special
} else {
TypeTag r0Tag = collapseType(pR0Type->tag);
@@ -1423,14 +1479,17 @@ class Compiler : public ErrorSink {
return 2;
case TY_CHAR:
return 1;
- default:
- return 0;
case TY_FLOAT:
return 4;
case TY_DOUBLE:
return 8;
case TY_POINTER:
return 4;
+ case TY_ARRAY:
+ return pType->length * sizeOf(pType->pHead);
+ default:
+ error("Unsupported type %d", pType->tag);
+ return 0;
}
}
@@ -1438,6 +1497,8 @@ class Compiler : public ErrorSink {
switch(pType->tag) {
case TY_DOUBLE:
return 8;
+ case TY_ARRAY:
+ return stackAlignmentOf(pType->pHead);
default:
return 4;
}
@@ -1447,6 +1508,11 @@ class Compiler : public ErrorSink {
switch(pType->tag) {
case TY_DOUBLE:
return 8;
+ case TY_ARRAY:
+ return sizeOf(pType);
+ case TY_FUNC:
+ error("stackSizeOf func not supported");
+ return 4;
default:
return 4;
}
@@ -1911,8 +1977,8 @@ class Compiler : public ErrorSink {
bool isFloatR0 = isFloatTag(tagR0);
bool isFloatTOS = isFloatTag(tagTOS);
if (!isFloatR0 && !isFloatTOS) {
- bool isPtrR0 = tagR0 == TY_POINTER;
- bool isPtrTOS = tagTOS == TY_POINTER;
+ bool isPtrR0 = isPointerTag(tagR0);
+ bool isPtrTOS = isPointerTag(tagTOS);
if (isPtrR0 || isPtrTOS) {
if (isPtrR0 && isPtrTOS) {
if (op != OP_MINUS) {
@@ -1936,7 +2002,8 @@ class Compiler : public ErrorSink {
if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) {
error("Unsupported pointer-scalar operation %d", op);
}
- Type* pPtrType = isPtrR0 ? pR0Type : pTOSType;
+ Type* pPtrType = getPointerArithmeticResultType(
+ pR0Type, pTOSType);
o(0x59); /* pop %ecx */
int size = sizeOf(pPtrType->pHead);
if (size != 1) {
@@ -2146,7 +2213,8 @@ class Compiler : public ErrorSink {
virtual void loadR0FromR0() {
Type* pPointerType = getR0Type();
assert(pPointerType->tag == TY_POINTER);
- switch (pPointerType->pHead->tag) {
+ TypeTag tag = pPointerType->pHead->tag;
+ switch (tag) {
case TY_POINTER:
case TY_INT:
o2(0x008b); /* mov (%eax), %eax */
@@ -2166,7 +2234,7 @@ class Compiler : public ErrorSink {
o2(0x00dd); // fldl (%eax)
break;
default:
- error("loadR0FromR0: unsupported type");
+ error("loadR0FromR0: unsupported type %d", tag);
break;
}
setR0Type(pPointerType->pHead);
@@ -2183,14 +2251,32 @@ class Compiler : public ErrorSink {
return getPC() - 4;
}
- virtual void convertR0(Type* pType){
+ virtual void convertR0Imp(Type* pType, bool isCast){
Type* pR0Type = getR0Type();
if (pR0Type == NULL) {
assert(false);
setR0Type(pType);
return;
}
- if (bitsSame(pType, pR0Type)) {
+ if (isPointerType(pType) && isPointerType(pR0Type)) {
+ Type* pA = pR0Type;
+ Type* pB = pType;
+ // Array decays to pointer
+ if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) {
+ pA = pA->pTail;
+ }
+ if (typeEqual(pA, pB)) {
+ return; // OK
+ }
+ if (pB->pHead->tag == TY_VOID) {
+ return; // convert to void* is OK.
+ }
+ if (pA->tag == TY_POINTER && pB->tag == TY_POINTER
+ && isCast) {
+ return; // OK
+ }
+ error("Incompatible pointer or array types");
+ } else if (bitsSame(pType, pR0Type)) {
// do nothing special
} else if (isFloatType(pType) && isFloatType(pR0Type)) {
// do nothing special, both held in same register on x87.
@@ -2326,6 +2412,11 @@ class Compiler : public ErrorSink {
return 1;
case TY_SHORT:
return 2;
+ case TY_ARRAY:
+ return alignmentOf(pType->pHead);
+ case TY_FUNC:
+ error("alignment of func not supported");
+ return 1;
default:
return 4;
}
@@ -2342,14 +2433,17 @@ class Compiler : public ErrorSink {
return 2;
case TY_CHAR:
return 1;
- default:
- return 0;
case TY_FLOAT:
return 4;
case TY_DOUBLE:
return 8;
case TY_POINTER:
return 4;
+ case TY_ARRAY:
+ return pType->length * sizeOf(pType->pHead);
+ default:
+ error("Unsupported type %d", pType->tag);
+ return 0;
}
}
@@ -2361,6 +2455,11 @@ class Compiler : public ErrorSink {
switch(pType->tag) {
case TY_DOUBLE:
return 8;
+ case TY_ARRAY:
+ return sizeOf(pType);
+ case TY_FUNC:
+ error("stackSizeOf func not supported");
+ return 4;
default:
return 4;
}
@@ -3911,7 +4010,7 @@ class Compiler : public ErrorSink {
skip(')');
unary();
pGen->forceR0RVal();
- pGen->convertR0(pCast);
+ pGen->castR0(pCast);
} else {
commaExpr();
skip(')');
@@ -3959,10 +4058,18 @@ class Compiler : public ErrorSink {
}
}
// load a variable
- Type* pVal = createPtrType(pVI->pType);
+ Type* pVal;
+ ExpressionType et;
+ if (pVI->pType->tag == TY_ARRAY) {
+ pVal = pVI->pType;
+ et = ET_RVALUE;
+ } else {
+ pVal = createPtrType(pVI->pType);
+ et = ET_LVALUE;
+ }
if (n) {
- ExpressionType et = ET_LVALUE;
- if (pVal->pHead->tag == TY_FUNC) {
+ int tag = pVal->pHead->tag;
+ if (tag == TY_FUNC) {
et = ET_RVALUE;
}
pGen->leaR0(n, pVal, et);
@@ -4251,6 +4358,8 @@ class Compiler : public ErrorSink {
}
if (at == TY_POINTER) {
return typeEqual(a->pHead, b->pHead);
+ } else if (at == TY_ARRAY) {
+ return a->length == b->length && typeEqual(a->pHead, b->pHead);
} else if (at == TY_FUNC || at == TY_PARAM) {
return typeEqual(a->pHead, b->pHead)
&& typeEqual(a->pTail, b->pTail);
@@ -4345,6 +4454,9 @@ class Compiler : public ErrorSink {
}
buffer.append('*');
break;
+ case TY_ARRAY:
+ decodeTypeImpPrefix(buffer, pType->pHead);
+ break;
case TY_FUNC:
decodeTypeImp(buffer, pType->pHead);
break;
@@ -4369,6 +4481,13 @@ class Compiler : public ErrorSink {
}
decodeTypeImpPostfix(buffer, pType->pHead);
break;
+ case TY_ARRAY:
+ {
+ String temp;
+ temp.printf("[%d]", pType->length);
+ buffer.append(temp);
+ }
+ break;
case TY_FUNC:
buffer.append('(');
for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) {
@@ -4418,9 +4537,13 @@ class Compiler : public ErrorSink {
nameRequired, reportFailure);
if (declName) {
// Clone the parent type so we can set a unique ID
+ Type* pOldType = pType;
pType = createType(pType->tag, pType->pHead, pType->pTail);
pType->id = declName;
+ pType->length = pOldType->length;
+ } else if (nameRequired) {
+ error("Expected a variable name");
}
// fprintf(stderr, "Parsed a declaration: ");
// printType(pType);
@@ -4490,11 +4613,27 @@ class Compiler : public ErrorSink {
error("Expected name. Got %s", temp.getUnwrapped());
reportFailure = true;
}
- while (accept('(')) {
- // Function declaration
- Type* pTail = acceptArgs(nameAllowed);
- pType = createType(TY_FUNC, pType, pTail);
- skip(')');
+ for(;;) {
+ if (accept('(')) {
+ // Function declaration
+ Type* pTail = acceptArgs(nameAllowed);
+ pType = createType(TY_FUNC, pType, pTail);
+ skip(')');
+ } if (accept('[')) {
+ if (tok != ']') {
+ if (tok != TOK_NUM || tokc <= 0) {
+ error("Expected positive integer constant");
+ } else {
+ Type* pDecayType = createPtrType(pType);
+ pType = createType(TY_ARRAY, pType, pDecayType);
+ pType->length = tokc;
+ }
+ next();
+ }
+ skip(']');
+ } else {
+ break;
+ }
}
if (pNewHead) {
diff --git a/libacc/tests/data/array.c b/libacc/tests/data/array.c
new file mode 100644
index 0000000..3af5e31
--- /dev/null
+++ b/libacc/tests/data/array.c
@@ -0,0 +1,77 @@
+// Array allocation tests
+
+void testLocalInt()
+{
+ int a[3];
+ a[0] = 1;
+ a[1] = 2;
+ a[2] = a[0] + a[1];
+ printf("localInt: %d\n", a[2]);
+}
+
+char a[3];
+double d[3];
+
+void testGlobalChar()
+{
+ a[0] = 1;
+ a[1] = 2;
+ a[2] = a[0] + a[1];
+ printf("globalChar: %d\n", a[2]);
+}
+
+void testGlobalDouble()
+{
+ d[0] = 1;
+ d[1] = 2;
+ d[2] = d[0] + d[1];
+ printf("globalDouble: %g\n", d[2]);
+}
+
+void testLocalDouble()
+{
+ double d[3];
+ float m[12];
+ m[0] = 1.0f;
+ m[1] = 2.0f;
+ d[0] = 1.0;
+ d[1] = 2.0;
+ d[2] = d[0] + d[1];
+ m[2] = m[0] + m[1];
+ printf("localDouble: %g %g\n", d[2], m[2]);
+}
+
+void vectorAdd(int* a, int* b, float* c, int len) {
+ int i;
+ for(i = 0; i < len; i++) {
+ c[i] = a[i] + b[i];
+ }
+}
+
+void testArgs() {
+ int a[3], b[3];
+ float c[3];
+ int i;
+ int len = 3;
+ for(i = 0; i < len; i++) {
+ a[i] = i;
+ b[i] = i;
+ c[i] = 0;
+ }
+ vectorAdd(a,b,c, len);
+ printf("testArgs:");
+ for(i = 0; i < len; i++) {
+ printf(" %g", c[i]);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ testLocalInt();
+ testLocalDouble();
+ testGlobalChar();
+ testGlobalDouble();
+ testArgs();
+ return 0;
+}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index a3114ad..4ad2e13 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -387,6 +387,16 @@ result: 0
result: -2
""","""""")
+ def testArray(self):
+ self.compileCheck(["-R", "data/array.c"], """Executing compiled code:
+localInt: 3
+localDouble: 3 3
+globalChar: 3
+globalDouble: 3
+testArgs: 0 2 4
+result: 0
+""","""""")
+
if __name__ == '__main__':
if not outputCanRun():
print "Many tests are expected to fail, because acc is not a 32-bit x86 Linux executable."