[llvm-branch-commits] [llvm] 2c63e76 - [XCOFF][AIX] Alternative path in EHStreamer for platforms do not have uleb128 support

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Dec 2 12:07:44 PST 2020


Author: jasonliu
Date: 2020-12-02T20:03:15Z
New Revision: 2c63e7604c87d97723919ca00d80ea38cddca8f9

URL: https://github.com/llvm/llvm-project/commit/2c63e7604c87d97723919ca00d80ea38cddca8f9
DIFF: https://github.com/llvm/llvm-project/commit/2c63e7604c87d97723919ca00d80ea38cddca8f9.diff

LOG: [XCOFF][AIX] Alternative path in EHStreamer for platforms do not have uleb128 support

Summary:
Not all system assembler supports `.uleb128 label2 - label1` form.
When the target do not support this form, we have to take
alternative manual calculation to get the offsets from them.

Reviewed By: hubert.reinterpretcast

Diffierential Revision: https://reviews.llvm.org/D92058

Added: 
    llvm/test/CodeGen/X86/gnu-eh-alternative.ll

Modified: 
    llvm/include/llvm/MC/MCAsmInfo.h
    llvm/include/llvm/Target/TargetLoweringObjectFile.h
    llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
    llvm/lib/MC/MCAsmInfo.cpp
    llvm/lib/MC/MCAsmInfoXCOFF.cpp
    llvm/lib/Target/TargetLoweringObjectFile.cpp
    llvm/test/CodeGen/PowerPC/aix-exception.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index 2b889d0ed5fa..c55dab4e7973 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -186,6 +186,9 @@ class MCAsmInfo {
   /// alignment is supported.
   bool UseDotAlignForAlignment = false;
 
+  /// True if the target supports LEB128 directives.
+  bool HasLEB128Directives = true;
+
   //===--- Data Emission Directives -------------------------------------===//
 
   /// This should be set to the directive used to get some number of zero (and
@@ -575,6 +578,8 @@ class MCAsmInfo {
     return UseDotAlignForAlignment;
   }
 
+  bool hasLEB128Directives() const { return HasLEB128Directives; }
+
   const char *getZeroDirective() const { return ZeroDirective; }
   bool doesZeroDirectiveSupportNonZeroValue() const {
     return ZeroDirectiveSupportsNonZeroValue;

diff  --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index edae4bb509ee..90041f077523 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -157,7 +157,7 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
   unsigned getPersonalityEncoding() const { return PersonalityEncoding; }
   unsigned getLSDAEncoding() const { return LSDAEncoding; }
   unsigned getTTypeEncoding() const { return TTypeEncoding; }
-  unsigned getCallSiteEncoding() const { return CallSiteEncoding; }
+  unsigned getCallSiteEncoding() const;
 
   const MCExpr *getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding,
                                   MCStreamer &Streamer) const;

diff  --git a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index b6fc83285a20..2ffe8a7b0469 100644
--- a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -413,6 +413,7 @@ MCSymbol *EHStreamer::emitExceptionTable() {
 
   bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
   bool IsWasm = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Wasm;
+  bool HasLEB128Directives = Asm->MAI->hasLEB128Directives();
   unsigned CallSiteEncoding =
       IsSJLJ ? static_cast<unsigned>(dwarf::DW_EH_PE_udata4) :
                Asm->getObjFileLowering().getCallSiteEncoding();
@@ -505,6 +506,79 @@ MCSymbol *EHStreamer::emitExceptionTable() {
     Asm->OutStreamer->emitLabel(CstBeginLabel);
   };
 
+  // An alternative path to EmitTypeTableRefAndCallSiteTableEndRef.
+  // For some platforms, the system assembler does not accept the form of
+  // `.uleb128 label2 - label1`. In those situations, we would need to calculate
+  // the size between label1 and label2 manually.
+  // In this case, we would need to calculate the LSDA size and the call
+  // site table size.
+  auto EmitTypeTableOffsetAndCallSiteTableOffset = [&]() {
+    assert(CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives &&
+           "Targets supporting .uleb128 do not need to take this path.");
+    if (CallSiteRanges.size() > 1)
+      report_fatal_error(
+          "-fbasic-block-sections is not yet supported on "
+          "platforms that do not have general LEB128 directive support.");
+
+    uint64_t CallSiteTableSize = 0;
+    const CallSiteRange &CSRange = CallSiteRanges.back();
+    for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx;
+         CallSiteIdx < CSRange.CallSiteEndIdx; ++CallSiteIdx) {
+      const CallSiteEntry &S = CallSites[CallSiteIdx];
+      // Each call site entry consists of 3 udata4 fields (12 bytes) and
+      // 1 ULEB128 field.
+      CallSiteTableSize += 12 + getULEB128Size(S.Action);
+      assert(isUInt<32>(CallSiteTableSize) && "CallSiteTableSize overflows.");
+    }
+
+    Asm->emitEncodingByte(TTypeEncoding, "@TType");
+    if (HaveTTData) {
+      const unsigned ByteSizeOfCallSiteOffset =
+          getULEB128Size(CallSiteTableSize);
+      uint64_t ActionTableSize = 0;
+      for (const ActionEntry &Action : Actions) {
+        // Each action entry consists of two SLEB128 fields.
+        ActionTableSize += getSLEB128Size(Action.ValueForTypeID) +
+                           getSLEB128Size(Action.NextAction);
+        assert(isUInt<32>(ActionTableSize) && "ActionTableSize overflows.");
+      }
+
+      const unsigned TypeInfoSize =
+          Asm->GetSizeOfEncodedValue(TTypeEncoding) * MF->getTypeInfos().size();
+
+      const uint64_t LSDASizeBeforeAlign =
+          1                          // Call site encoding byte.
+          + ByteSizeOfCallSiteOffset // ULEB128 encoding of CallSiteTableSize.
+          + CallSiteTableSize        // Call site table content.
+          + ActionTableSize;         // Action table content.
+
+      const uint64_t LSDASizeWithoutAlign = LSDASizeBeforeAlign + TypeInfoSize;
+      const unsigned ByteSizeOfLSDAWithoutAlign =
+          getULEB128Size(LSDASizeWithoutAlign);
+      const uint64_t DisplacementBeforeAlign =
+          2 // LPStartEncoding and TypeTableEncoding.
+          + ByteSizeOfLSDAWithoutAlign + LSDASizeBeforeAlign;
+
+      // The type info area starts with 4 byte alignment.
+      const unsigned NeedAlignVal = (4 - DisplacementBeforeAlign % 4) % 4;
+      uint64_t LSDASizeWithAlign = LSDASizeWithoutAlign + NeedAlignVal;
+      const unsigned ByteSizeOfLSDAWithAlign =
+          getULEB128Size(LSDASizeWithAlign);
+
+      // The LSDASizeWithAlign could use 1 byte less padding for alignment
+      // when the data we use to represent the LSDA Size "needs" to be 1 byte
+      // larger than the one previously calculated without alignment.
+      if (ByteSizeOfLSDAWithAlign > ByteSizeOfLSDAWithoutAlign)
+        LSDASizeWithAlign -= 1;
+
+      Asm->OutStreamer->emitULEB128IntValue(LSDASizeWithAlign,
+                                            ByteSizeOfLSDAWithAlign);
+    }
+
+    Asm->emitEncodingByte(CallSiteEncoding, "Call site");
+    Asm->OutStreamer->emitULEB128IntValue(CallSiteTableSize);
+  };
+
   // SjLj / Wasm Exception handling
   if (IsSJLJ || IsWasm) {
     Asm->OutStreamer->emitLabel(Asm->getMBBExceptionSym(Asm->MF->front()));
@@ -620,7 +694,10 @@ MCSymbol *EHStreamer::emitExceptionTable() {
             Asm->MAI->getCodePointerSize());
       }
 
-      EmitTypeTableRefAndCallSiteTableEndRef();
+      if (HasLEB128Directives)
+        EmitTypeTableRefAndCallSiteTableEndRef();
+      else
+        EmitTypeTableOffsetAndCallSiteTableOffset();
 
       for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx;
            CallSiteIdx != CSRange.CallSiteEndIdx; ++CallSiteIdx) {

diff  --git a/llvm/lib/MC/MCAsmInfo.cpp b/llvm/lib/MC/MCAsmInfo.cpp
index 9767ee6c1133..0d2d26b0eb47 100644
--- a/llvm/lib/MC/MCAsmInfo.cpp
+++ b/llvm/lib/MC/MCAsmInfo.cpp
@@ -28,6 +28,12 @@ static cl::opt<DefaultOnOff> DwarfExtendedLoc(
                clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
     cl::init(Default));
 
+cl::opt<cl::boolOrDefault> UseLEB128Directives(
+    "use-leb128-directives", cl::Hidden,
+    cl::desc(
+        "Disable the usage of LEB128 directives, and generate .byte instead."),
+    cl::init(cl::BOU_UNSET));
+
 MCAsmInfo::MCAsmInfo() {
   SeparatorString = ";";
   CommentString = "#";
@@ -51,6 +57,8 @@ MCAsmInfo::MCAsmInfo() {
   WeakDirective = "\t.weak\t";
   if (DwarfExtendedLoc != Default)
     SupportsExtendedDwarfLocDirective = DwarfExtendedLoc == Enable;
+  if (UseLEB128Directives != cl::BOU_UNSET)
+    HasLEB128Directives = UseLEB128Directives == cl::BOU_TRUE;
 
   // FIXME: Clang's logic should be synced with the logic used to initialize
   //        this member and the two implementations should be merged.

diff  --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
index eb46deedcd11..2f8bc6a49bb7 100644
--- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp
+++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp
@@ -8,9 +8,12 @@
 
 #include "llvm/MC/MCAsmInfoXCOFF.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
 
 using namespace llvm;
 
+extern cl::opt<cl::boolOrDefault> UseLEB128Directives;
+
 void MCAsmInfoXCOFF::anchor() {}
 
 MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
@@ -20,6 +23,8 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() {
   PrivateLabelPrefix = "L..";
   SupportsQuotedNames = false;
   UseDotAlignForAlignment = true;
+  if (UseLEB128Directives == cl::BOU_UNSET)
+    HasLEB128Directives = false;
   ZeroDirective = "\t.space\t";
   ZeroDirectiveSupportsNonZeroValue = false;
   AsciiDirective = nullptr; // not supported

diff  --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp
index eea0aeea2c45..087d5e3497f9 100644
--- a/llvm/lib/Target/TargetLoweringObjectFile.cpp
+++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp
@@ -20,6 +20,7 @@
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCStreamer.h"
@@ -55,6 +56,15 @@ TargetLoweringObjectFile::~TargetLoweringObjectFile() {
   delete Mang;
 }
 
+unsigned TargetLoweringObjectFile::getCallSiteEncoding() const {
+  // If target does not have LEB128 directives, we would need the
+  // call site encoding to be udata4 so that the alternative path
+  // for not having LEB128 directives could work.
+  if (!getContext().getAsmInfo()->hasLEB128Directives())
+    return dwarf::DW_EH_PE_udata4;
+  return CallSiteEncoding;
+}
+
 static bool isNullOrUndef(const Constant *C) {
   // Check that the constant isn't all zeros or undefs.
   if (C->isNullValue() || isa<UndefValue>(C))

diff  --git a/llvm/test/CodeGen/PowerPC/aix-exception.ll b/llvm/test/CodeGen/PowerPC/aix-exception.ll
index edef76c75c68..f2fc323e166f 100644
--- a/llvm/test/CodeGen/PowerPC/aix-exception.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-exception.ll
@@ -107,11 +107,10 @@ eh.resume:                                        ; preds = %catch.dispatch
 ; ASM:  	.byte	255                             # @LPStart Encoding = omit
 ; ASM32:	.byte	187                             # @TType Encoding = indirect datarel sdata4
 ; ASM64:  .byte	188                             # @TType Encoding = indirect datarel sdata8
-; ASM:  	.uleb128 L..ttbase0-L..ttbaseref0
-; ASM:  L..ttbaseref0:
+; ASM32: 	.byte 37
+; ASM64:  .byte	41
 ; ASM:  	.byte	3                               # Call site Encoding = udata4
-; ASM:  	.uleb128 L..cst_end0-L..cst_begin0
-; ASM:  L..cst_begin0:
+; ASM:  	.byte 26
 ; ASM:  	.vbyte	4, L..tmp0-L..func_begin0       # >> Call Site 1 <<
 ; ASM:  	.vbyte	4, L..tmp1-L..tmp0              #   Call between L..tmp0 and L..tmp1
 ; ASM:  	.vbyte	4, L..tmp2-L..func_begin0       #     jumps to L..tmp2
@@ -140,9 +139,9 @@ eh.resume:                                        ; preds = %catch.dispatch
 ; ASM64:  .vbyte	8, GCC_except_table1
 ; ASM64:  .vbyte	8, __xlcxx_personality_v1[DS]
 
-; ASM:  	.toc
+; ASM:    .toc
 ; ASM:  L..C0:
-; ASM:  	.tc _ZTIi[TC],_ZTIi[UA]
+; ASM:    .tc _ZTIi[TC],_ZTIi[UA]
 
 declare i8* @__cxa_allocate_exception(i32)
 declare void @__cxa_throw(i8*, i8*, i8*)

diff  --git a/llvm/test/CodeGen/X86/gnu-eh-alternative.ll b/llvm/test/CodeGen/X86/gnu-eh-alternative.ll
new file mode 100644
index 000000000000..b7817e18dcca
--- /dev/null
+++ b/llvm/test/CodeGen/X86/gnu-eh-alternative.ll
@@ -0,0 +1,103 @@
+; RUN: llc -verify-machineinstrs -mtriple x86_64-pc-linux-gnu -filetype=asm < %s | \
+; RUN:   FileCheck --check-prefixes=ASM,ULEB128 %s
+; RUN: llc -verify-machineinstrs -mtriple x86_64-pc-linux-gnu -use-leb128-directives=true -filetype=asm < %s | \
+; RUN:   FileCheck --check-prefixes=ASM,ULEB128 %s
+; RUN: llc -verify-machineinstrs -mtriple x86_64-pc-linux-gnu -use-leb128-directives=false -filetype=asm < %s | \
+; RUN:   FileCheck --check-prefixes=ASM,NO128 %s
+
+ at _ZTIi = external dso_local constant i8*
+
+define dso_local i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %retval = alloca i32, align 4
+  %exn.slot = alloca i8*, align 8
+  %ehselector.slot = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  %exception = call i8* @__cxa_allocate_exception(i64 4) #1
+  %0 = bitcast i8* %exception to i32*
+  store i32 1, i32* %0, align 16
+  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #2
+          to label %unreachable unwind label %lpad
+
+lpad:                                             ; preds = %entry
+  %1 = landingpad { i8*, i32 }
+          catch i8* null
+  %2 = extractvalue { i8*, i32 } %1, 0
+  store i8* %2, i8** %exn.slot, align 8
+  %3 = extractvalue { i8*, i32 } %1, 1
+  store i32 %3, i32* %ehselector.slot, align 4
+  br label %catch
+
+catch:                                            ; preds = %lpad
+  %exn = load i8*, i8** %exn.slot, align 8
+  %4 = call i8* @__cxa_begin_catch(i8* %exn) #1
+  store i32 2, i32* %retval, align 4
+  call void @__cxa_end_catch()
+  br label %return
+
+try.cont:                                         ; No predecessors!
+  store i32 1, i32* %retval, align 4
+  br label %return
+
+return:                                           ; preds = %try.cont, %catch
+  %5 = load i32, i32* %retval, align 4
+  ret i32 %5
+
+unreachable:                                      ; preds = %entry
+  unreachable
+}
+
+; ASM:     GCC_except_table0:
+; ASM:     .Lexception0:
+; ASM:     	.byte	255                             # @LPStart Encoding = omit
+; ASM:     	.byte	3                               # @TType Encoding = udata4
+
+; NO128:   	.byte	49
+; NO128:   	.byte	3                               # Call site Encoding = udata4
+; NO128:   	.byte	39
+; NO128:    .long	.Lfunc_begin0-.Lfunc_begin0     # >> Call Site 1 <<
+; NO128:    .long	.Ltmp0-.Lfunc_begin0            #   Call between .Lfunc_begin0 and .Ltmp0
+; NO128:    .long	0                               #     has no landing pad
+; NO128:    .byte	0                               #   On action: cleanup
+; NO128:    .long	.Ltmp0-.Lfunc_begin0            # >> Call Site 2 <<
+; NO128:    .long	.Ltmp1-.Ltmp0                   #   Call between .Ltmp0 and .Ltmp1
+; NO128:    .long	.Ltmp2-.Lfunc_begin0            #     jumps to .Ltmp2
+; NO128:    .byte	1                               #   On action: 1
+; NO128:    .long	.Ltmp1-.Lfunc_begin0            # >> Call Site 3 <<
+; NO128:    .long	.Lfunc_end0-.Ltmp1              #   Call between .Ltmp1 and .Lfunc_end0
+; NO128:    .long	0                               #     has no landing pad
+; NO128:    .byte	0                               #   On action: cleanup
+
+; ULEB128: 	.uleb128 .Lttbase0-.Lttbaseref0
+; ULEB128: .Lttbaseref0:
+; ULEB128: 	.byte	1                               # Call site Encoding = uleb128
+; ULEB128: 	.uleb128 .Lcst_end0-.Lcst_begin0
+; ULEB128: .Lcst_begin0:
+; ULEB128: 	.uleb128 .Lfunc_begin0-.Lfunc_begin0    # >> Call Site 1 <<
+; ULEB128: 	.uleb128 .Ltmp0-.Lfunc_begin0           #   Call between .Lfunc_begin0 and .Ltmp0
+; ULEB128: 	.byte	0                               #     has no landing pad
+; ULEB128: 	.byte	0                               #   On action: cleanup
+; ULEB128: 	.uleb128 .Ltmp0-.Lfunc_begin0           # >> Call Site 2 <<
+; ULEB128: 	.uleb128 .Ltmp1-.Ltmp0                  #   Call between .Ltmp0 and .Ltmp1
+; ULEB128: 	.uleb128 .Ltmp2-.Lfunc_begin0           #     jumps to .Ltmp2
+; ULEB128: 	.byte	1                               #   On action: 1
+; ULEB128: 	.uleb128 .Ltmp1-.Lfunc_begin0           # >> Call Site 3 <<
+; ULEB128: 	.uleb128 .Lfunc_end0-.Ltmp1             #   Call between .Ltmp1 and .Lfunc_end0
+; ULEB128: 	.byte	0                               #     has no landing pad
+; ULEB128: 	.byte	0                               #   On action: cleanup
+
+; ASM:     .Lcst_end0:
+; ASM:     	.byte	1                               # >> Action Record 1 <<
+; ASM:                                             #   Catch TypeInfo 1
+; ASM:     	.byte	0                               #   No further actions
+; ASM:     	.p2align	2
+; ASM:                                             # >> Catch TypeInfos <<
+; ASM:     	.long	0                               # TypeInfo 1
+; ASM:     .Lttbase0:
+; ASM:     	.p2align	2
+
+declare dso_local i8* @__cxa_allocate_exception(i64)
+declare dso_local void @__cxa_throw(i8*, i8*, i8*)
+declare dso_local i32 @__gxx_personality_v0(...)
+declare dso_local i8* @__cxa_begin_catch(i8*)
+declare dso_local void @__cxa_end_catch()


        


More information about the llvm-branch-commits mailing list