diff options
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 24 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 4 | ||||
-rw-r--r-- | test/CodeGen/address-space-field1.c | 16 | ||||
-rw-r--r-- | test/CodeGen/packed-structure.c | 89 |
4 files changed, 114 insertions, 19 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 8cc548048d..cbe19825f9 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1118,7 +1118,8 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) V = CGF.Builder.CreateLoad(V, "tmp"); - LValue LV = CGF.MakeAddrLValue(V, E->getType()); + unsigned Alignment = CGF.getContext().getDeclAlign(VD).getQuantity(); + LValue LV = CGF.MakeAddrLValue(V, E->getType(), Alignment); setObjCGCLValueClass(CGF.getContext(), E, LV); return LV; } @@ -1138,17 +1139,18 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, V = CGF.Builder.CreateBitCast(V, CGF.ConvertType(NoProtoType), "tmp"); } } - return CGF.MakeAddrLValue(V, E->getType()); + unsigned Alignment = CGF.getContext().getDeclAlign(FD).getQuantity(); + return CGF.MakeAddrLValue(V, E->getType(), Alignment); } LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const NamedDecl *ND = E->getDecl(); + unsigned Alignment = CGF.getContext().getDeclAlign(ND).getQuantity(); if (ND->hasAttr<WeakRefAttr>()) { const ValueDecl* VD = cast<ValueDecl>(ND); llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD); - - return MakeAddrLValue(Aliasee, E->getType()); + return MakeAddrLValue(Aliasee, E->getType(), Alignment); } if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { @@ -1174,7 +1176,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LValue LV = MakeAddrLValue(V, E->getType()); + LValue LV = MakeAddrLValue(V, E->getType(), Alignment); if (NonGCable) { LV.getQuals().removeObjCGCAttr(); LV.setNonGC(true); @@ -1190,7 +1192,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (E->getQualifier()) { const FieldDecl *FD = cast<FieldDecl>(ND); llvm::Value *V = CGM.EmitPointerToDataMember(FD); - return MakeAddrLValue(V, FD->getType()); + return MakeAddrLValue(V, FD->getType(), Alignment); } assert(false && "Unhandled DeclRefExpr"); @@ -1201,7 +1203,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { } LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) { - return MakeAddrLValue(GetAddrOfBlockDecl(E), E->getType()); + unsigned Alignment = + CGF.getContext().getDeclAlign(E->getDecl()).getQuantity(); + return MakeAddrLValue(GetAddrOfBlockDecl(E), E->getType(), Alignment); } LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { @@ -1637,7 +1641,8 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, if (Field->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LValue LV = MakeAddrLValue(V, Field->getType()); + unsigned Alignment = getContext().getDeclAlign(Field).getQuantity(); + LValue LV = MakeAddrLValue(V, Field->getType(), Alignment); LV.getQuals().addCVRQualifiers(CVRQualifiers); // __weak attribute on a field is ignored. @@ -1663,7 +1668,8 @@ CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value* BaseValue, assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); - return MakeAddrLValue(V, FieldType); + unsigned Alignment = getContext().getDeclAlign(Field).getQuantity(); + return MakeAddrLValue(V, FieldType, Alignment); } LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 603d309e63..f54a0113e7 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -969,8 +969,8 @@ public: // Helpers //===--------------------------------------------------------------------===// - LValue MakeAddrLValue(llvm::Value *V, QualType T) { - return LValue::MakeAddr(V, T, 0, getContext()); + LValue MakeAddrLValue(llvm::Value *V, QualType T, unsigned Alignment = 0) { + return LValue::MakeAddr(V, T, Alignment, getContext()); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c index a81e08ebca..f0be2138b3 100644 --- a/test/CodeGen/address-space-field1.c +++ b/test/CodeGen/address-space-field1.c @@ -5,18 +5,18 @@ // CHECK: [[p2addr:%.*]] = alloca %struct.S addrspace(2)* // CHECK: store %struct.S addrspace(1)* %p1, %struct.S addrspace(1)** [[p1addr]] // CHECK: store %struct.S addrspace(2)* %p2, %struct.S addrspace(2)** [[p2addr]] -// CHECK: [[t0:%.*]] = load %struct.S addrspace(2)** [[p2addr]] ; <%struct.S addrspace(2)*> [#uses=1] +// CHECK: [[t0:%.*]] = load %struct.S addrspace(2)** [[p2addr]], align 8 ; <%struct.S addrspace(2)*> [#uses=1] // CHECK: [[t1:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t0]], i32 0, i32 1 ; <i32 addrspace(2)*> [#uses=1] -// CHECK: [[t2:%.*]] = load i32 addrspace(2)* [[t1]] ; <i32> [#uses=1] -// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)** [[p1addr]] ; <%struct.S addrspace(1)*> [#uses=1] +// CHECK: [[t2:%.*]] = load i32 addrspace(2)* [[t1]], align 4 ; <i32> [#uses=1] +// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)** [[p1addr]], align 8 ; <%struct.S addrspace(1)*> [#uses=1] // CHECK: [[t4:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t3]], i32 0, i32 0 ; <i32 addrspace(1)*> [#uses=1] -// CHECK: store i32 [[t2]], i32 addrspace(1)* [[t4]] -// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)** [[p2addr]] ; <%struct.S addrspace(2)*> [#uses=1] +// CHECK: store i32 [[t2]], i32 addrspace(1)* [[t4]], align 4 +// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)** [[p2addr]], align 8 ; <%struct.S addrspace(2)*> [#uses=1] // CHECK: [[t6:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t5]], i32 0, i32 0 ; <i32 addrspace(2)*> [#uses=1] -// CHECK: [[t7:%.*]] = load i32 addrspace(2)* [[t6]] ; <i32> [#uses=1] -// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)** [[p1addr]] ; <%struct.S addrspace(1)*> [#uses=1] +// CHECK: [[t7:%.*]] = load i32 addrspace(2)* [[t6]], align 4 ; <i32> [#uses=1] +// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)** [[p1addr]], align 8 ; <%struct.S addrspace(1)*> [#uses=1] // CHECK: [[t9:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t8]], i32 0, i32 1 ; <i32 addrspace(1)*> [#uses=1] -// CHECK: store i32 [[t7]], i32 addrspace(1)* [[t9]] +// CHECK: store i32 [[t7]], i32 addrspace(1)* [[t9]], align 4 // CHECK: ret void // CHECK:} diff --git a/test/CodeGen/packed-structure.c b/test/CodeGen/packed-structure.c new file mode 100644 index 0000000000..2934d01d64 --- /dev/null +++ b/test/CodeGen/packed-structure.c @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | opt -S -strip -o %t +// RUX: llvm-gcc -flto -S -O3 -o %t %s +// RUN: FileCheck --check-prefix=CHECK-GLOBAL < %t %s +// RUN: FileCheck --check-prefix=CHECK-FUNCTIONS < %t %s + +struct s0 { + int x; + int y __attribute__((packed)); +}; + +// CHECK-GLOBAL: @s0_align_x = global i32 4 + +// FIXME: This should be 1 to match gcc. PR7951. +// CHECK-GLOBAL: @s0_align_y = global i32 4 + +// CHECK-GLOBAL: @s0_align = global i32 4 +int s0_align_x = __alignof(((struct s0*)0)->x); +int s0_align_y = __alignof(((struct s0*)0)->y); +int s0_align = __alignof(struct s0); + +// CHECK-FUNCTIONS: define i32 @s0_load_x +// CHECK-FUNCTIONS: [[s0_load_x:%.*]] = load i32* {{.*}}, align 4 +// CHECK-FUNCTIONS: ret i32 [[s0_load_x]] +int s0_load_x(struct s0 *a) { return a->x; } +// FIXME: This seems like it should be align 1. This is actually something which +// has changed in llvm-gcc recently, previously both x and y would be loaded +// with align 1 (in 2363.1 at least). +// +// CHECK-FUNCTIONS: define i32 @s0_load_y +// CHECK-FUNCTIONS: [[s0_load_y:%.*]] = load i32* {{.*}}, align 4 +// CHECK-FUNCTIONS: ret i32 [[s0_load_y]] +int s0_load_y(struct s0 *a) { return a->y; } +// CHECK-FUNCTIONS: define void @s0_copy +// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 4, i1 false) +void s0_copy(struct s0 *a, struct s0 *b) { *b = *a; } + +// + +struct s1 { + int x; + int y; +} __attribute__((packed)); + +// CHECK-GLOBAL: @s1_align_x = global i32 1 +// CHECK-GLOBAL: @s1_align_y = global i32 1 +// CHECK-GLOBAL: @s1_align = global i32 1 +int s1_align_x = __alignof(((struct s1*)0)->x); +int s1_align_y = __alignof(((struct s1*)0)->y); +int s1_align = __alignof(struct s1); + +// CHECK-FUNCTIONS: define i32 @s1_load_x +// CHECK-FUNCTIONS: [[s1_load_x:%.*]] = load i32* {{.*}}, align 1 +// CHECK-FUNCTIONS: ret i32 [[s1_load_x]] +int s1_load_x(struct s1 *a) { return a->x; } +// CHECK-FUNCTIONS: define i32 @s1_load_y +// CHECK-FUNCTIONS: [[s1_load_y:%.*]] = load i32* {{.*}}, align 1 +// CHECK-FUNCTIONS: ret i32 [[s1_load_y]] +int s1_load_y(struct s1 *a) { return a->y; } +// CHECK-FUNCTIONS: define void @s1_copy +// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false) +void s1_copy(struct s1 *a, struct s1 *b) { *b = *a; } + +// + +#pragma pack(push,2) +struct s2 { + int x; + int y; +}; +#pragma pack(pop) + +// CHECK-GLOBAL: @s2_align_x = global i32 2 +// CHECK-GLOBAL: @s2_align_y = global i32 2 +// CHECK-GLOBAL: @s2_align = global i32 2 +int s2_align_x = __alignof(((struct s2*)0)->x); +int s2_align_y = __alignof(((struct s2*)0)->y); +int s2_align = __alignof(struct s2); + +// CHECK-FUNCTIONS: define i32 @s2_load_x +// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2 +// CHECK-FUNCTIONS: ret i32 [[s2_load_y]] +int s2_load_x(struct s2 *a) { return a->x; } +// CHECK-FUNCTIONS: define i32 @s2_load_y +// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2 +// CHECK-FUNCTIONS: ret i32 [[s2_load_y]] +int s2_load_y(struct s2 *a) { return a->y; } +// CHECK-FUNCTIONS: define void @s2_copy +// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 2, i1 false) +void s2_copy(struct s2 *a, struct s2 *b) { *b = *a; } |