mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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
This commit is contained in:
parent
5d27c8ae50
commit
59a39cf74c
@ -186,6 +186,9 @@ protected:
|
||||
/// 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 @@ public:
|
||||
return UseDotAlignForAlignment;
|
||||
}
|
||||
|
||||
bool hasLEB128Directives() const { return HasLEB128Directives; }
|
||||
|
||||
const char *getZeroDirective() const { return ZeroDirective; }
|
||||
bool doesZeroDirectiveSupportNonZeroValue() const {
|
||||
return ZeroDirectiveSupportsNonZeroValue;
|
||||
|
@ -157,7 +157,7 @@ public:
|
||||
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;
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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*)
|
||||
|
103
test/CodeGen/X86/gnu-eh-alternative.ll
Normal file
103
test/CodeGen/X86/gnu-eh-alternative.ll
Normal file
@ -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
|
||||
|
||||
@_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()
|
Loading…
x
Reference in New Issue
Block a user