https://github.com/el-ev updated 
https://github.com/llvm/llvm-project/pull/153546

>From b1b7b10975ecd212405d7f8a7a4021821b95fc7b Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Thu, 14 Aug 2025 15:12:18 +0800
Subject: [PATCH 1/2] [CIR] Implement codegen for inline assembly without input
 and output operands

---
 clang/include/clang/CIR/MissingFeatures.h |   5 +
 clang/lib/CIR/CodeGen/CIRGenAsm.cpp       | 136 ++++++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenFunction.h    |   2 +
 clang/lib/CIR/CodeGen/CIRGenModule.h      |   1 +
 clang/lib/CIR/CodeGen/CIRGenStmt.cpp      |   5 +-
 clang/lib/CIR/CodeGen/CMakeLists.txt      |   1 +
 clang/test/CIR/CodeGen/inline-asm.c       |  18 +++
 7 files changed, 166 insertions(+), 2 deletions(-)
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenAsm.cpp
 create mode 100644 clang/test/CIR/CodeGen/inline-asm.c

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index baab62f572b98..ebf57246ba0b9 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -176,7 +176,12 @@ struct MissingFeatures {
   static bool aggValueSlotVolatile() { return false; }
   static bool alignCXXRecordDecl() { return false; }
   static bool armComputeVolatileBitfields() { return false; }
+  static bool asmGoto() { return false; }
+  static bool asmInputOperands() { return false; }
   static bool asmLabelAttr() { return false; }
+  static bool asmMemoryEffects() { return false; }
+  static bool asmOutputOperands() { return false; }
+  static bool asmUnwindClobber() { return false; }
   static bool assignMemcpyizer() { return false; }
   static bool astVarDeclInterface() { return false; }
   static bool attributeBuiltin() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenAsm.cpp 
b/clang/lib/CIR/CodeGen/CIRGenAsm.cpp
new file mode 100644
index 0000000000000..fdf59f071335b
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenAsm.cpp
@@ -0,0 +1,136 @@
+//===--- CIRGenAsm.cpp - Inline Assembly Support for CIR CodeGen ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to emit inline assembly.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DiagnosticSema.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include "CIRGenFunction.h"
+#include "TargetInfo.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+using namespace cir;
+
+static AsmFlavor inferFlavor(const CIRGenModule &cgm, const AsmStmt &s) {
+  AsmFlavor gnuAsmFlavor =
+      cgm.getCodeGenOpts().getInlineAsmDialect() == CodeGenOptions::IAD_ATT
+          ? AsmFlavor::x86_att
+          : AsmFlavor::x86_intel;
+
+  return isa<MSAsmStmt>(&s) ? AsmFlavor::x86_intel : gnuAsmFlavor;
+}
+
+static void collectClobbers(const CIRGenFunction &cgf, const AsmStmt &s,
+                            std::string &constraints, bool &hasUnwindClobber,
+                            bool &readOnly, bool readNone) {
+
+  hasUnwindClobber = false;
+  const CIRGenModule &cgm = cgf.getCIRGenModule();
+
+  // Clobbers
+  for (unsigned i = 0, e = s.getNumClobbers(); i != e; i++) {
+    std::string clobberStr = s.getClobber(i);
+    StringRef clobber{clobberStr};
+    if (clobber == "memory")
+      readOnly = readNone = false;
+    else if (clobber == "unwind") {
+      hasUnwindClobber = true;
+      continue;
+    } else if (clobber != "cc") {
+      clobber = cgf.getTarget().getNormalizedGCCRegisterName(clobber);
+      if (cgm.getCodeGenOpts().StackClashProtector &&
+          cgf.getTarget().isSPRegName(clobber)) {
+        cgm.getDiags().Report(s.getAsmLoc(),
+                              diag::warn_stack_clash_protection_inline_asm);
+      }
+    }
+
+    if (isa<MSAsmStmt>(&s)) {
+      if (clobber == "eax" || clobber == "edx") {
+        if (constraints.find("=&A") != std::string::npos)
+          continue;
+        std::string::size_type position1 =
+            constraints.find("={" + clobber.str() + "}");
+        if (position1 != std::string::npos) {
+          constraints.insert(position1 + 1, "&");
+          continue;
+        }
+        std::string::size_type position2 = constraints.find("=A");
+        if (position2 != std::string::npos) {
+          constraints.insert(position2 + 1, "&");
+          continue;
+        }
+      }
+    }
+    if (!constraints.empty())
+      constraints += ',';
+
+    constraints += "~{";
+    constraints += clobber;
+    constraints += '}';
+  }
+
+  // Add machine specific clobbers
+  std::string_view machineClobbers = cgf.getTarget().getClobbers();
+  if (!machineClobbers.empty()) {
+    if (!constraints.empty())
+      constraints += ',';
+    constraints += machineClobbers;
+  }
+}
+
+mlir::LogicalResult CIRGenFunction::emitAsmStmt(const AsmStmt &s) {
+  // Assemble the final asm string.
+  std::string asmString = s.generateAsmString(getContext());
+
+  std::string constraints;
+
+  // An inline asm can be marked readonly if it meets the following conditions:
+  //  - it doesn't have any sideeffects
+  //  - it doesn't clobber memory
+  //  - it doesn't return a value by-reference
+  // It can be marked readnone if it doesn't have any input memory constraints
+  // in addition to meeting the conditions listed above.
+  bool readOnly = true, readNone = true;
+
+  if (s.getNumInputs() != 0 || s.getNumOutputs() != 0) {
+    assert(!cir::MissingFeatures::asmInputOperands());
+    assert(!cir::MissingFeatures::asmOutputOperands());
+    cgm.errorNYI(s.getAsmLoc(), "asm with operands");
+  }
+
+  bool hasUnwindClobber = false;
+  collectClobbers(*this, s, constraints, hasUnwindClobber, readOnly, readNone);
+
+  llvm::SmallVector<mlir::ValueRange, 8> operands;
+  mlir::Type resultType;
+
+  bool hasSideEffect = s.isVolatile() || s.getNumOutputs() == 0;
+
+  cir::InlineAsmOp ia = builder.create<cir::InlineAsmOp>(
+      getLoc(s.getAsmLoc()), resultType, operands, asmString, constraints,
+      hasSideEffect, inferFlavor(cgm, s), mlir::ArrayAttr());
+
+  if (false /*IsGCCAsmGoto*/) {
+    assert(!cir::MissingFeatures::asmGoto());
+  } else if (hasUnwindClobber) {
+    assert(!cir::MissingFeatures::asmUnwindClobber());
+  } else {
+    assert(!cir::MissingFeatures::asmMemoryEffects());
+  }
+
+  llvm::SmallVector<mlir::Attribute> operandAttrs;
+  ia.setOperandAttrsAttr(builder.getArrayAttr(operandAttrs));
+
+  return mlir::success();
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c3e77c99cca35..2ae217aa1cdb2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -942,6 +942,8 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   Address emitArrayToPointerDecay(const Expr *array);
 
+  mlir::LogicalResult emitAsmStmt(const clang::AsmStmt &s);
+
   RValue emitAtomicExpr(AtomicExpr *e);
   void emitAtomicInit(Expr *init, LValue dest);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 283b76a0dd16e..06cc3e09e416b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -102,6 +102,7 @@ class CIRGenModule : public CIRGenTypeCache {
   clang::ASTContext &getASTContext() const { return astContext; }
   const clang::TargetInfo &getTarget() const { return target; }
   const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
+  clang::DiagnosticsEngine &getDiags() const { return diags; }
   CIRGenTypes &getTypes() { return genTypes; }
   const clang::LangOptions &getLangOpts() const { return langOpts; }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp 
b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index d1e4a14824011..a0c69f34c74f9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -132,6 +132,9 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
     return emitOpenACCCacheConstruct(cast<OpenACCCacheConstruct>(*s));
   case Stmt::OpenACCAtomicConstructClass:
     return emitOpenACCAtomicConstruct(cast<OpenACCAtomicConstruct>(*s));
+  case Stmt::GCCAsmStmtClass:
+  case Stmt::MSAsmStmtClass:
+    return emitAsmStmt(cast<AsmStmt>(*s));
   case Stmt::OMPScopeDirectiveClass:
   case Stmt::OMPErrorDirectiveClass:
   case Stmt::LabelStmtClass:
@@ -145,8 +148,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
   case Stmt::CoreturnStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::IndirectGotoStmtClass:
-  case Stmt::GCCAsmStmtClass:
-  case Stmt::MSAsmStmtClass:
   case Stmt::OMPParallelDirectiveClass:
   case Stmt::OMPTaskwaitDirectiveClass:
   case Stmt::OMPTaskyieldDirectiveClass:
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt 
b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 12cea944eb2f3..7366446a33c6e 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -8,6 +8,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
 
 add_clang_library(clangCIR
   CIRGenerator.cpp
+  CIRGenAsm.cpp
   CIRGenAtomic.cpp
   CIRGenBuilder.cpp
   CIRGenCall.cpp
diff --git a/clang/test/CIR/CodeGen/inline-asm.c 
b/clang/test/CIR/CodeGen/inline-asm.c
new file mode 100644
index 0000000000000..73b2c9aa0a0eb
--- /dev/null
+++ b/clang/test/CIR/CodeGen/inline-asm.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
+
+void f1() {
+  // CIR: cir.asm(x86_att, 
+  // CIR:   {"" "~{dirflag},~{fpsr},~{flags}"}) side_effects
+  // LLVM: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
+  __asm__ volatile("" : : : );
+}
+
+void f2() {
+  // CIR: cir.asm(x86_att,
+  // CIR:   {"nop" "~{dirflag},~{fpsr},~{flags}"}) side_effects
+  // LLVM: call void asm sideeffect "nop", "~{dirflag},~{fpsr},~{flags}"()
+  __asm__ volatile("nop" : : : );
+}

>From 5328c79e2a64d47cccba7f4aa04c52a1c026be66 Mon Sep 17 00:00:00 2001
From: Iris Shi <0...@owo.li>
Date: Sun, 17 Aug 2025 17:07:59 +0800
Subject: [PATCH 2/2] Address comments

---
 clang/lib/CIR/CodeGen/CIRGenAsm.cpp | 26 +++++++++++++-------------
 clang/test/CIR/CodeGen/inline-asm.c |  6 ++++++
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenAsm.cpp 
b/clang/lib/CIR/CodeGen/CIRGenAsm.cpp
index fdf59f071335b..17dffb3515d2a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAsm.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAsm.cpp
@@ -10,11 +10,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "clang/Basic/DiagnosticSema.h"
-#include "llvm/ADT/StringExtras.h"
-
 #include "CIRGenFunction.h"
-#include "TargetInfo.h"
 #include "clang/CIR/MissingFeatures.h"
 
 using namespace clang;
@@ -39,20 +35,18 @@ static void collectClobbers(const CIRGenFunction &cgf, 
const AsmStmt &s,
 
   // Clobbers
   for (unsigned i = 0, e = s.getNumClobbers(); i != e; i++) {
-    std::string clobberStr = s.getClobber(i);
-    StringRef clobber{clobberStr};
-    if (clobber == "memory")
+    std::string clobber = s.getClobber(i);
+    if (clobber == "memory") {
       readOnly = readNone = false;
-    else if (clobber == "unwind") {
+    } else if (clobber == "unwind") {
       hasUnwindClobber = true;
       continue;
     } else if (clobber != "cc") {
       clobber = cgf.getTarget().getNormalizedGCCRegisterName(clobber);
       if (cgm.getCodeGenOpts().StackClashProtector &&
-          cgf.getTarget().isSPRegName(clobber)) {
+          cgf.getTarget().isSPRegName(clobber))
         cgm.getDiags().Report(s.getAsmLoc(),
                               diag::warn_stack_clash_protection_inline_asm);
-      }
     }
 
     if (isa<MSAsmStmt>(&s)) {
@@ -60,7 +54,7 @@ static void collectClobbers(const CIRGenFunction &cgf, const 
AsmStmt &s,
         if (constraints.find("=&A") != std::string::npos)
           continue;
         std::string::size_type position1 =
-            constraints.find("={" + clobber.str() + "}");
+            constraints.find("={" + clobber + "}");
         if (position1 != std::string::npos) {
           constraints.insert(position1 + 1, "&");
           continue;
@@ -93,7 +87,12 @@ mlir::LogicalResult CIRGenFunction::emitAsmStmt(const 
AsmStmt &s) {
   // Assemble the final asm string.
   std::string asmString = s.generateAsmString(getContext());
 
+  bool isGCCAsmGoto = false;
+
   std::string constraints;
+  std::vector<mlir::Value> outArgs;
+  std::vector<mlir::Value> inArgs;
+  std::vector<mlir::Value> inOutArgs;
 
   // An inline asm can be marked readonly if it meets the following conditions:
   //  - it doesn't have any sideeffects
@@ -112,7 +111,8 @@ mlir::LogicalResult CIRGenFunction::emitAsmStmt(const 
AsmStmt &s) {
   bool hasUnwindClobber = false;
   collectClobbers(*this, s, constraints, hasUnwindClobber, readOnly, readNone);
 
-  llvm::SmallVector<mlir::ValueRange, 8> operands;
+  std::array<mlir::ValueRange, 3> operands = {outArgs, inArgs, inOutArgs};
+
   mlir::Type resultType;
 
   bool hasSideEffect = s.isVolatile() || s.getNumOutputs() == 0;
@@ -121,7 +121,7 @@ mlir::LogicalResult CIRGenFunction::emitAsmStmt(const 
AsmStmt &s) {
       getLoc(s.getAsmLoc()), resultType, operands, asmString, constraints,
       hasSideEffect, inferFlavor(cgm, s), mlir::ArrayAttr());
 
-  if (false /*IsGCCAsmGoto*/) {
+  if (isGCCAsmGoto) {
     assert(!cir::MissingFeatures::asmGoto());
   } else if (hasUnwindClobber) {
     assert(!cir::MissingFeatures::asmUnwindClobber());
diff --git a/clang/test/CIR/CodeGen/inline-asm.c 
b/clang/test/CIR/CodeGen/inline-asm.c
index 73b2c9aa0a0eb..fc959f9326876 100644
--- a/clang/test/CIR/CodeGen/inline-asm.c
+++ b/clang/test/CIR/CodeGen/inline-asm.c
@@ -5,6 +5,9 @@
 
 void f1() {
   // CIR: cir.asm(x86_att, 
+  // CIR:   out = [],
+  // CIR:   in = [],
+  // CIR:   in_out = [],
   // CIR:   {"" "~{dirflag},~{fpsr},~{flags}"}) side_effects
   // LLVM: call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
   __asm__ volatile("" : : : );
@@ -12,6 +15,9 @@ void f1() {
 
 void f2() {
   // CIR: cir.asm(x86_att,
+  // CIR:   out = [],
+  // CIR:   in = [],
+  // CIR:   in_out = [],
   // CIR:   {"nop" "~{dirflag},~{fpsr},~{flags}"}) side_effects
   // LLVM: call void asm sideeffect "nop", "~{dirflag},~{fpsr},~{flags}"()
   __asm__ volatile("nop" : : : );

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to