Skip to content

Commit 2ff14fa

Browse files
[CIR] Add support for FileScopeAsm
1 parent 96a0551 commit 2ff14fa

File tree

6 files changed

+127
-1
lines changed

6 files changed

+127
-1
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,18 @@ def CIR_TypeSizeInfoAttr : CIR_Attr<"TypeSizeInfo", "type_size_info"> {
221221
}];
222222
}
223223

224+
//===----------------------------------------------------------------------===//
225+
// FileScopeAsm
226+
//===----------------------------------------------------------------------===//
227+
228+
def CIR_ModuleAsmAttr : CIR_Attr<"ModuleAsm", "module_asm"> {
229+
let summary = "Module-level inline assembly";
230+
let description = [{
231+
Stores file-scope inline assembly strings.
232+
}];
233+
let parameters = (ins "mlir::ArrayAttr":$asm_strings);
234+
let assemblyFormat = [{ `<` $asm_strings `>`}];
235+
}
224236

225237
//===----------------------------------------------------------------------===//
226238
// BoolAttr

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,10 @@ void CIRGenFunction::emitDecl(const Decl &D) {
832832
case Decl::LinkageSpec:
833833
case Decl::Export:
834834
case Decl::ObjCPropertyImpl:
835-
case Decl::FileScopeAsm:
835+
case Decl::FileScopeAsm: {
836+
CGM.buildFileScopeAsm(cast<FileScopeAsmDecl>(&D));
837+
return;
838+
}
836839
case Decl::Friend:
837840
case Decl::FriendTemplate:
838841
case Decl::Block:

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "mlir/IR/OperationSupport.h"
3232
#include "mlir/IR/SymbolTable.h"
3333
#include "mlir/IR/Verifier.h"
34+
#include "clang/AST/Decl.h"
3435
#include "clang/AST/Expr.h"
3536
#include "clang/Basic/Cuda.h"
3637
#include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -2072,6 +2073,9 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
20722073
emitTopLevelDecl(childDecl);
20732074
break;
20742075
}
2076+
case Decl::FileScopeAsm:
2077+
buildFileScopeAsm(cast<FileScopeAsmDecl>(decl));
2078+
break;
20752079
case Decl::PragmaComment: {
20762080
const auto *PCD = cast<PragmaCommentDecl>(decl);
20772081
switch (PCD->getCommentKind()) {
@@ -3776,6 +3780,9 @@ void CIRGenModule::Release() {
37763780
if (getTriple().isPPC() && !MissingFeatures::mustTailCallUndefinedGlobals()) {
37773781
llvm_unreachable("NYI");
37783782
}
3783+
3784+
// Finalize module attributes (including inline assembly)
3785+
finalizeModuleAttributes();
37793786
}
37803787

37813788
namespace {
@@ -4430,3 +4437,28 @@ cir::LabelOp
44304437
CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
44314438
return blockAddressInfoToLabel.lookup(blockInfo);
44324439
}
4440+
4441+
void CIRGenModule::buildFileScopeAsm(const FileScopeAsmDecl *D) {
4442+
// Get assembly string from declaration
4443+
appendModuleInlineAsm(D->getAsmString());
4444+
}
4445+
4446+
void CIRGenModule::finalizeModuleAttributes() {
4447+
if (moduleAsm.empty())
4448+
return;
4449+
4450+
// Build array of string attributes
4451+
llvm::SmallVector<mlir::Attribute> asmStrings;
4452+
for (const auto &asmStr : moduleAsm) {
4453+
asmStrings.push_back(builder.getStringAttr(asmStr));
4454+
}
4455+
4456+
// Create array attribute
4457+
mlir::ArrayAttr asmArray = builder.getArrayAttr(asmStrings);
4458+
4459+
// Create ModuleAsmAttr
4460+
auto moduleAsmAttr = cir::ModuleAsmAttr::get(builder.getContext(), asmArray);
4461+
4462+
// Set as module attribute
4463+
theModule->setAttr("cir.module_asm", moduleAsmAttr);
4464+
}

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "CIRGenTypes.h"
2424
#include "CIRGenVTables.h"
2525
#include "CIRGenValue.h"
26+
#include "clang/AST/Decl.h"
2627
#include "clang/CIR/MissingFeatures.h"
2728

2829
#include "clang/AST/ASTContext.h"
@@ -154,6 +155,8 @@ class CIRGenModule : public CIRGenTypeCache {
154155
llvm::DenseMap<const Expr *, mlir::Operation *>
155156
materializedGlobalTemporaryMap;
156157

158+
llvm::SmallVector<llvm::StringRef> moduleAsm;
159+
157160
public:
158161
mlir::ModuleOp getModule() const { return theModule; }
159162
CIRGenBuilderTy &getBuilder() { return builder; }
@@ -958,6 +961,11 @@ class CIRGenModule : public CIRGenTypeCache {
958961
/// one of them.
959962
cir::AnnotationAttr emitAnnotateAttr(const clang::AnnotateAttr *aa);
960963

964+
/// Process file-scope inline assembly (e.g., `asm(".text");` at global
965+
/// scope). Collects assembly strings into moduleAsm vector for later
966+
/// finalization.
967+
void buildFileScopeAsm(const FileScopeAsmDecl *D);
968+
961969
private:
962970
// An ordered map of canonical GlobalDecls to their mangled names.
963971
llvm::MapVector<clang::GlobalDecl, llvm::StringRef> MangledDeclNames;
@@ -989,6 +997,14 @@ class CIRGenModule : public CIRGenTypeCache {
989997
/// Add global annotations for a global value.
990998
/// Those annotations are emitted during lowering to the LLVM code.
991999
void addGlobalAnnotations(const ValueDecl *d, mlir::Operation *gv);
1000+
1001+
/// Append module-level inline assembly
1002+
void appendModuleInlineAsm(llvm::StringRef asmStr) {
1003+
moduleAsm.push_back(asmStr);
1004+
}
1005+
1006+
/// Finalize module attribute (call at the end of codegen)
1007+
void finalizeModuleAttributes();
9921008
};
9931009
} // namespace clang::CIRGen
9941010

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15+
#include "mlir/IR/Attributes.h"
1516
#include "mlir/IR/DialectRegistry.h"
1617
#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
1718
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
@@ -86,6 +87,17 @@ class CIRDialectLLVMIRTranslationInterface
8687
mlir::dyn_cast<cir::UWTableAttr>(attribute.getValue()))
8788
llvmModule->setUwtable(convertUWTableKind(uwTableAttr.getValue()));
8889

90+
// Handle module-level inline assembly
91+
if (auto moduleAsmAttr =
92+
mlir::dyn_cast<cir::ModuleAsmAttr>(attribute.getValue())) {
93+
mlir::ArrayAttr asmStrings = moduleAsmAttr.getAsmStrings();
94+
for (mlir::Attribute attr : asmStrings) {
95+
if (auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr)) {
96+
llvmModule->appendModuleInlineAsm(strAttr.getValue());
97+
}
98+
}
99+
}
100+
89101
// Drop ammended CIR attribute from LLVM op.
90102
module->removeAttr(attribute.getName());
91103
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
2+
// RUN: -emit-cir %s -o %t.cir
3+
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
4+
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
6+
// RUN: -emit-llvm %s -o %t.ll
7+
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM
8+
9+
// Test basic file-scope assembly
10+
asm(".section .text");
11+
asm(".global my_func");
12+
asm("my_func: ret");
13+
14+
// Test file-scope assembly with functions
15+
int foo() {
16+
return 42;
17+
}
18+
19+
asm(".data");
20+
asm(".align 8");
21+
22+
int bar() {
23+
return 24;
24+
}
25+
26+
// Test file-scope assembly at end of file
27+
asm(".section .rodata");
28+
asm(".string \"hello\"");
29+
30+
int main() {
31+
return foo() + bar();
32+
}
33+
34+
// CIR: cir.module_asm = #cir.module_asm<[".section .text", ".global my_func", "my_func: ret", ".data", ".align 8", ".section .rodata", ".string {{\\22}}hello{{\\22}}"
35+
36+
// CIR: cir.func {{.*}}@foo
37+
// CIR: cir.func {{.*}}@bar
38+
// CIR: cir.func {{.*}}@main
39+
40+
// LLVM: module asm ".section .text"
41+
// LLVM: module asm ".global my_func"
42+
// LLVM: module asm "my_func: ret"
43+
// LLVM: module asm ".data"
44+
// LLVM: module asm ".align 8"
45+
// LLVM: module asm ".section .rodata"
46+
// LLVM: module asm ".string {{\\22}}hello{{\\22}}"
47+
48+
// LLVM: define{{.*}} i32 @foo()
49+
// LLVM: define{{.*}} i32 @bar()
50+
// LLVM: define{{.*}} i32 @main()
51+

0 commit comments

Comments
 (0)