Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1474,6 +1474,8 @@ } } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); + if (BaseT.getQualifiers().hasUnaligned()) + Align = Target->getCharWidth(); if (const VarDecl *VD = dyn_cast(D)) { if (VD->hasGlobalStorage() && !ForAlignof) Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -5673,6 +5673,8 @@ T = Ref->getPointeeType(); // __alignof is defined to return the preferred alignment. + if (T.getQualifiers().hasUnaligned()) + return CharUnits::One(); return Info.Ctx.toCharUnitsFromBits( Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); } Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -149,6 +149,8 @@ Alignment = CGM.getClassPointerAlignment(RD); } else { Alignment = getContext().getTypeAlignInChars(T); + if (T.getQualifiers().hasUnaligned()) + Alignment = CharUnits::One(); } // Cap to the global maximum type alignment unless the alignment Index: test/CodeGen/unaligned-decl.c =================================================================== --- /dev/null +++ test/CodeGen/unaligned-decl.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +// CHECK: @a1 = global i32 1, align 1 +__unaligned int a1 = 1; + +// CHECK: @a2 = global i32 1, align 1 +int __unaligned a2 = 1; + +// CHECK: @a3 = {{.*}} align 1 +__unaligned int a3[10]; + +// CHECK: @a4 = {{.*}} align 1 +int __unaligned a4[10]; + +// CHECK: @p1 = {{.*}} align 1 +int *__unaligned p1; + +// CHECK: @p2 = {{.*}} align 8 +int __unaligned *p2; + +// CHECK: @p3 = {{.*}} align 1 +int __unaligned *__unaligned p3; Index: test/CodeGen/unaligned-expr.c =================================================================== --- /dev/null +++ test/CodeGen/unaligned-expr.c @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +// ------------- +// Scalar integer +// ------------- +__unaligned int x; +void test1(void) { + // CHECK: {{%.*}} = load i32, i32* @x, align 1 + // CHECK: store i32 {{%.*}}, i32* @x, align 1 + x++; +} + +void test2(void) { + // CHECK: %y = alloca i32, align 1 + // CHECK: {{%.*}} = load i32, i32* %y, align 1 + // CHECK: store i32 {{%.*}}, i32* %y, align 1 + __unaligned int y; + y++; +} + +void test2_1(void) { + // CHECK: %y = alloca i32, align 1 + // CHECK: store i32 1, i32* %y, align 1 + __unaligned int y = 1; +} + +// ------------- +// Global pointer +// ------------- +int *__unaligned p1; +void test3(void) { + + // CHECK: {{%.*}} = load i32*, i32** @p1, align 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 4 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 4 + (*p1)++; +} + +int __unaligned *p2; +void test4(void) { + // CHECK: {{%.*}} = load i32*, i32** @p2, align 8 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + (*p2)++; +} + +int __unaligned *__unaligned p3; +void test5(void) { + // CHECK: {{%.*}} = load i32*, i32** @p3, align 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + (*p3)++; +} + +// ------------- +// Local pointer +// ------------- +void test6(void) { + // CHECK: %lp1 = alloca i32*, align 1 + // CHECK: {{%.*}} = load i32*, i32** %lp1, align 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 4 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 4 + int *__unaligned lp1; + (*lp1)++; +} + +void test7(void) { + // CHECK: %lp2 = alloca i32*, align 8 + // CHECK: {{%.*}} = load i32*, i32** %lp2, align 8 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + int __unaligned *lp2; + (*lp2)++; +} + +void test8(void) { + // CHECK: %lp3 = alloca i32*, align 1 + // CHECK: {{%.*}} = load i32*, i32** %lp3, align 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + int __unaligned *__unaligned lp3; + (*lp3)++; +} + +// ------------- +// Global array +// ------------- +__unaligned int a[10]; +void test9(void) { + // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @a, i64 0, i64 3), align 1 + // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @a, i64 0, i64 3), align 1 + (a[3])++; +} + +// ------------- +// Local array +// ------------- +void test10(void) { + // CHECK: %la = alloca [10 x i32], align 1 + // CHECK: {{%.*}} = getelementptr inbounds [10 x i32], [10 x i32]* %la, i64 0, i64 3 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + __unaligned int la[10]; + (la[3])++; +} + +// -------- +// Typedefs +// -------- + +typedef __unaligned int UnalignedInt; +void test13() { + // CHECK: %i = alloca i32, align 1 + // CHECK: {{%.*}} = load i32, i32* %i, align 1 + // CHECK: store i32 {{%.*}}, i32* %i, align 1 + UnalignedInt i; + i++; +} + +typedef int Aligned; +typedef __unaligned Aligned UnalignedInt2; +void test14() { + // CHECK: %i = alloca i32, align 1 + // CHECK: {{%.*}} = load i32, i32* %i, align 1 + // CHECK: store i32 {{%.*}}, i32* %i, align 1 + UnalignedInt2 i; + i++; +} + +typedef UnalignedInt UnalignedInt3; +void test15() { + // CHECK: %i = alloca i32, align 1 + // CHECK: {{%.*}} = load i32, i32* %i, align 1 + // CHECK: store i32 {{%.*}}, i32* %i, align 1 + UnalignedInt3 i; + i++; +} + +// ------------- +// Decayed types +// ------------- +void test16(__unaligned int c[10]) { + // CHECK: {{%.*}} = alloca i32*, align 8 + // CHECK: store i32* %c, i32** {{%.*}}, align 8 + // CHECK: {{%.*}} = load i32*, i32** {{%.*}}, align 8 + // CHECK: {{%.*}} = getelementptr inbounds i32, i32* {{%.*}}, i64 3 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + c[3]++; +} + +// ----------- +// __alignof__ +// ----------- +int test17(void) { + // CHECK: ret i32 1 + return __alignof__(__unaligned int); +} + +int test18(void) { + // CHECK: ret i32 1 + __unaligned int a; + return __alignof__(a); +} + +int test19(void) { + // CHECK: ret i32 1 + __unaligned int a[10]; + return __alignof__(a); +} + +// ----------- +// structs +// ----------- +typedef +struct S1 { + char c; + int x; +} S1; + +__unaligned S1 s1; +void test20(void) { + // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds (%struct.S1, %struct.S1* @s1, i32 0, i32 1), align 1 + // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds (%struct.S1, %struct.S1* @s1, i32 0, i32 1), align 1 + s1.x++; +} + +void test21(void) { + // CHECK: {{%.*}} = alloca %struct.S1, align 1 + // CHECK: {{%.*}} = getelementptr inbounds %struct.S1, %struct.S1* {{%.*}}, i32 0, i32 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + __unaligned S1 s1_2; + s1_2.x++; +} + +typedef +struct __attribute__((packed)) S2 { + char c; + int x; +} S2; + +__unaligned S2 s2; +void test22(void) { + // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds (%struct.S2, %struct.S2* @s2, i32 0, i32 1), align 1 + // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds (%struct.S2, %struct.S2* @s2, i32 0, i32 1), align 1 + s2.x++; +} + +void test23(void) { + // CHECK: {{%.*}} = alloca %struct.S2, align 1 + // CHECK: {{%.*}} = getelementptr inbounds %struct.S2, %struct.S2* {{%.*}}, i32 0, i32 1 + // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 + // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 + __unaligned S2 s2_2; + s2_2.x++; +} Index: test/CodeGen/unaligned-field.c =================================================================== --- /dev/null +++ test/CodeGen/unaligned-field.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s +// Test that __unaligned does not impact the layout of the fields. + +struct A +{ + char a; + __unaligned int b; +} a; +// CHECK: %struct.A = type { i8, i32 } + +struct A2 +{ + int b; + char a; + __unaligned int c; +} a2; +// CHECK: %struct.A2 = type { i32, i8, i32 } Index: test/CodeGenCXX/unaligned.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/unaligned.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -x c++ -std=c++11 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +int foo() { + // CHECK: ret i32 1 + return alignof(__unaligned int); +}