changeset 1350:15e9762bb620

Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Thu, 14 May 2009 13:26:40 +0200
parents a376776e2301
children 8d501abecd24
files gen/aa.cpp gen/abi-x86-64.cpp gen/abi.cpp gen/arrays.cpp gen/asmstmt.cpp gen/classes.cpp gen/functions.cpp gen/llvmhelpers.cpp gen/llvmhelpers.h gen/naked.cpp gen/nested.cpp gen/passes/GarbageCollect2Stack.cpp gen/statements.cpp gen/tocall.cpp gen/toir.cpp ir/irlandingpad.cpp
diffstat 16 files changed, 61 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/gen/aa.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/aa.cpp	Thu May 14 13:26:40 2009 +0200
@@ -33,7 +33,7 @@
         pkey = key->getRVal();
     }
     else {
-        LLValue* tmp = DtoAlloca(DtoType(keytype), "aatmpkeystorage");
+        LLValue* tmp = DtoAlloca(keytype, "aatmpkeystorage");
         DVarValue var(keytype, tmp);
         DtoAssign(loc, &var, key);
         return tmp;
@@ -41,7 +41,7 @@
 
     // give memory
     if (needmem) {
-        LLValue* tmp = DtoAlloca(DtoType(keytype), "aatmpkeystorage");
+        LLValue* tmp = DtoAlloca(keytype, "aatmpkeystorage");
         DtoStore(pkey, tmp);
         pkey = tmp;
     }
--- a/gen/abi-x86-64.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/abi-x86-64.cpp	Thu May 14 13:26:40 2009 +0200
@@ -455,7 +455,7 @@
         } else {
             // No memory location, create one.
             LLValue* rval = v->getRVal();
-            lval = DtoAlloca(rval->getType());
+            lval = DtoRawAlloca(rval->getType(), 0);
             DtoStore(rval, lval);
         }
         
@@ -479,7 +479,7 @@
         } else {
             // No memory location, create one.
             LLValue* rval = v->getRVal();
-            lval = DtoAlloca(rval->getType());
+            lval = DtoRawAlloca(rval->getType(), 0);
             DtoStore(rval, lval);
         }
         
--- a/gen/abi.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/abi.cpp	Thu May 14 13:26:40 2009 +0200
@@ -112,7 +112,7 @@
     LLValue* get(Type* dty, DValue* dv)
     {
         Logger::println("rewriting int -> struct");
-        LLValue* mem = DtoAlloca(DtoType(dty), ".int_to_struct");
+        LLValue* mem = DtoAlloca(dty, ".int_to_struct");
         LLValue* v = dv->getRVal();
         DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType())));
         return DtoLoad(mem);
--- a/gen/arrays.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/arrays.cpp	Thu May 14 13:26:40 2009 +0200
@@ -77,7 +77,7 @@
     // give slices and complex values storage (and thus an address to pass)
     if (value->isSlice())
     {
-        val = DtoAlloca(DtoType(value->getType()), ".tmpparam");
+        val = DtoAlloca(value->getType(), ".tmpparam");
         DVarValue lval(value->getType(), val);
         DtoAssign(loc, &lval, value);
     }
@@ -448,7 +448,7 @@
     LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname);
 
     // build dims
-    LLValue* dimsArg = DtoAlloca(DtoSize_t(), DtoConstUint(ndims), ".newdims");
+    LLValue* dimsArg = DtoArrayAlloca(Type::tsize_t, ndims, ".newdims");
     LLValue* firstDim = NULL; 
     for (size_t i=0; i<ndims; ++i)
     {
--- a/gen/asmstmt.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/asmstmt.cpp	Thu May 14 13:26:40 2009 +0200
@@ -600,7 +600,7 @@
             outSetterStmt->code += asmGotoEndLabel.str()+":\n";
 
             // create storage for and initialize the temporary
-            jump_target = DtoAlloca(LLType::Int32Ty, "__llvm_jump_target");
+            jump_target = DtoAlloca(Type::tint32, "__llvm_jump_target");
             gIR->ir->CreateStore(DtoConstUint(0), jump_target);
             // setup variable for output from asm
             outSetterStmt->out_c = "=*m,";
--- a/gen/classes.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/classes.cpp	Thu May 14 13:26:40 2009 +0200
@@ -129,7 +129,8 @@
     LLValue* mem;
     if (newexp->onstack)
     {
-        mem = DtoAlloca(DtoType(tc)->getContainedType(0), ".newclass_alloca");
+        // FIXME align scope class to its largest member
+        mem = DtoRawAlloca(DtoType(tc)->getContainedType(0), 0, ".newclass_alloca");
     }
     // custom allocator
     else if (newexp->allocator)
--- a/gen/functions.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/functions.cpp	Thu May 14 13:26:40 2009 +0200
@@ -683,6 +683,7 @@
     gIR->scopes.push_back(IRScope(beginbb, endbb));
 
     // create alloca point
+    // this gets erased when the function is complete, so alignment etc does not matter at all
     llvm::Instruction* allocaPoint = new llvm::AllocaInst(LLType::Int32Ty, "alloca point", beginbb);
     irfunction->allocapoint = allocaPoint;
 
@@ -704,7 +705,7 @@
         LLValue* thisvar = irfunction->thisArg;
         assert(thisvar);
 
-        LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
+        LLValue* thismem = DtoRawAlloca(thisvar->getType(), 0, "this"); // FIXME: align?
         DtoStore(thisvar, thismem);
         irfunction->thisArg = thismem;
         
@@ -760,7 +761,7 @@
                     argt = irloc->value->getType();
                 else
                     argt = DtoType(vd->type);
-                LLValue* mem = DtoAlloca(argt, vd->ident->toChars());
+                LLValue* mem = DtoRawAlloca(argt, 0, vd->ident->toChars());
 
                 // let the abi transform the argument back first
                 DImValue arg_dval(vd->type, irloc->value);
@@ -796,19 +797,19 @@
         DtoNestedInit(fd->vresult);
     } else if (fd->vresult) {
         fd->vresult->ir.irLocal = new IrLocal(fd->vresult);
-        fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), fd->vresult->toChars());
+        fd->vresult->ir.irLocal->value = DtoAlloca(fd->vresult->type, fd->vresult->toChars());
     }
     
     // copy _argptr and _arguments to a memory location
     if (f->linkage == LINKd && f->varargs == 1)
     {
         // _argptr
-        LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptr_mem");
+        LLValue* argptrmem = DtoRawAlloca(fd->ir.irFunc->_argptr->getType(), 0, "_argptr_mem");
         new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb());
         fd->ir.irFunc->_argptr = argptrmem;
 
         // _arguments
-        LLValue* argumentsmem = DtoAlloca(fd->ir.irFunc->_arguments->getType(), "_arguments_mem");
+        LLValue* argumentsmem = DtoRawAlloca(fd->ir.irFunc->_arguments->getType(), 0, "_arguments_mem");
         new llvm::StoreInst(fd->ir.irFunc->_arguments, argumentsmem, gIR->scopebb());
         fd->ir.irFunc->_arguments = argumentsmem;
     }
@@ -918,7 +919,7 @@
     // byval arg, but expr has no storage yet
     else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
     {
-        LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
+        LLValue* alloc = DtoAlloca(argexp->type, ".tmp_arg");
         DVarValue* vv = new DVarValue(argexp->type, alloc);
         DtoAssign(argexp->loc, vv, arg);
         arg = vv;
--- a/gen/llvmhelpers.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/llvmhelpers.cpp	Thu May 14 13:26:40 2009 +0200
@@ -95,14 +95,29 @@
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
 
-llvm::AllocaInst* DtoAlloca(const LLType* lltype, const std::string& name)
+llvm::AllocaInst* DtoAlloca(Type* type, const char* name)
 {
-    return new llvm::AllocaInst(lltype, name, gIR->topallocapoint());
+    const llvm::Type* lltype = DtoType(type);
+    llvm::AllocaInst* ai = new llvm::AllocaInst(lltype, name, gIR->topallocapoint());
+    ai->setAlignment(type->alignsize());
+    return ai;
 }
 
-llvm::AllocaInst* DtoAlloca(const LLType* lltype, LLValue* arraysize, const std::string& name)
+llvm::AllocaInst* DtoArrayAlloca(Type* type, unsigned arraysize, const char* name)
 {
-    return new llvm::AllocaInst(lltype, arraysize, name, gIR->topallocapoint());
+    const llvm::Type* lltype = DtoType(type);
+    llvm::AllocaInst* ai = new llvm::AllocaInst(
+        lltype, DtoConstUint(arraysize), name, gIR->topallocapoint());
+    ai->setAlignment(type->alignsize());
+    return ai;
+}
+
+llvm::AllocaInst* DtoRawAlloca(const llvm::Type* lltype, size_t alignment, const char* name)
+{
+    llvm::AllocaInst* ai = new llvm::AllocaInst(lltype, name, gIR->topallocapoint());
+    if (alignment)
+        ai->setAlignment(alignment);
+    return ai;
 }
 
 
@@ -894,7 +909,7 @@
                 if(gTargetData->getTypeSizeInBits(lltype) == 0) 
                     allocainst = llvm::ConstantPointerNull::get(getPtrToType(lltype));
                 else
-                    allocainst = DtoAlloca(lltype, vd->toChars());
+                    allocainst = DtoAlloca(vd->type, vd->toChars());
 
                 //allocainst->setAlignment(vd->type->alignsize()); // TODO
                 vd->ir.irLocal = new IrLocal(vd);
@@ -1010,7 +1025,7 @@
     LLValue* allocaval = NULL;
     if (!addr && (!var->ir.irLocal || !var->ir.irLocal->value))
     {
-        addr = DtoAlloca(DtoType(var->type), var->toChars());
+        addr = DtoAlloca(var->type, var->toChars());
         
         // add debug info
         if (global.params.symdebug)
--- a/gen/llvmhelpers.h	Wed May 13 18:08:40 2009 +0200
+++ b/gen/llvmhelpers.h	Thu May 14 13:26:40 2009 +0200
@@ -40,8 +40,9 @@
 void DtoDeleteArray(DValue* arr);
 
 // emit an alloca
-llvm::AllocaInst* DtoAlloca(const LLType* lltype, const std::string& name = "");
-llvm::AllocaInst* DtoAlloca(const LLType* lltype, LLValue* arraysize, const std::string& name = "");
+llvm::AllocaInst* DtoAlloca(Type* type, const char* name = "");
+llvm::AllocaInst* DtoArrayAlloca(Type* type, unsigned arraysize, const char* name = "");
+llvm::AllocaInst* DtoRawAlloca(const llvm::Type* lltype, size_t alignment, const char* name = "");
 
 // assertion generator
 void DtoAssert(Module* M, Loc loc, DValue* msg);
--- a/gen/naked.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/naked.cpp	Thu May 14 13:26:40 2009 +0200
@@ -258,7 +258,7 @@
 
             // generate asm
             as->out_c = "=*m,=*m,";
-            LLValue* tmp = DtoAlloca(llretTy, ".tmp_asm_ret");
+            LLValue* tmp = DtoRawAlloca(llretTy, 0, ".tmp_asm_ret");
             as->out.push_back( tmp );
             as->out.push_back( DtoGEPi(tmp, 0,1) );
             as->code = "movd %eax, $<<out0>>" "\n\t" "mov %edx, $<<out1>>";
@@ -413,7 +413,7 @@
     if (type->ty == Tstruct)
     {
         // make a copy
-        llvm::Value* mem = DtoAlloca(ret_type, ".__asm_tuple_ret");
+        llvm::Value* mem = DtoAlloca(type, ".__asm_tuple_ret");
 
         TypeStruct* ts = (TypeStruct*)type;
         size_t n = ts->sym->fields.dim;
--- a/gen/nested.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/nested.cpp	Thu May 14 13:26:40 2009 +0200
@@ -167,7 +167,7 @@
     if (nestedCtx == NCArray) {
         // alloca as usual if no value already
         if (!vd->ir.irLocal->value)
-            vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
+            vd->ir.irLocal->value = DtoAlloca(vd->type, vd->toChars());
         
         // store the address into the nested vars array
         assert(vd->ir.irLocal->nestedIndex >= 0);
@@ -324,7 +324,8 @@
             const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
         
             // alloca it
-            LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
+            // FIXME align ?
+            LLValue* nestedVars = DtoRawAlloca(nestedVarsTy, 0, ".nested_vars");
             
             IrFunction* irfunction = fd->ir.irFunc;
             
@@ -459,7 +460,8 @@
             // FIXME: For D2, this should be a gc_malloc (or similar) call, not alloca
             //        (Note that it'd also require more aggressive copying of
             //        by-value parameters instead of just alloca'd ones)
-            LLValue* frame = DtoAlloca(frameType, ".frame");
+            // FIXME: alignment ?
+            LLValue* frame = DtoRawAlloca(frameType, 0, ".frame");
             
             // copy parent frames into beginning
             if (depth != 0) {
--- a/gen/passes/GarbageCollect2Stack.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/passes/GarbageCollect2Stack.cpp	Thu May 14 13:26:40 2009 +0200
@@ -98,7 +98,7 @@
             NumGcToStack++;
             
             Instruction* Begin = CS.getCaller()->getEntryBlock().begin();
-            return new AllocaInst(Ty, ".nongc_mem", Begin);
+            return new AllocaInst(Ty, ".nongc_mem", Begin); // FIXME: align?
         }
         
         FunctionInfo(unsigned typeInfoArgNr, bool safeToDelete)
@@ -165,7 +165,7 @@
             
             // Convert array size to 32 bits if necessary
             Value* count = Builder.CreateIntCast(arrSize, Type::Int32Ty, false);
-            AllocaInst* alloca = Builder.CreateAlloca(Ty, count, ".nongc_mem");
+            AllocaInst* alloca = Builder.CreateAlloca(Ty, count, ".nongc_mem"); // FIXME: align?
             
             if (Initialized) {
                 // For now, only zero-init is supported.
--- a/gen/statements.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/statements.cpp	Thu May 14 13:26:40 2009 +0200
@@ -1025,7 +1025,7 @@
     if (key)
         keyvar = DtoRawVarDeclaration(key);
     else
-        keyvar = DtoAlloca(keytype, "foreachkey");
+        keyvar = DtoRawAlloca(keytype, 0, "foreachkey"); // FIXME: align?
     LLValue* zerokey = llvm::ConstantInt::get(keytype,0,false);
 
     // value
--- a/gen/tocall.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/tocall.cpp	Thu May 14 13:26:40 2009 +0200
@@ -169,7 +169,7 @@
     if (Logger::enabled())
         Logger::cout() << "d-variadic argument struct type:\n" << *vtype << '\n';
 
-    LLValue* mem = DtoAlloca(vtype,"_argptr_storage");
+    LLValue* mem = DtoRawAlloca(vtype, 0, "_argptr_storage");
 
     // store arguments in the struct
     for (int i=begin,k=0; i<n_arguments; i++,k++)
@@ -316,7 +316,7 @@
     // return in hidden ptr is first
     if (retinptr)
     {
-        LLValue* retvar = DtoAlloca(argiter->get()->getContainedType(0), ".rettmp");
+        LLValue* retvar = DtoRawAlloca(argiter->get()->getContainedType(0), 0, ".rettmp");
         ++argiter;
         args.push_back(retvar);
 
@@ -552,7 +552,7 @@
     // pointer to a struct, store it to a stack slot before continuing.
     if (tf->next->ty == Tstruct && !isaPointer(retllval)) {
         Logger::println("Storing return value to stack slot");
-        LLValue* mem = DtoAlloca(retllval->getType());
+        LLValue* mem = DtoRawAlloca(retllval->getType(), 0);
         DtoStore(retllval, mem);
         retllval = mem;
     }
--- a/gen/toir.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/gen/toir.cpp	Thu May 14 13:26:40 2009 +0200
@@ -909,7 +909,7 @@
     {
         assert(v->isSlice());
         LLValue* rval = v->getRVal();
-        lval = DtoAlloca(rval->getType(), ".tmp_slice_storage");
+        lval = DtoRawAlloca(rval->getType(), 0, ".tmp_slice_storage");
         DtoStore(rval, lval);
     }
 
@@ -2124,13 +2124,12 @@
     LOG_SCOPE;
 
     Type* dtype = type->toBasetype();
-    const LLType* resty = DtoType(dtype);
 
     DValue* dvv;
     // voids returns will need no storage
     if (dtype->ty != Tvoid) {
         // allocate a temporary for the final result. failed to come up with a better way :/
-        LLValue* resval = DtoAlloca(resty,"condtmp");
+        LLValue* resval = DtoAlloca(dtype,"condtmp");
         dvv = new DVarValue(type, resval);
     } else {
         dvv = new DConstValue(type, getNullValue(DtoTypeNotVoid(dtype)));
@@ -2345,7 +2344,7 @@
         dstMem = dynSlice->ptr;
     }
     else
-        dstMem = DtoAlloca(llStoType, "arrayliteral");
+        dstMem = DtoRawAlloca(llStoType, 0, "arrayliteral");
 
     // store elements
     for (size_t i=0; i<len; ++i)
@@ -2509,7 +2508,7 @@
     const LLType* st = llvm::StructType::get(valuetypes, packed);
 
     // alloca a stack slot
-    LLValue* mem = DtoAlloca(st, ".structliteral");
+    LLValue* mem = DtoRawAlloca(st, 0, ".structliteral");
 
     // fill in values
     for (size_t i = 0; i < n; i++)
@@ -2596,12 +2595,11 @@
 
     Type* aatype = type->toBasetype();
     Type* vtype = aatype->nextOf();
-    const LLType* aalltype = DtoType(type);
 
     // it should be possible to avoid the temporary in some cases
-    LLValue* tmp = DtoAlloca(aalltype,"aaliteral");
+    LLValue* tmp = DtoAlloca(type,"aaliteral");
     DValue* aa = new DVarValue(type, tmp);
-    DtoStore(LLConstant::getNullValue(aalltype), tmp);
+    DtoStore(LLConstant::getNullValue(DtoType(type)), tmp);
 
     const size_t n = keys->dim;
     for (size_t i=0; i<n; ++i)
--- a/ir/irlandingpad.cpp	Wed May 13 18:08:40 2009 +0200
+++ b/ir/irlandingpad.cpp	Thu May 14 13:26:40 2009 +0200
@@ -206,8 +206,7 @@
     if(!catch_var)
     {
         Logger::println("Making new catch var");
-        const LLType* objectTy = DtoType(ClassDeclaration::object->type);
-        catch_var = DtoAlloca(objectTy,"catchvar");
+        catch_var = DtoAlloca(ClassDeclaration::object->type, "catchvar");
     }
     return catch_var;
 }