Author: 吴腾
Date: 2026-07-01T21:05:17-07:00
New Revision: 39f1fb931f81d78c3ea9e9fb2ae0deefbdcb4922

URL: 
https://github.com/llvm/llvm-project/commit/39f1fb931f81d78c3ea9e9fb2ae0deefbdcb4922
DIFF: 
https://github.com/llvm/llvm-project/commit/39f1fb931f81d78c3ea9e9fb2ae0deefbdcb4922.diff

LOG: [InlineAsm] Diagnose oversized non-scalar tied asm outputs (#206230)

The 'r' asm constraint binds an operand to a general-purpose register.
For tied inline asm operands, Clang may promote a smaller integer input
to match a larger non-scalar register output. Only allow that path when
the output size can be represented by an integer type that fits in a
general-purpose register.

Otherwise, diagnose with err_store_value_to_reg before CodeGen attempts
to lower the asm and crashes.

This keeps GPR-sized aggregate/class outputs accepted while rejecting
larger array, struct, union, complex, vector, and class outputs. Add
Sema coverage for the affected C and C++ cases.

Fixes #204775

Added: 
    clang/test/SemaCXX/inline-asm-aggregate-output.cpp

Modified: 
    clang/lib/Sema/SemaStmtAsm.cpp
    clang/test/Sema/asm.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 96d372c89d2b1..6bf12d9cd98da 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -735,10 +735,13 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, 
bool IsSimple,
     if (!SmallerValueMentioned && !FPTiedToInt && InputDomain != AD_Other &&
         OutputConstraintInfos[TiedTo].allowsRegister()) {
 
-      // FIXME: GCC supports the OutSize to be 128 at maximum. Currently 
codegen
-      // crash when the size larger than the register size. So we limit it 
here.
-      if (OutTy->isStructureType() &&
-          Context.getIntTypeForBitwidth(OutSize, /*Signed*/ false).isNull()) {
+      // FIXME: GCC supports some non-scalar register outputs. Currently
+      // codegen crashes when the size cannot be represented by an integer type
+      // that fits in a general-purpose register.
+      bool FitsInGeneralPurposeRegister =
+          OutSize <= Context.getTargetInfo().getRegisterWidth() &&
+          !Context.getIntTypeForBitwidth(OutSize, /*Signed*/ false).isNull();
+      if (OutputDomain == AD_Other && !FitsInGeneralPurposeRegister) {
         targetDiag(OutputExpr->getExprLoc(), diag::err_store_value_to_reg);
         return NS;
       }

diff  --git a/clang/test/Sema/asm.c b/clang/test/Sema/asm.c
index a666b45b3150c..cc9acac1e169d 100644
--- a/clang/test/Sema/asm.c
+++ b/clang/test/Sema/asm.c
@@ -345,6 +345,13 @@ typedef struct _st_size128 {
   int d;
 } st_size128;
 
+typedef union _un_size96 {
+  int a[3];
+  char b[12];
+} un_size96;
+
+typedef int int4 __attribute__((ext_vector_type(4)));
+
 void test19(long long x)
 {
   st_size64 a;
@@ -352,7 +359,12 @@ void test19(long long x)
   st_size16 c;
   st_size32 d;
   st_size128 e;
-  asm ("" : "=rm" (a): "0" (1)); // no-error
+  char f[16];
+  char g[8];
+  un_size96 h;
+  _Complex float i;
+  int4 j;
+  asm ("" : "=rm" (a): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
   asm ("" : "=rm" (d): "0" (1)); // no-error
   asm ("" : "=rm" (c): "0" (x)); // no-error
   // FIXME: This case is actually supported by codegen.
@@ -360,10 +372,16 @@ void test19(long long x)
   // FIXME: This case is actually supported by codegen.
   asm ("" : "=rm" (a): "0" (d)); // expected-error {{unsupported inline asm: 
input with type 'st_size32' (aka 'struct _st_size32') matching output with type 
'st_size64' (aka 'struct _st_size64')}}
   asm ("" : "=rm" (b): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
-  // FIXME: This case should be supported by codegen, but it fails now.
-  asm ("" : "=rm" (e): "0" (1)); // no-error
+  // No general-purpose register can hold a 128-bit aggregate output.
+  asm ("" : "=rm" (e): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
   // FIXME: This case should be supported by codegen, but it fails now.
   asm ("" : "=rm" (x): "0" (e)); // expected-error {{unsupported inline asm: 
input with type 'st_size128' (aka 'struct _st_size128') matching output with 
type 'long long'}}
+  // Likewise for larger array, union, complex, and vector outputs.
+  asm ("" : "=r" (f): "0" (f)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+  asm ("" : "=rm" (g): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+  asm ("" : "=rm" (h): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+  asm ("" : "=rm" (i): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+  asm ("" : "=rm" (j): "0" (1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
 }
 
 typedef int int2 __attribute__((ext_vector_type(2)));

diff  --git a/clang/test/SemaCXX/inline-asm-aggregate-output.cpp 
b/clang/test/SemaCXX/inline-asm-aggregate-output.cpp
new file mode 100644
index 0000000000000..e7b16519c78c9
--- /dev/null
+++ b/clang/test/SemaCXX/inline-asm-aggregate-output.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -fsyntax-only -verify
+
+namespace TiedAggregateOutput {
+class C8 {
+  long long a;
+
+public:
+  C8();
+};
+
+class C12 {
+  int a;
+  int b;
+  int c;
+
+public:
+  C12();
+};
+
+class C16 {
+  long long a;
+  long long b;
+
+public:
+  C16();
+};
+
+void int_tied_to_gpr_sized_class_output() {
+  C8 c;
+  asm("" : "=rm"(c) : "0"(1)); // no-error
+}
+
+void int_tied_to_class_output_too_large() {
+  C12 c;
+  asm("" : "=rm"(c) : "0"(1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+}
+
+void int_tied_to_class_output() {
+  C16 c;
+  asm("" : "=r"(c) : "0"(1)); // expected-error {{impossible constraint in 
asm: cannot store value into a register}}
+}
+} // namespace TiedAggregateOutput


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to