changeset 819:446263a8a30d

Fixed taking address of global static array element as constant expression.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 02 Dec 2008 01:07:22 +0100
parents e8f8cafcaa62
children bb4a81e68ddb
files gen/toir.cpp tests/mini/const2.d
diffstat 2 files changed, 65 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/gen/toir.cpp	Mon Dec 01 20:26:32 2008 +0100
+++ b/gen/toir.cpp	Tue Dec 02 01:07:22 2008 +0100
@@ -896,32 +896,71 @@
 
 LLConstant* AddrExp::toConstElem(IRState* p)
 {
-    assert(e1->op == TOKvar);
-    VarExp* vexp = (VarExp*)e1;
-
-    if (vexp->var->needThis())
+    // FIXME: this should probably be generalized more so we don't
+    // need to have a case for each thing we can take the address of
+
+    // address of global variable
+    if (e1->op == TOKvar)
     {
-        error("need 'this' to access %s", vexp->var->toChars());
-        fatal();
+        VarExp* vexp = (VarExp*)e1;
+
+        // make sure 'this' isn't needed
+        if (vexp->var->needThis())
+        {
+            error("need 'this' to access %s", vexp->var->toChars());
+            fatal();
+        }
+
+        // global variable
+        if (VarDeclaration* vd = vexp->var->isVarDeclaration())
+        {
+            LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
+            assert(llc);
+            return llc;
+        }
+        // static function
+        else if (FuncDeclaration* fd = vexp->var->isFuncDeclaration())
+        {
+            IrFunction* irfunc = fd->ir.irFunc;
+            assert(irfunc);
+            return irfunc->func;
+        }
+        // something else
+        else
+        {
+            // fail
+            goto Lerr;
+        }
     }
-
-    // global variable
-    if (VarDeclaration* vd = vexp->var->isVarDeclaration())
+    // address of indexExp
+    else if (e1->op == TOKindex)
     {
-        LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
-        assert(llc);
-        return llc;
-    }
-    // static function
-    else if (FuncDeclaration* fd = vexp->var->isFuncDeclaration())
-    {
-        IrFunction* irfunc = fd->ir.irFunc;
-        assert(irfunc);
-        return irfunc->func;
+        IndexExp* iexp = (IndexExp*)e1;
+
+        // indexee must be global static array var
+        assert(iexp->e1->op == TOKvar);
+        VarExp* vexp = (VarExp*)iexp->e1;
+        VarDeclaration* vd = vexp->var->isVarDeclaration();
+        assert(vd);
+        assert(vd->type->toBasetype()->ty == Tsarray);
+        assert(vd->ir.irGlobal);
+
+        // get index
+        LLConstant* index = iexp->e2->toConstElem(p);
+        assert(index->getType() == DtoSize_t());
+
+        // gep
+        LLConstant* idxs[2] = { DtoConstSize_t(0), index };
+        LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(isaConstant(vd->ir.irGlobal->value), idxs, 2);
+
+        // bitcast to requested type
+        assert(type->toBasetype()->ty == Tpointer);
+        return DtoBitCast(gep, DtoType(type));
     }
     // not yet supported
     else
     {
+    Lerr:
         error("constant expression '%s' not yet implemented", toChars());
         fatal();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/const2.d	Tue Dec 02 01:07:22 2008 +0100
@@ -0,0 +1,7 @@
+int[10] test;
+int* t = &test[3];
+
+void main()
+{
+    assert(t is &test[3]);
+}