This is an archive of the discontinued LLVM Phabricator instance.

[LLVMbugs] [Bug 18710] Only generate .ARM.exidx and .ARM.extab when needed in EHABI
Needs ReviewPublic

Authored by chrib on Mar 20 2017, 10:42 AM.

Details

Reviewers
rengolin
rogfer01
Summary

add uwtable if unwind table is needed,regardless of nothrow/nothow status. Fulfill-f[no]-unwind-tables

Depends on reviews.llvm.org/D31139

Diff Detail

Event Timeline

chrib created this revision.Mar 20 2017, 10:42 AM

Can you clarify the logic here? It's my understanding that:

-fno-exceptions does *not* imply -fno-unwind-tables

however:

-fno-unwind-tables *does* imply that exceptions cannot be used on targets that require the tables to do unwinding.

Can you clarify the logic here? It's my understanding that:

-fno-exceptions does *not* imply -fno-unwind-tables

however:

-fno-unwind-tables *does* imply that exceptions cannot be used on targets that require the tables to do unwinding.

Yes, (bad things might happen or (std::terminate will be called, or destructors not called.)...

But -f[no]-unwind-tables implies the UWTable attribute, not NoUwind attribute. To toggle NoUnwind, use -fno-exceptions

And this is getting worse with .canunwind which means DoesNotThrow :)

in my understanding, the logic is as follow:

Since "An exception cannot propagate through a function with a nounwind table. The exception handling runtime environment terminates the program if it encounters a nounwind table during exception processing." (ARM Information Center)

The "nounwind" LLVM attribute, which means "Function does not throw" translates as the EXIDX_CANTUNWIND value in the exception table index table which needs to be created for the purpose (for the function)

And of course without exception runtime environment (the test here) we don't need this table. So I can see 3 cases:

  • nounwind set : Generate .cantunwind directive and unwind table
  • nounwind set but not EH Do not generate the .cantunwind directive and do not emit the unwind table
  • uwtable set Need to generate the unwind table (even without EH)

The disable-arm-cantunwind flag means: without EH support if the function does not throw, do dot generate the exception tables and the EXIDX_CANTUNWIND value.

Is it possible to enable cantunwind for one function and enable for another? If so, does this have to be a function attribute?

chrib added a comment.EditedMar 28 2017, 1:44 AM

Yes we can enable cantunwind with the nothrow gcc attribute when exceptions are enabled
Forcing it when exceptions are not enabled (e.g for attribute cleanup) would require -funwind-tables at function level anyway

So the flag should work, but conceptually I agree, this semantic should be better carried thru attributes, hopefully without adding a new one

chrib updated this revision to Diff 93631.EditedMar 31 2017, 6:34 AM
  1. Updating D31140: [LLVMbugs] [Bug 18710] Only generate .ARM.exidx and .ARM.extab when needed in EHABI #

Set UWTable if the language requires an exception table.
Conservatively only for ARM (necessary to emit the .cantunwind directive). But could probably be enabled for all targets.

depends on D31139

chrib updated this revision to Diff 94329.Apr 6 2017, 1:53 AM
  • NeedsUnwindTable check thumb arch
chrib updated this revision to Diff 113846.Sep 5 2017, 6:20 AM

Rebase and cleanup NeedsUnwindTable for be variants.

If you want to follow what we do for x86-64 on ARM, you should be doing this in the driver, not codegen (grep for IsUnwindTablesDefault).

chrib planned changes to this revision.EditedSep 8 2017, 5:13 AM

Yes, I also tried to look into this direction, but I did not find a clean way from the driver to emit the attribute based on codegen options and language. Also unwind-tables must not be the default for arm. (for C this is what I want to eliminate). In fact I haven't found an example of setting attributes in the driver. not sure it's even possible.

Also, setting this new uwtable attribute close to the existing NoUnwind attribute in CodeGen makes the orthogonality both attributes more obvious (or less obscure :-).

This said, testing for the Triple Arch here is not clean (I probably prefer a target overloads) but that was a conservative approach. to avoid that we would need to propose a follow up that simplifies the code as:

// We might need an unwind table, even if the function cannot throw.                                                                                                                                                                                                                                                         
if (hasUnwindExceptions(LangOpts) || CodeGenOpts.UnwindTables)
  B.addAttribute(llvm::Attribute::UWTable);

// If the module doesn't support exceptions the function cannot throw.                                                                                                                                                                                                                                                       
// We can have a nothrow function even if unwind tables are required.                                                                                                                                                                                                                                                        
if (!hasUnwindExceptions(LangOpts))
  B.addAttribute(llvm::Attribute::NoUnwind);

but this will impact all targets and can cause other changes in the backend, so it's probably better to do this separately. Do you have an advice on that ?

thanks,

chrib added a comment.Sep 8 2017, 6:24 AM

forgot to give the motivating figure. this brings a code size reduction of 9.5 % (geomean of text sections sizes) on coremarkpro -Oz for cortex-m3 eabi

chrib edited the summary of this revision. (Show Details)Sep 8 2017, 6:28 AM

Oh, you don't want to emit them by default. :)

I'm not sure what you're trying to do here... there are three possibilities:

  1. The function could have an exception thrown through it, so we need an unwind table.
  2. The function can't have an exception thrown through it, and we don't need an unwind table.
  3. The function can't have an exception thrown through it, but we need an unwind table anyway for ABI reasons.

We don't really care whether "uwtable" is set in the first scenario; it's obvious we need the table anyway. So I'm not sure what you're trying to accomplish here. (This is why I suggested using needsUnwindTableEntry() on the LLVM patch.)

chrib updated this revision to Diff 114589.Sep 11 2017, 7:07 AM

Hello Eli,

You were right, using IsUnwindTablesDefault is the correct way to abstract the need for UnwindTables. I missed the relationship between the driver munwind-table and GodeGenOpts.UnwindTables use in Codegen.

Here is a new patch just setting IsUnwindTablesDefault for EHABI. No Changes in the testsuite results with D31139

efriedma added inline comments.Sep 13 2017, 3:23 PM
lib/Driver/ToolChains/BareMetal.cpp
61

This still seems weird. In most situations, I would expect you want the same behavior for C code and C++ with -fno-exceptions. On other platforms, we get that behavior by just returning false (the default).

OK, we can refine so that unwind-table is also not generated for C++ -fno-exceptions.

To summarize this gives or C++ :

Unwind (table)Exceptions (can throw)
defaultYY
fno-unwindNY (1)
fno-exceptionsNN

(1) without unwind, no handler can be found so the default is to terminate.

for C :

Unwind (table)Exceptions (can throw)
defaultNN
funwindYN
fexceptionsYN

Cheers,

chrib updated this revision to Diff 115176.Sep 14 2017, 12:51 AM

Update IsUnwindTablesDefault to test fno-exceptions. (see Darwin.cpp)

Add comments.

I would rather not make ARM baremetal do something different from every other target...

On Linux, for most targets, we don't add the uwtable attribute by default; without the uwtable attribute, non-ARM backends (e.g. aarch64) only emit tables for functions which might unwind. Following this precedent is probably the most straightforward.

MachO::IsUnwindTablesDefault does something similar to what you're doing here (except it doesn't depend on CCCIsCXX). But Apple platforms have to deal with ObjC exception handling, so I'm not sure that's the best precedent to follow.

chrib added a comment.Sep 20 2017, 1:30 AM

oops yes of course. I forgot some bits while switching from testing the arch to testing the platform.

indeed --target=arm-none-linux-gnueabihf lost its unwind info in c++. Surprisingly not caught by the llvm tests, will add some.

thanks

chrib added a comment.Sep 21 2017, 5:47 AM

Hello,

I didn't find an easy way factorize the change in IsUnwindTableDefault to support the multiple ARM toolchains. After a quick check in Triple::arm in Driver/Toochains, many seem impacted (excepted NetBSD and Darwin that uses DwarfCFI or SJLG). So here is an attempt to move this into a small arm hook and use.

Also, I realized that the cxx tests was not correctly checked because most of them are invoked as "clang" instead if "clang++" So another proposal is to check the input type in IsUnwindTablesDefault.

Finally I've added the clang tests to check for this.

thanks !

chrib updated this revision to Diff 116176.Sep 21 2017, 5:57 AM

Changes since last revision:

  • Check IsUnwindTablesDefault in ARM Toolchains that support ExceptionHandling::ARM (not Darwin, NetBSD)
  • Check input type with driver mode for C++ mode.
  • Add Tests
chrib updated this revision to Diff 117139.Sep 29 2017, 7:14 AM

Hello,

I realized that testing CCCisCXX for IsUnwindTablesDefault was not really good and useless here, because we cannot treat C as C++ mode. In fact only the file type matters, as seen in the tests.

So I'd like to amend my previous proposal to

  • Add the InputType parameter to IsUnwindTablesDefault and use in the new function ARMNeedUnwindTable
  • Fix tests thinko (wrong triplet)
  • Rebase

sorry for the respin, thanks !

chrib updated this revision to Diff 135603.Feb 23 2018, 2:18 AM

hello, realizing that this has been stuck for a while now. did I answer all the concerns ? rebased patch,

gentle ping :-)

many thanks,

Christian

chrib updated this revision to Diff 135610.Feb 23 2018, 2:34 AM

damn it last diff was the llvm part (D31139). Here is the clang part.

sorry for the noise, still not experienced with Phabricator.