j0le created this revision. j0le added reviewers: rogfer01, rnk. j0le added a project: clang. Herald added a subscriber: cfe-commits. j0le requested review of this revision.
Hello everyone, I think, I have found the reason, why there is a difference between C and C++ for the keyword __unaligned: For C, the Method getAsCXXREcordDecl() returns nullptr. That guarantees that hasUnaligned() is called. If the language is C++, it is not guaranteed, that hasUnaligend() is called and evaluated. I have some questions: - Does this CXXRecordDecl contain information, whether the keyword __unaligned is used? - Does getClassPointerAlignment() has some side effects, that are needed? Here are some links: https://bugs.llvm.org/show_bug.cgi?id=47499 Thread on the cfe-dev mailing list: http://lists.llvm.org/pipermail/cfe-dev/2020-September/066783.html Diff, that introduced the check hasUnaligned() in getNaturalTypeAlignment(): https://reviews.llvm.org/D30166 Kind Regards Ole (Jan Ole Hüser) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D90630 Files: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/unaligned-struct-copy.c Index: clang/test/CodeGen/unaligned-struct-copy.c =================================================================== --- /dev/null +++ clang/test/CodeGen/unaligned-struct-copy.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -xc -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +struct S1 { + unsigned long x; +}; + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test1 + +void test1(__unaligned struct S1 *out) { + // CHECK: store + // CHECK-SAME: align 1 + out->x = 5; + // CHECK: ret void +} + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test2 + +void test2(__unaligned struct S1 *out, __unaligned struct S1 *in) { + // CHECK: load + // CHECK-SAME: align 1 + // CHECK: store + // CHECK-SAME: align 1 + *out = *in; + // CHECK: ret void +} Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -6146,16 +6146,17 @@ *BaseInfo = LValueBaseInfo(AlignmentSource::Type); CharUnits Alignment; + const CXXRecordDecl *RD; + if (T.getQualifiers().hasUnaligned()) { + Alignment = CharUnits::One(); + } // For C++ class pointees, we don't know whether we're pointing at a // base or a complete object, so we generally need to use the // non-virtual alignment. - const CXXRecordDecl *RD; - if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { + else if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { Alignment = 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: clang/test/CodeGen/unaligned-struct-copy.c =================================================================== --- /dev/null +++ clang/test/CodeGen/unaligned-struct-copy.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -xc -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +struct S1 { + unsigned long x; +}; + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test1 + +void test1(__unaligned struct S1 *out) { + // CHECK: store + // CHECK-SAME: align 1 + out->x = 5; + // CHECK: ret void +} + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test2 + +void test2(__unaligned struct S1 *out, __unaligned struct S1 *in) { + // CHECK: load + // CHECK-SAME: align 1 + // CHECK: store + // CHECK-SAME: align 1 + *out = *in; + // CHECK: ret void +} Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -6146,16 +6146,17 @@ *BaseInfo = LValueBaseInfo(AlignmentSource::Type); CharUnits Alignment; + const CXXRecordDecl *RD; + if (T.getQualifiers().hasUnaligned()) { + Alignment = CharUnits::One(); + } // For C++ class pointees, we don't know whether we're pointing at a // base or a complete object, so we generally need to use the // non-virtual alignment. - const CXXRecordDecl *RD; - if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { + else if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { Alignment = getClassPointerAlignment(RD); } else { Alignment = getContext().getTypeAlignInChars(T); - if (T.getQualifiers().hasUnaligned()) - Alignment = CharUnits::One(); } // Cap to the global maximum type alignment unless the alignment
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits