Skip to content

Commit 6398903

Browse files
Extend the uwtable attribute with unwind table kind
We have the `clang -cc1` command-line option `-funwind-tables=1|2` and the codegen option `VALUE_CODEGENOPT(UnwindTables, 2, 0) ///< Unwind tables (1) or asynchronous unwind tables (2)`. However, this is encoded in LLVM IR by the presence or the absence of the `uwtable` attribute, i.e. we lose the information whether to generate want just some unwind tables or asynchronous unwind tables. Asynchronous unwind tables take more space in the runtime image, I'd estimate something like 80-90% more, as the difference is adding roughly the same number of CFI directives as for prologues, only a bit simpler (e.g. `.cfi_offset reg, off` vs. `.cfi_restore reg`). Or even more, if you consider tail duplication of epilogue blocks. Asynchronous unwind tables could also restrict code generation to having only a finite number of frame pointer adjustments (an example of *not* having a finite number of `SP` adjustments is on AArch64 when untagging the stack (MTE) in some cases the compiler can modify `SP` in a loop). Having the CFI precise up to an instruction generally also means one cannot bundle together CFI instructions once the prologue is done, they need to be interspersed with ordinary instructions, which means extra `DW_CFA_advance_loc` commands, further increasing the unwind tables size. That is to say, async unwind tables impose a non-negligible overhead, yet for the most common use cases (like C++ exceptions), they are not even needed. This patch extends the `uwtable` attribute with an optional value: - `uwtable` (default to `async`) - `uwtable(sync)`, synchronous unwind tables - `uwtable(async)`, asynchronous (instruction precise) unwind tables Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D114543
1 parent 48f1884 commit 6398903

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+473
-295
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3188,7 +3188,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
31883188
B.addAttribute(llvm::Attribute::NoReturn)
31893189
.addAttribute(llvm::Attribute::NoUnwind);
31903190
}
3191-
B.addAttribute(llvm::Attribute::UWTable);
3191+
B.addUWTableAttr(llvm::UWTableKind::Default);
31923192

31933193
llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(
31943194
FnType, FnName,

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ void CodeGenModule::Release() {
828828
if (CodeGenOpts.NoPLT)
829829
getModule().setRtLibUseGOT();
830830
if (CodeGenOpts.UnwindTables)
831-
getModule().setUwtable();
831+
getModule().setUwtable(llvm::UWTableKind(CodeGenOpts.UnwindTables));
832832

833833
switch (CodeGenOpts.getFramePointer()) {
834834
case CodeGenOptions::FramePointerKind::None:
@@ -1839,7 +1839,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
18391839
llvm::AttrBuilder B(F->getContext());
18401840

18411841
if (CodeGenOpts.UnwindTables)
1842-
B.addAttribute(llvm::Attribute::UWTable);
1842+
B.addUWTableAttr(llvm::UWTableKind(CodeGenOpts.UnwindTables));
18431843

18441844
if (CodeGenOpts.StackClashProtector)
18451845
B.addAttribute("probe-stack", "inline-asm");

clang/test/CodeGen/asan-globals.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void func() {
4848
// RUN: %clang_cc1 -emit-llvm -fsanitize=address -funwind-tables=2 -o - %s | FileCheck %s --check-prefixes=UWTABLE
4949
// UWTABLE: define internal void @asan.module_dtor() #[[#ATTR:]] {
5050
// UWTABLE: attributes #[[#ATTR]] = { nounwind uwtable }
51-
// UWTABLE: ![[#]] = !{i32 7, !"uwtable", i32 1}
51+
// UWTABLE: ![[#]] = !{i32 7, !"uwtable", i32 2}
5252

5353
// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[IGNORELISTED_GLOBAL:[0-9]+]], ![[SECTIONED_GLOBAL:[0-9]+]], ![[SPECIAL_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
5454
// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false}

clang/test/CodeGen/uwtable-attr.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test that function and modules attributes react on the command-line options,
2+
// it does not state the current behaviour makes sense in all cases (it does not).
3+
4+
// RUN: %clang -S -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,DEFAULT
5+
// RUN: %clang -S -emit-llvm -o - %s -funwind-tables -fno-asynchronous-unwind-tables | FileCheck %s -check-prefixes=CHECK,TABLES
6+
// RUN: %clang -S -emit-llvm -o - %s -fno-unwind-tables -fno-asynchronous-unwind-tables | FileCheck %s -check-prefixes=CHECK,NO_TABLES
7+
8+
// RUN: %clang -S -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,DEFAULT
9+
// RUN: %clang -S -emit-llvm -o - -x c++ %s -funwind-tables -fno-asynchronous-unwind-tables | FileCheck %s -check-prefixes=CHECK,TABLES
10+
// RUN: %clang -S -emit-llvm -o - -x c++ %s -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables | FileCheck %s -check-prefixes=CHECK,NO_TABLES
11+
12+
#ifdef __cplusplus
13+
extern "C" void g(void);
14+
struct S { ~S(); };
15+
extern "C" int f() { S s; g(); return 0;};
16+
#else
17+
void g(void);
18+
int f() { g(); return 0; };
19+
#endif
20+
21+
// CHECK: define {{.*}} @f() #[[#F:]]
22+
// CHECK: declare {{.*}} @g() #[[#]]
23+
24+
// DEFAULT: attributes #[[#F]] = { {{.*}} uwtable{{ }}{{.*}} }
25+
// DEFAULT: ![[#]] = !{i32 7, !"uwtable", i32 2}
26+
27+
// TABLES: attributes #[[#F]] = { {{.*}} uwtable(sync){{.*}} }
28+
// TABLES: ![[#]] = !{i32 7, !"uwtable", i32 1}
29+
30+
// NO_TABLES-NOT: uwtable

llvm/bindings/go/llvm/ir_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ func TestAttributes(t *testing.T) {
8383
"sspstrong",
8484
"sanitize_thread",
8585
"sanitize_memory",
86-
"uwtable",
8786
"zeroext",
8887
"cold",
8988
"nocf_check",

llvm/docs/LangRef.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,12 +2108,15 @@ example:
21082108
function with a tail call. The prototype of a thunk should not be used for
21092109
optimization purposes. The caller is expected to cast the thunk prototype to
21102110
match the thunk target prototype.
2111-
``uwtable``
2111+
``uwtable[(sync|async)]``
21122112
This attribute indicates that the ABI being targeted requires that
21132113
an unwind table entry be produced for this function even if we can
21142114
show that no exceptions passes by it. This is normally the case for
21152115
the ELF x86-64 abi, but it can be disabled for some compilation
2116-
units.
2116+
units. The optional parameter describes what kind of unwind tables
2117+
to generate: ``sync`` for normal unwind tables, ``async`` for asynchronous
2118+
(instruction precise) unwind tables. Without the parameter, the attribute
2119+
``uwtable`` is equivalent to ``uwtable(async)``.
21172120
``nocf_check``
21182121
This attribute indicates that no control-flow check will be performed on
21192122
the attributed entity. It disables -fcf-protection=<> for a specific
@@ -7215,8 +7218,9 @@ functions is small.
72157218
- "frame-pointer": **Max**. The value can be 0, 1, or 2. A synthesized function
72167219
will get the "frame-pointer" function attribute, with value being "none",
72177220
"non-leaf", or "all", respectively.
7218-
- "uwtable": **Max**. The value can be 0 or 1. If the value is 1, a synthesized
7219-
function will get the ``uwtable`` function attribute.
7221+
- "uwtable": **Max**. The value can be 0, 1, or 2. If the value is 1, a synthesized
7222+
function will get the ``uwtable(sync)`` function attribute, if the value is 2,
7223+
a synthesized function will get the ``uwtable(async)`` function attribute.
72207224

72217225
Objective-C Garbage Collection Module Flags Metadata
72227226
----------------------------------------------------

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ namespace llvm {
263263
bool parseOptionalAlignment(MaybeAlign &Alignment,
264264
bool AllowParens = false);
265265
bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes);
266+
bool parseOptionalUWTableKind(UWTableKind &Kind);
266267
bool parseScopeAndOrdering(bool IsAtomic, SyncScope::ID &SSID,
267268
AtomicOrdering &Ordering);
268269
bool parseScope(SyncScope::ID &SSID);

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ enum Kind {
252252
kw_immarg,
253253
kw_byref,
254254
kw_mustprogress,
255+
kw_sync,
256+
kw_async,
255257

256258
kw_type,
257259
kw_opaque,

llvm/include/llvm/IR/Attributes.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/ADT/StringRef.h"
2323
#include "llvm/Config/llvm-config.h"
2424
#include "llvm/Support/Alignment.h"
25+
#include "llvm/Support/CodeGen.h"
2526
#include "llvm/Support/PointerLikeTypeTraits.h"
2627
#include <bitset>
2728
#include <cassert>
@@ -130,6 +131,7 @@ class Attribute {
130131
static Attribute getWithByRefType(LLVMContext &Context, Type *Ty);
131132
static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty);
132133
static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty);
134+
static Attribute getWithUWTableKind(LLVMContext &Context, UWTableKind Kind);
133135

134136
/// For a typed attribute, return the equivalent attribute with the type
135137
/// changed to \p ReplacementTy.
@@ -223,6 +225,9 @@ class Attribute {
223225
/// unknown.
224226
Optional<unsigned> getVScaleRangeMax() const;
225227

228+
// Returns the unwind table kind.
229+
UWTableKind getUWTableKind() const;
230+
226231
/// The Attribute is converted to a string of equivalent mnemonic. This
227232
/// is, presumably, for writing out the mnemonics for the assembly writer.
228233
std::string getAsString(bool InAttrGrp = false) const;
@@ -353,6 +358,7 @@ class AttributeSet {
353358
std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
354359
unsigned getVScaleRangeMin() const;
355360
Optional<unsigned> getVScaleRangeMax() const;
361+
UWTableKind getUWTableKind() const;
356362
std::string getAsString(bool InAttrGrp = false) const;
357363

358364
/// Return true if this attribute set belongs to the LLVMContext.
@@ -841,6 +847,9 @@ class AttributeList {
841847
/// arg.
842848
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;
843849

850+
/// Get the unwind table kind requested for the function.
851+
UWTableKind getUWTableKind() const;
852+
844853
/// Return the attributes at the index as a string.
845854
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
846855

@@ -1190,6 +1199,10 @@ class AttrBuilder {
11901199
/// Attribute.getIntValue().
11911200
AttrBuilder &addVScaleRangeAttrFromRawRepr(uint64_t RawVScaleRangeRepr);
11921201

1202+
/// This turns the unwind table kind into the form used internally in
1203+
/// Attribute.
1204+
AttrBuilder &addUWTableAttr(UWTableKind Kind);
1205+
11931206
ArrayRef<Attribute> attrs() const { return Attrs; }
11941207

11951208
bool operator==(const AttrBuilder &B) const;

llvm/include/llvm/IR/Attributes.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def SwiftSelf : EnumAttr<"swiftself", [ParamAttr]>;
273273
def SwiftAsync : EnumAttr<"swiftasync", [ParamAttr]>;
274274

275275
/// Function must be in a unwind table.
276-
def UWTable : EnumAttr<"uwtable", [FnAttr]>;
276+
def UWTable : IntAttr<"uwtable", [FnAttr]>;
277277

278278
/// Minimum/Maximum vscale value for function.
279279
def VScaleRange : IntAttr<"vscale_range", [FnAttr]>;

0 commit comments

Comments
 (0)