pengfei updated this revision to Diff 363974.
pengfei added a comment.

Address Jennifer comments from off-line.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107141/new/

https://reviews.llvm.org/D107141

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Sema/SemaStmtAsm.cpp
  clang/test/Sema/asm.c

Index: clang/test/Sema/asm.c
===================================================================
--- clang/test/Sema/asm.c
+++ clang/test/Sema/asm.c
@@ -313,3 +313,51 @@
   asm ("jne %l0":::);
   asm goto ("jne %l0"::::lab);
 }
+
+typedef struct test19_a {
+  int a;
+  char b;
+} test19_a;
+
+typedef struct test19_b {
+  int a;
+  int b;
+  int c;
+} test19_b;
+
+typedef struct test19_c {
+  char a;
+  char b;
+} test19_c;
+
+typedef struct test19_d {
+  char a;
+  char b;
+  char c;
+  char d;
+} test19_d;
+
+typedef struct test19_e {
+  int a;
+  int b;
+  int c;
+  int d;
+} test19_e;
+
+void test19(long long x)
+{
+  test19_a a;
+  test19_b b;
+  test19_c c;
+  test19_d d;
+  test19_e e;
+  asm ("" : "=rm" (a): "0" (1)); // no-error
+  asm ("" : "=rm" (d): "0" (1)); // no-error
+  asm ("" : "=rm" (c): "0" (x)); // no-error
+  asm ("" : "=rm" (x): "0" (a)); // no-error
+  asm ("" : "=rm" (a): "0" (d)); // no-error
+  asm ("" : "=rm" (b): "0" (1)); // expected-error {{unsupported inline asm: input with type 'int' matching output with type 'test19_b' (aka 'struct test19_b')}}
+  // FIXME: The below 2 cases should be no error.
+  asm ("" : "=rm" (e): "0" (1)); // expected-error {{unsupported inline asm: input with type 'int' matching output with type 'test19_e' (aka 'struct test19_e')}}
+  asm ("" : "=rm" (x): "0" (e)); // expected-error {{unsupported inline asm: input with type 'test19_e' (aka 'struct test19_e') matching output with type 'long long'}}
+}
Index: clang/lib/Sema/SemaStmtAsm.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAsm.cpp
+++ clang/lib/Sema/SemaStmtAsm.cpp
@@ -617,14 +617,33 @@
       AD_Int, AD_FP, AD_Other
     } InputDomain, OutputDomain;
 
-    if (InTy->isIntegerType() || InTy->isPointerType())
+    auto IsPower2Structure = [this](QualType Ty) {
+      if (!Ty->isStructureType())
+        return false;
+
+      switch (Context.getTypeSize(Ty)) {
+      default:
+        return false;
+      case 8:
+      case 16:
+      case 32:
+      case 64:
+      // TODO: The maximum size GCC supports is 128 bits.
+      // We may need to extract the first element in this case.
+        return true;
+      }
+    };
+
+    if (InTy->isIntegerType() || InTy->isPointerType() ||
+        IsPower2Structure(InTy))
       InputDomain = AD_Int;
     else if (InTy->isRealFloatingType())
       InputDomain = AD_FP;
     else
       InputDomain = AD_Other;
 
-    if (OutTy->isIntegerType() || OutTy->isPointerType())
+    if (OutTy->isIntegerType() || OutTy->isPointerType() ||
+        IsPower2Structure(OutTy))
       OutputDomain = AD_Int;
     else if (OutTy->isRealFloatingType())
       OutputDomain = AD_FP;
@@ -666,7 +685,8 @@
     // output was a register, just extend the shorter one to the size of the
     // larger one.
     if (!SmallerValueMentioned && InputDomain != AD_Other &&
-        OutputConstraintInfos[TiedTo].allowsRegister())
+        OutputConstraintInfos[TiedTo].allowsRegister() &&
+        OutputDomain != AD_Other)
       continue;
 
     // Either both of the operands were mentioned or the smaller one was
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -2469,20 +2469,32 @@
       unsigned Output = Info.getTiedOperand();
       QualType OutputType = S.getOutputExpr(Output)->getType();
       QualType InputTy = InputExpr->getType();
+      uint64_t OutputSize = getContext().getTypeSize(OutputType);
+      uint64_t InputSize = getContext().getTypeSize(InputTy);
 
-      if (getContext().getTypeSize(OutputType) >
-          getContext().getTypeSize(InputTy)) {
+      if (OutputSize > InputSize) {
         // Use ptrtoint as appropriate so that we can do our extension.
         if (isa<llvm::PointerType>(Arg->getType()))
           Arg = Builder.CreatePtrToInt(Arg, IntPtrTy);
+        if (isa<llvm::StructType>(Arg->getType())) {
+          llvm::IntegerType *IntTy =
+              llvm::IntegerType::get(getLLVMContext(), InputSize);
+          Arg = Builder.CreateBitCast(Arg, IntTy);
+        }
         llvm::Type *OutputTy = ConvertType(OutputType);
         if (isa<llvm::IntegerType>(OutputTy))
           Arg = Builder.CreateZExt(Arg, OutputTy);
         else if (isa<llvm::PointerType>(OutputTy))
           Arg = Builder.CreateZExt(Arg, IntPtrTy);
-        else {
-          assert(OutputTy->isFloatingPointTy() && "Unexpected output type");
+        else if (OutputTy->isFloatingPointTy())
           Arg = Builder.CreateFPExt(Arg, OutputTy);
+        else {
+          assert(OutputTy->isStructTy() && OutputSize != 128 &&
+                 "Unexpected output type");
+          llvm::IntegerType *IntTy =
+              llvm::IntegerType::get(getLLVMContext(), OutputSize);
+          Arg = Builder.CreateZExt(Arg, IntTy);
+          Arg = Builder.CreateBitCast(Arg, OutputTy);
         }
       }
       // Deal with the tied operands' constraint code in adjustInlineAsmType.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to