Skip to content
Merged
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
30 changes: 30 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,36 @@ def ConvergentAttr : CIRUnitAttr<"Convergent", "convergent"> {
let storageType = [{ ConvergentAttr }];
}

def UWTableKindNone
: I32EnumAttrCase<"None", 0, "none">;
def UWTableKindSync
: I32EnumAttrCase<"Sync", 1, "sync">;
def UWTableKindAsync
: I32EnumAttrCase<"Async", 2, "async">;

def UWTableKind : I32EnumAttr<"UWTableKind", "Unwind table kind", [
UWTableKindNone, UWTableKindSync, UWTableKindAsync
]> {
let cppNamespace = "::cir";
let genSpecializedAttr = 0;
}

def UWTableAttr : EnumAttr<CIR_Dialect, UWTableKind, "uwtable"> {
let summary = "Unwind table kind attribute";
let description = [{
The kind of unwind tables to generate for a function. `none` means no unwind
tables are generated; `sync` means synchronous unwind tables (that are only
valid at call boundaries), and `async` means asynchronous unwind tables
(that are valid at all instructions). When applied to a module, this
controls the unwind table generation for any synthesized functions.
}];

let cppClassName = "UWTableAttr";
let assemblyFormat = [{
`<` $value `>`
}];
}

class CIR_GlobalCtorDtor<string name, string attrMnemonic,
string sum, string desc>
: CIR_Attr<"Global" # name, "global_" # attrMnemonic> {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def CIR_Dialect : Dialect {
static llvm::StringRef getLangAttrName() { return "cir.lang"; }
static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; }
static llvm::StringRef getUWTableAttrName() { return "cir.uwtable"; }

static llvm::StringRef getGlobalCtorsAttrName() { return "cir.global_ctors"; }
static llvm::StringRef getGlobalDtorsAttrName() { return "cir.global_dtors"; }
Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ struct MissingFeatures {
static bool codeModel() { return false; }
static bool largeDataThreshold() { return false; }
static bool directAccessExternalData() { return false; }
static bool setUwtable() { return false; }
static bool setFramePointer() { return false; }
static bool simplifyPersonality() { return false; }
static bool emitVersionIdentMetadata() { return false; }
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2500,6 +2500,12 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
FuncOp f) {
mlir::NamedAttrList attrs{f.getExtraAttrs().getElements().getValue()};

if ((!decl || !decl->hasAttr<NoUwtableAttr>()) && codeGenOpts.UnwindTables) {
auto attr = cir::UWTableAttr::get(
&getMLIRContext(), cir::UWTableKind(codeGenOpts.UnwindTables));
attrs.set(attr.getMnemonic(), attr);
}

if (!hasUnwindExceptions(getLangOpts())) {
auto attr = cir::NoThrowAttr::get(&getMLIRContext());
attrs.set(attr.getMnemonic(), attr);
Expand Down Expand Up @@ -3258,7 +3264,10 @@ void CIRGenModule::Release() {
llvm_unreachable("NYI");
assert(!MissingFeatures::directAccessExternalData());
if (codeGenOpts.UnwindTables)
assert(!MissingFeatures::setUwtable());
theModule->setAttr(
cir::CIRDialect::getUWTableAttrName(),
cir::UWTableAttr::get(&getMLIRContext(),
cir::UWTableKind(codeGenOpts.UnwindTables)));

switch (codeGenOpts.getFramePointer()) {
case CodeGenOptions::FramePointerKind::None:
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ class CIRDialectLLVMIRTranslationInterface
oclVerMD->addOperand(llvm::MDNode::get(llvmContext, oclVerElts));
}

if (auto uwTableAttr =
mlir::dyn_cast<cir::UWTableAttr>(attribute.getValue()))
llvmModule->setUwtable(convertUWTableKind(uwTableAttr.getValue()));

// Drop ammended CIR attribute from LLVM op.
module->removeAttr(attribute.getName());
}
Expand Down Expand Up @@ -129,6 +133,11 @@ class CIRDialectLLVMIRTranslationInterface
attr.getValue())) {
emitOpenCLKernelArgMetadata(clArgMetadata, func.getNumArguments(),
llvmFunc, moduleTranslation);
} else if (auto uwTableAttr =
mlir::dyn_cast<cir::UWTableAttr>(attr.getValue())) {
llvm::AttrBuilder builder(llvmFunc->getContext());
builder.addUWTableAttr(convertUWTableKind(uwTableAttr.getValue()));
llvmFunc->addFnAttrs(builder);
}
}
}
Expand Down Expand Up @@ -261,6 +270,19 @@ class CIRDialectLLVMIRTranslationInterface
llvmFunc->setMetadata("kernel_arg_name",
llvm::MDNode::get(vmCtx, argNames));
}

private:
static llvm::UWTableKind convertUWTableKind(cir::UWTableKind kind) {
// TODO(cir): Use UWTableKindAttr from the LLVM dialect when available.
switch (kind) {
case cir::UWTableKind::None:
return llvm::UWTableKind::None;
case cir::UWTableKind::Sync:
return llvm::UWTableKind::Sync;
case cir::UWTableKind::Async:
return llvm::UWTableKind::Async;
}
}
};

void registerCIRDialectTranslation(mlir::DialectRegistry &registry) {
Expand Down
56 changes: 56 additions & 0 deletions clang/test/CIR/CodeGen/uwtable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t-none.cir
// RUN: FileCheck %s --input-file=%t-none.cir --check-prefix=CIR-NONE
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -funwind-tables=0 %s -o %t-none-explicit.cir
// RUN: FileCheck %s --input-file=%t-none-explicit.cir --check-prefix=CIR-NONE
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -funwind-tables=1 %s -o %t-sync.cir
// RUN: FileCheck %s --input-file=%t-sync.cir --check-prefix=CIR-SYNC
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -funwind-tables=2 %s -o %t-async.cir
// RUN: FileCheck %s --input-file=%t-async.cir --check-prefix=CIR-ASYNC

// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-none.ll
// RUN: FileCheck %s --input-file=%t-none.ll --check-prefix=LLVM-NONE
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -funwind-tables=0 %s -o %t-none-explicit.ll
// RUN: FileCheck %s --input-file=%t-none-explicit.ll --check-prefix=LLVM-NONE
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -funwind-tables=1 %s -o %t-sync.ll
// RUN: FileCheck %s --input-file=%t-sync.ll --check-prefix=LLVM-SYNC
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -funwind-tables=2 %s -o %t-async.ll
// RUN: FileCheck %s --input-file=%t-async.ll --check-prefix=LLVM-ASYNC

// CIR-NONE-NOT: #cir.uwtable

// CIR-SYNC-DAG: module {{.*}} attributes {{{.*}}cir.uwtable = #cir.uwtable<sync>
// CIR-SYNC-DAG: cir.func @_Z1fv() extra(#[[f_attr:.*]])
// CIR-SYNC-DAG: cir.func @_Z1gv() extra(#[[g_attr:.*]])
// CIR-SYNC-DAG: #[[f_attr]] = #cir<extra({{{.*}}uwtable = #cir.uwtable<sync>
// CIR-SYNC-DAG: #[[g_attr]] =
// CIR-SYNC-NOT: #cir.uwtable

// CIR-ASYNC-DAG: module {{.*}} attributes {{{.*}}cir.uwtable = #cir.uwtable<async>
// CIR-ASYNC-DAG: cir.func @_Z1fv() extra(#[[f_attr:.*]])
// CIR-ASYNC-DAG: cir.func @_Z1gv() extra(#[[g_attr:.*]])
// CIR-ASYNC-DAG: #[[f_attr]] = #cir<extra({{{.*}}uwtable = #cir.uwtable<async>
// CIR-ASYNC-DAG: #[[g_attr]] =
// CIR-ASYNC-NOT: #cir.uwtable

// Avoid matching "uwtable" in the ModuleID and source_filename comments.
// LLVM-NONE: define {{.*}} @_Z1fv()
// LLVM-NONE-NOT: uwtable

// LLVM-SYNC: define {{.*}} @_Z1fv() #[[#F_ATTRS:]]
// LLVM-SYNC: define {{.*}} @_Z1gv() #[[#G_ATTRS:]]
// LLVM-SYNC: attributes #[[#F_ATTRS]] = {{{.*}}uwtable(sync)
// LLVM-SYNC: attributes #[[#G_ATTRS]] =
// LLVM-SYNC-NOT: uwtable
// LLVM-SYNC-DAG: ![[#METADATA:]] = !{i32 7, !"uwtable", i32 1}
// LLVM-SYNC-DAG: !llvm.module.flags = !{{{.*}}[[#METADATA]]

// LLVM-ASYNC: define {{.*}} @_Z1fv() #[[#ATTRS:]]
// LLVM-ASYNC: define {{.*}} @_Z1gv() #[[#G_ATTRS:]]
// LLVM-ASYNC: attributes #[[#ATTRS]] = {{{.*}}uwtable{{ }}
// LLVM-ASYNC: attributes #[[#G_ATTRS]] =
// LLVM-ASYNC-NOT: uwtable
// LLVM-ASYNC-DAG: ![[#METADATA:]] = !{i32 7, !"uwtable", i32 2}
// LLVM-ASYNC-DAG: !llvm.module.flags = !{{{.*}}[[#METADATA]]
void f() {}

[[clang::nouwtable]] void g() {}
Loading