aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-11-16 00:42:57 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-11-16 00:42:57 +0000
commit2f77b3d57031ded0de2b7b977fb63b4660f82624 (patch)
tree69c8f2e92274b61cbcc8583fcbb2ad2b3f725d81
parent1432569f88c6da4da902df7571621f3ea3f76596 (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.cpp42
-rw-r--r--lib/CodeGen/CodeGenFunction.h9
-rw-r--r--test/CodeGenCXX/references.cpp14
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
+}