Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,18 @@ def CIR_TypeSizeInfoAttr : CIR_Attr<"TypeSizeInfo", "type_size_info"> {
}];
}

//===----------------------------------------------------------------------===//
// FileScopeAsm
Copy link
Member

Choose a reason for hiding this comment

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

-> CIR_ModuleAsmAttr?

//===----------------------------------------------------------------------===//

def CIR_ModuleAsmAttr : CIR_Attr<"ModuleAsm", "module_asm"> {
let summary = "Module-level inline assembly";
let description = [{
Stores file-scope inline assembly strings.
}];
let parameters = (ins "mlir::ArrayAttr":$asm_strings);
let assemblyFormat = [{ `<` $asm_strings `>`}];
}

//===----------------------------------------------------------------------===//
// BoolAttr
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,10 @@ void CIRGenFunction::emitDecl(const Decl &D) {
case Decl::LinkageSpec:
case Decl::Export:
case Decl::ObjCPropertyImpl:
case Decl::FileScopeAsm:
case Decl::FileScopeAsm: {
CGM.buildFileScopeAsm(cast<FileScopeAsmDecl>(&D));
return;
}
case Decl::Friend:
case Decl::FriendTemplate:
case Decl::Block:
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "mlir/IR/OperationSupport.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/IR/Verifier.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/Cuda.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
Expand Down Expand Up @@ -2072,6 +2073,9 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
emitTopLevelDecl(childDecl);
break;
}
case Decl::FileScopeAsm:
buildFileScopeAsm(cast<FileScopeAsmDecl>(decl));
Copy link
Member

Choose a reason for hiding this comment

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

Please follow OG skeleton:

  case Decl::FileScopeAsm:
    // File-scope asm is ignored during device-side CUDA compilation.
    if (langOpts.CUDA && langOpts.CUDAIsDevice)
      break;
    // File-scope asm is ignored during device-side OpenMP compilation.
    if (langOpts.OpenMPIsTargetDevice)
      break;
    // File-scope asm is ignored during device-side SYCL compilation.
    if (langOpts.SYCLIsDevice)
      break;
    buildFileScopeAsm(cast<FileScopeAsmDecl>(decl));
    break;
  }

Copy link
Member

Choose a reason for hiding this comment

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

Just call moduleAsm.push_back(Asm.str()); directly here, the two levels of indirection are not providing any benefits right now

break;
case Decl::PragmaComment: {
const auto *PCD = cast<PragmaCommentDecl>(decl);
switch (PCD->getCommentKind()) {
Expand Down Expand Up @@ -3776,6 +3780,9 @@ void CIRGenModule::Release() {
if (getTriple().isPPC() && !MissingFeatures::mustTailCallUndefinedGlobals()) {
llvm_unreachable("NYI");
}

// Finalize module attributes (including inline assembly)
finalizeModuleAttributes();
Copy link
Member

Choose a reason for hiding this comment

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

OG doesn't do this right here, why are we? There's already other model level attributes being handled, the content of this function should be there

}

namespace {
Expand Down Expand Up @@ -4430,3 +4437,28 @@ cir::LabelOp
CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
return blockAddressInfoToLabel.lookup(blockInfo);
}

void CIRGenModule::buildFileScopeAsm(const FileScopeAsmDecl *D) {
// Get assembly string from declaration
appendModuleInlineAsm(D->getAsmString());
}

void CIRGenModule::finalizeModuleAttributes() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Name might be too generic. Should I rename it to something more specific?

if (moduleAsm.empty())
return;

// Build array of string attributes
llvm::SmallVector<mlir::Attribute> asmStrings;
for (const auto &asmStr : moduleAsm) {
asmStrings.push_back(builder.getStringAttr(asmStr));
}

// Create array attribute
mlir::ArrayAttr asmArray = builder.getArrayAttr(asmStrings);

// Create ModuleAsmAttr
auto moduleAsmAttr = cir::ModuleAsmAttr::get(builder.getContext(), asmArray);

// Set as module attribute
theModule->setAttr("cir.module_asm", moduleAsmAttr);
}
16 changes: 16 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "CIRGenTypes.h"
#include "CIRGenVTables.h"
#include "CIRGenValue.h"
#include "clang/AST/Decl.h"
#include "clang/CIR/MissingFeatures.h"

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

llvm::SmallVector<std::string> moduleAsm;

public:
mlir::ModuleOp getModule() const { return theModule; }
CIRGenBuilderTy &getBuilder() { return builder; }
Expand Down Expand Up @@ -958,6 +961,11 @@ class CIRGenModule : public CIRGenTypeCache {
/// one of them.
cir::AnnotationAttr emitAnnotateAttr(const clang::AnnotateAttr *aa);

/// Process file-scope inline assembly (e.g., `asm(".text");` at global
/// scope). Collects assembly strings into moduleAsm vector for later
/// finalization.
void buildFileScopeAsm(const FileScopeAsmDecl *D);

private:
// An ordered map of canonical GlobalDecls to their mangled names.
llvm::MapVector<clang::GlobalDecl, llvm::StringRef> MangledDeclNames;
Expand Down Expand Up @@ -989,6 +997,14 @@ class CIRGenModule : public CIRGenTypeCache {
/// Add global annotations for a global value.
/// Those annotations are emitted during lowering to the LLVM code.
void addGlobalAnnotations(const ValueDecl *d, mlir::Operation *gv);

/// Append module-level inline assembly
void appendModuleInlineAsm(llvm::StringRef Asm) {
moduleAsm.push_back(Asm.str());
}

/// Finalize module attribute (call at the end of codegen)
void finalizeModuleAttributes();
};
} // namespace clang::CIRGen

Expand Down
12 changes: 12 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/DialectRegistry.h"
#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
Expand Down Expand Up @@ -86,6 +87,17 @@ class CIRDialectLLVMIRTranslationInterface
mlir::dyn_cast<cir::UWTableAttr>(attribute.getValue()))
llvmModule->setUwtable(convertUWTableKind(uwTableAttr.getValue()));

// Handle module-level inline assembly
if (auto moduleAsmAttr =
mlir::dyn_cast<cir::ModuleAsmAttr>(attribute.getValue())) {
mlir::ArrayAttr asmStrings = moduleAsmAttr.getAsmStrings();
for (mlir::Attribute attr : asmStrings) {
if (auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attr)) {
llvmModule->appendModuleInlineAsm(strAttr.getValue());
}
}
}
Comment on lines +90 to +99
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does it make sense to place the lowering here or is there another place you guys prefer?


// Drop ammended CIR attribute from LLVM op.
module->removeAttr(attribute.getName());
}
Expand Down
51 changes: 51 additions & 0 deletions clang/test/CIR/CodeGen/file-scope-asm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir \
// RUN: -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 \
// RUN: -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM

// Test basic file-scope assembly
asm(".section .text");
asm(".global my_func");
asm("my_func: ret");

// Test file-scope assembly with functions
int foo() {
return 42;
}

asm(".data");
asm(".align 8");

int bar() {
return 24;
}

// Test file-scope assembly at end of file
asm(".section .rodata");
asm(".string \"hello\"");

int main() {
return foo() + bar();
}

// CIR: cir.module_asm = #cir.module_asm<[".section .text", ".global my_func", "my_func: ret", ".data", ".align 8", ".section .rodata", ".string {{\\22}}hello{{\\22}}"

// CIR: cir.func {{.*}}@foo
// CIR: cir.func {{.*}}@bar
// CIR: cir.func {{.*}}@main

// LLVM: module asm ".section .text"
// LLVM: module asm ".global my_func"
// LLVM: module asm "my_func: ret"
// LLVM: module asm ".data"
// LLVM: module asm ".align 8"
// LLVM: module asm ".section .rodata"
// LLVM: module asm ".string {{\\22}}hello{{\\22}}"

// LLVM: define{{.*}} i32 @foo()
Copy link
Member

Choose a reason for hiding this comment

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

Look for OGCG in other tests and add the similar here.

// LLVM: define{{.*}} i32 @bar()
// LLVM: define{{.*}} i32 @main()