Support unwinding from inline assembly

I've taken the following steps to add unwinding support from inline assembly:

1) Add a new `unwind` "attribute" (like `sideeffect`) to the asm syntax:

```
invoke void asm sideeffect unwind "call thrower", "~{dirflag},~{fpsr},~{flags}"()
    to label %exit unwind label %uexit
```

2.) Add Bitcode writing/reading support + LLVM-IR parsing.

3.) Emit EHLabels around inline assembly lowering (SelectionDAGBuilder + GlobalISel) when `InlineAsm::canThrow` is enabled.

4.) Tweak InstCombineCalls/InlineFunction pass to not mark inline assembly "calls" as nounwind.

5.) Add clang support by introducing a new clobber: "unwind", which lower to the `canThrow` being enabled.

6.) Don't allow unwinding callbr.

Reviewed By: Amanieu

Differential Revision: https://reviews.llvm.org/D95745
This commit is contained in:
cynecx
2021-05-13 19:05:11 +01:00
committed by Amanieu d'Antras
parent 9d3eb7885d
commit 8ec9fd4839
35 changed files with 865 additions and 107 deletions

View File

@@ -2830,7 +2830,7 @@ Error BitcodeReader::parseConstants() {
}
// This version adds support for the asm dialect keywords (e.g.,
// inteldialect).
case bitc::CST_CODE_INLINEASM: {
case bitc::CST_CODE_INLINEASM_OLD2: {
if (Record.size() < 2)
return error("Invalid record");
std::string AsmStr, ConstrStr;
@@ -2855,6 +2855,33 @@ Error BitcodeReader::parseConstants() {
InlineAsm::AsmDialect(AsmDialect));
break;
}
// This version adds support for the unwind keyword.
case bitc::CST_CODE_INLINEASM: {
if (Record.size() < 2)
return error("Invalid record");
std::string AsmStr, ConstrStr;
bool HasSideEffects = Record[0] & 1;
bool IsAlignStack = (Record[0] >> 1) & 1;
unsigned AsmDialect = (Record[0] >> 2) & 1;
bool CanThrow = (Record[0] >> 3) & 1;
unsigned AsmStrSize = Record[1];
if (2 + AsmStrSize >= Record.size())
return error("Invalid record");
unsigned ConstStrSize = Record[2 + AsmStrSize];
if (3 + AsmStrSize + ConstStrSize > Record.size())
return error("Invalid record");
for (unsigned i = 0; i != AsmStrSize; ++i)
AsmStr += (char)Record[2 + i];
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[3 + AsmStrSize + i];
UpgradeInlineAsmString(&AsmStr);
V = InlineAsm::get(
cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr,
ConstrStr, HasSideEffects, IsAlignStack,
InlineAsm::AsmDialect(AsmDialect), CanThrow);
break;
}
case bitc::CST_CODE_BLOCKADDRESS:{
if (Record.size() < 3)
return error("Invalid record");