1
0
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:
jasonliu 2020-12-02 18:46:58 +00:00
parent 5d27c8ae50
commit 59a39cf74c
8 changed files with 215 additions and 8 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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))

View File

@ -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*)

View 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()