diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-11-16 00:42:57 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-11-16 00:42:57 +0000 |
commit | 2f77b3d57031ded0de2b7b977fb63b4660f82624 (patch) | |
tree | 69c8f2e92274b61cbcc8583fcbb2ad2b3f725d81 | |
parent | 1432569f88c6da4da902df7571621f3ea3f76596 (diff) |
Fix a bunch of really nasty bugs in how we compute alignment for reference lvalues. PR11376.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144745 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 42 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 9 | ||||
-rw-r--r-- | test/CodeGenCXX/references.cpp | 14 |
3 files changed, 51 insertions, 14 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 0b6195dc79..a35bb5f711 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1319,14 +1319,19 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, "Var decl must have external storage or be a file var decl!"); llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD); - if (VD->getType()->isReferenceType()) - V = CGF.Builder.CreateLoad(V); - - V = EmitBitCastOfLValueToProperType(CGF, V, - CGF.getTypes().ConvertTypeForMem(E->getType())); - + llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType()); + V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy); unsigned Alignment = CGF.getContext().getDeclAlign(VD).getQuantity(); - LValue LV = CGF.MakeAddrLValue(V, E->getType(), Alignment); + QualType T = E->getType(); + LValue LV; + if (VD->getType()->isReferenceType()) { + llvm::LoadInst *LI = CGF.Builder.CreateLoad(V); + LI->setAlignment(Alignment); + V = LI; + LV = CGF.MakeNaturalAlignAddrLValue(V, T); + } else { + LV = CGF.MakeAddrLValue(V, E->getType(), Alignment); + } setObjCGCLValueClass(CGF.getContext(), E, LV); return LV; } @@ -1353,6 +1358,7 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const NamedDecl *ND = E->getDecl(); unsigned Alignment = getContext().getDeclAlign(ND).getQuantity(); + QualType T = E->getType(); if (ND->hasAttr<WeakRefAttr>()) { const ValueDecl *VD = cast<ValueDecl>(ND); @@ -1377,14 +1383,17 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (VD->hasAttr<BlocksAttr>()) V = BuildBlockByrefAddress(V, VD); - - if (VD->getType()->isReferenceType()) - V = Builder.CreateLoad(V); - V = EmitBitCastOfLValueToProperType(*this, V, - getTypes().ConvertTypeForMem(E->getType())); + LValue LV; + if (VD->getType()->isReferenceType()) { + llvm::LoadInst *LI = Builder.CreateLoad(V); + LI->setAlignment(Alignment); + V = LI; + LV = MakeNaturalAlignAddrLValue(V, T); + } else { + LV = MakeAddrLValue(V, T, Alignment); + } - LValue LV = MakeAddrLValue(V, E->getType(), Alignment); if (NonGCable) { LV.getQuals().removeObjCGCAttr(); LV.setNonGC(true); @@ -1843,6 +1852,7 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, const RecordDecl *rec = field->getParent(); QualType type = field->getType(); + unsigned alignment = getContext().getDeclAlign(field).getQuantity(); bool mayAlias = rec->hasAttr<MayAliasAttr>(); @@ -1859,6 +1869,7 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, if (const ReferenceType *refType = type->getAs<ReferenceType>()) { llvm::LoadInst *load = Builder.CreateLoad(addr, "ref"); if (cvr & Qualifiers::Volatile) load->setVolatile(true); + load->setAlignment(alignment); if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; @@ -1872,6 +1883,10 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, addr = load; mayAlias = false; type = refType->getPointeeType(); + if (type->isIncompleteType()) + alignment = 0; + else + alignment = getContext().getTypeAlignInChars(type).getQuantity(); cvr = 0; // qualifiers don't recursively apply to referencee } } @@ -1887,7 +1902,6 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, if (field->hasAttr<AnnotateAttr>()) addr = EmitFieldAnnotations(field, addr); - unsigned alignment = getContext().getDeclAlign(field).getQuantity(); LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 09b8b2b373..740a13e122 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1541,6 +1541,15 @@ public: return LValue::MakeAddr(V, T, Alignment, getContext(), CGM.getTBAAInfo(T)); } + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { + unsigned Alignment; + if (T->isIncompleteType()) + Alignment = 0; + else + Alignment = getContext().getTypeAlignInChars(T).getQuantity(); + return LValue::MakeAddr(V, T, Alignment, getContext(), + CGM.getTBAAInfo(T)); + } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The caller is responsible for setting an appropriate alignment on diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 4bbc251ab5..505f41893f 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -1,10 +1,16 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s void t1() { + // CHECK: define void @_Z2t1v + // CHECK: [[REFLOAD:%.*]] = load i32** @a, align 8 + // CHECK: load i32* [[REFLOAD]], align 4 extern int& a; int b = a; } void t2(int& a) { + // CHECK: define void @_Z2t2Ri + // CHECK: [[REFLOAD2:%.*]] = load i32** {{.*}}, align 8 + // CHECK: load i32* [[REFLOAD2]], align 4 int b = a; } @@ -297,3 +303,11 @@ namespace PR9565 { // CHECK-NEXT: ret void } } + +namespace N6 { + extern struct x {char& x;}y; + int a() { return y.x; } + // CHECK: define i32 @_ZN2N61aEv + // CHECK: [[REFLOAD3:%.*]] = load i8** getelementptr inbounds (%"struct.N6::x"* @_ZN2N61yE, i32 0, i32 0), align 8 + // CHECK: %0 = load i8* [[REFLOAD3]], align 1 +} |