Skip to content

[WIP] [clang] Align cleanup structs to prevent SIGBUS on sparc32 #152866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

koachan
Copy link
Contributor

@koachan koachan commented Aug 9, 2025

The cleanup structs expect that pointers and (u)int64_t have the same alignment requirements, which isn't true on sparc32, which causes SIGBUSes.

See also: #66620

The cleanup structs expect that pointers and (u)int64_t have the same alignment
requirements, which isn't true on sparc32, which causes SIGBUSes.

See also: llvm#66620
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. labels Aug 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 9, 2025

@llvm/pr-subscribers-clang

Author: Koakuma (koachan)

Changes

The cleanup structs expect that pointers and (u)int64_t have the same alignment requirements, which isn't true on sparc32, which causes SIGBUSes.

See also: #66620


Full diff: https://github.com/llvm/llvm-project/pull/152866.diff

3 Files Affected:

  • (modified) clang/include/clang/AST/APValue.h (+1-1)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+3-2)
  • (modified) clang/lib/CodeGen/EHScopeStack.h (+1-1)
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index 9999a30c51ade..167fa7078d028 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -143,7 +143,7 @@ class APValue {
     AddrLabelDiff
   };
 
-  class LValueBase {
+  class alignas(8) LValueBase {
     typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
                                DynamicAllocLValue>
         PtrTy;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index bf16d727bac04..393c5161177df 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -725,7 +725,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   };
 
   /// Header for data within LifetimeExtendedCleanupStack.
-  struct LifetimeExtendedCleanupHeader {
+  struct alignas(8) LifetimeExtendedCleanupHeader {
     /// The size of the following cleanup object.
     unsigned Size;
     /// The kind of cleanup to push.
@@ -947,7 +947,8 @@ class CodeGenFunction : public CodeGenTypeCache {
         LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size +
         (Header.IsConditional ? sizeof(ActiveFlag) : 0));
 
-    static_assert(sizeof(Header) % alignof(T) == 0,
+    static_assert((alignof(LifetimeExtendedCleanupHeader) == alignof(T)) &&
+                      (alignof(T) == alignof(RawAddress)),
                   "Cleanup will be allocated on misaligned address");
     char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
     new (Buffer) LifetimeExtendedCleanupHeader(Header);
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index ed11dc2bb05d7..1a9cff48ad852 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -143,7 +143,7 @@ class EHScopeStack {
   ///
   /// Cleanup implementations should generally be declared in an
   /// anonymous namespace.
-  class Cleanup {
+  class alignas(8) Cleanup {
     // Anchor the construction vtable.
     virtual void anchor();
 

@llvmbot
Copy link
Member

llvmbot commented Aug 9, 2025

@llvm/pr-subscribers-clang-codegen

Author: Koakuma (koachan)

Changes

The cleanup structs expect that pointers and (u)int64_t have the same alignment requirements, which isn't true on sparc32, which causes SIGBUSes.

See also: #66620


Full diff: https://github.com/llvm/llvm-project/pull/152866.diff

3 Files Affected:

  • (modified) clang/include/clang/AST/APValue.h (+1-1)
  • (modified) clang/lib/CodeGen/CodeGenFunction.h (+3-2)
  • (modified) clang/lib/CodeGen/EHScopeStack.h (+1-1)
diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
index 9999a30c51ade..167fa7078d028 100644
--- a/clang/include/clang/AST/APValue.h
+++ b/clang/include/clang/AST/APValue.h
@@ -143,7 +143,7 @@ class APValue {
     AddrLabelDiff
   };
 
-  class LValueBase {
+  class alignas(8) LValueBase {
     typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
                                DynamicAllocLValue>
         PtrTy;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index bf16d727bac04..393c5161177df 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -725,7 +725,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   };
 
   /// Header for data within LifetimeExtendedCleanupStack.
-  struct LifetimeExtendedCleanupHeader {
+  struct alignas(8) LifetimeExtendedCleanupHeader {
     /// The size of the following cleanup object.
     unsigned Size;
     /// The kind of cleanup to push.
@@ -947,7 +947,8 @@ class CodeGenFunction : public CodeGenTypeCache {
         LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size +
         (Header.IsConditional ? sizeof(ActiveFlag) : 0));
 
-    static_assert(sizeof(Header) % alignof(T) == 0,
+    static_assert((alignof(LifetimeExtendedCleanupHeader) == alignof(T)) &&
+                      (alignof(T) == alignof(RawAddress)),
                   "Cleanup will be allocated on misaligned address");
     char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
     new (Buffer) LifetimeExtendedCleanupHeader(Header);
diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h
index ed11dc2bb05d7..1a9cff48ad852 100644
--- a/clang/lib/CodeGen/EHScopeStack.h
+++ b/clang/lib/CodeGen/EHScopeStack.h
@@ -143,7 +143,7 @@ class EHScopeStack {
   ///
   /// Cleanup implementations should generally be declared in an
   /// anonymous namespace.
-  class Cleanup {
+  class alignas(8) Cleanup {
     // Anchor the construction vtable.
     virtual void anchor();
 

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rorth
Copy link
Collaborator

rorth commented Aug 11, 2025

I've run a sparc-sun-solaris2.11 2-stage Debug build with this patch. The build itself went well (with the exception of an unrelated failure to link libomp.so), but test results are still terrible with 455 failures. But it's still massive improvement compared to before.

However, when trying an i386-pc-solaris2.11 Debug build, I ran into a build failure due to this patch:

FAILED: tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/CGBuiltin.cpp.o
[...]
In file included from /vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CGBuiltin.cpp:13:
In file included from /vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CGBuiltin.h:12:
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:951:24: error: static assertion failed due to requirement 'alignof((anonymous namespace)::CallObjCArcUse) == alignof(clang::CodeGen::RawAddress)': Cleanup will be allocated on misaligned address
  951 |                       (alignof(T) == alignof(RawAddress)),
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:924:14: note: in instantiation of function template specialization 'clang::CodeGen::CodeGenFunction::pushCleanupAfterFullExprWithActiveFlag<(anonymous namespace)::CallObjCArcUse, llvm::Value *>' requested here
  924 |       return pushCleanupAfterFullExprWithActiveFlag<T>(
      |              ^
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CGBuiltin.cpp:2269:13: note: in instantiation of function template specialization 'clang::CodeGen::CodeGenFunction::pushCleanupAfterFullExpr<(anonymous namespace)::CallObjCArcUse, llvm::Value *>' requested here
 2269 |             pushCleanupAfterFullExpr<CallObjCArcUse>(Cleanup, ArgVal);
      |             ^
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:951:35: note: expression evaluates to '8 == 4'
  951 |                       (alignof(T) == alignof(RawAddress)),
      |                        ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:951:24: error: static assertion failed due to requirement 'alignof(clang::CodeGen::EHScopeStack::ConditionalCleanup<(anonymous namespace)::CallObjCArcUse, llvm::Value *>) == alignof(clang::CodeGen::RawAddress)': Cleanup will be allocated on misaligned address
  951 |                       (alignof(T) == alignof(RawAddress)),
      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:935:5: note: in instantiation of function template specialization 'clang::CodeGen::CodeGenFunction::pushCleanupAfterFullExprWithActiveFlag<clang::CodeGen::EHScopeStack::ConditionalCleanup<(anonymous namespace)::CallObjCArcUse, llvm::Value *>, std::tuple<llvm::PointerIntPair<llvm::Value *, 1, bool>>>' requested here
  935 |     pushCleanupAfterFullExprWithActiveFlag<CleanupType>(Kind, ActiveFlag,
      |     ^
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CGBuiltin.cpp:2269:13: note: in instantiation of function template specialization 'clang::CodeGen::CodeGenFunction::pushCleanupAfterFullExpr<(anonymous namespace)::CallObjCArcUse, llvm::Value *>' requested here
 2269 |             pushCleanupAfterFullExpr<CallObjCArcUse>(Cleanup, ArgVal);
      |             ^
/vol/llvm/src/llvm-project/local/clang/lib/CodeGen/CodeGenFunction.h:951:35: note: expression evaluates to '8 == 4' 
  951 |                       (alignof(T) == alignof(RawAddress)), 
      |                        ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
2 errors generated.

Besides, I think it would be clearer to use alignas(uint64_t) instead of a magic constant.

@koachan
Copy link
Contributor Author

koachan commented Aug 12, 2025

Besides, I think it would be clearer to use alignas(uint64_t) instead of a magic constant.

Changed to this, it should fix the i386 issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants