diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -612,6 +612,7 @@ static const EHPersonality MSVC_C_specific_handler; static const EHPersonality MSVC_CxxFrameHandler3; static const EHPersonality GNU_Wasm_CPlusPlus; + static const EHPersonality XL_CPlusPlus; /// Does this personality use landingpads or the family of pad instructions /// designed to form funclets? diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -113,6 +113,8 @@ EHPersonality::MSVC_CxxFrameHandler3 = { "__CxxFrameHandler3", nullptr }; const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = { "__gxx_wasm_personality_v0", nullptr }; +const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1", + nullptr}; static const EHPersonality &getCPersonality(const TargetInfo &Target, const LangOptions &L) { @@ -161,6 +163,8 @@ const llvm::Triple &T = Target.getTriple(); if (T.isWindowsMSVCEnvironment()) return EHPersonality::MSVC_CxxFrameHandler3; + if (T.isOSAIX()) + return EHPersonality::XL_CPlusPlus; if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; if (L.DWARFExceptions) diff --git a/clang/test/CodeGenCXX/personality.cpp b/clang/test/CodeGenCXX/personality.cpp --- a/clang/test/CodeGenCXX/personality.cpp +++ b/clang/test/CodeGenCXX/personality.cpp @@ -12,6 +12,9 @@ // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fseh-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SEH // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fsjlj-exceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNU-SJLJ +// RUN: %clang_cc1 -triple powerpc-unknown-aix-xcoff -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-AIX +// RUN: %clang_cc1 -triple powerpc64-unknown-aix-xcoff -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-AIX + extern void g(); // CHECK-GNU: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) @@ -21,6 +24,8 @@ // CHECK-WIN: personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) +// CHECK-AIX: personality i8* bitcast (i32 (...)* @__xlcxx_personality_v1 to i8*) + void f() { try { g(); diff --git a/llvm/include/llvm/Analysis/EHPersonalities.h b/llvm/include/llvm/Analysis/EHPersonalities.h --- a/llvm/include/llvm/Analysis/EHPersonalities.h +++ b/llvm/include/llvm/Analysis/EHPersonalities.h @@ -32,7 +32,8 @@ MSVC_CXX, CoreCLR, Rust, - Wasm_CXX + Wasm_CXX, + XL_CXX }; /// See if the given exception handling personality function is one diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -603,7 +603,7 @@ unsigned GetSizeOfEncodedValue(unsigned Encoding) const; /// Emit reference to a ttype global with a specified encoding. - void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; + virtual void emitTTypeReference(const GlobalValue *GV, unsigned Encoding); /// Emit a reference to a symbol for use in dwarf. Different object formats /// represent this in different ways. Some use a relocation others encode diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -22,6 +22,7 @@ ARM, ///< ARM EHABI WinEH, ///< Windows Exception Handling Wasm, ///< WebAssembly Exception Handling + AIX, ///< AIX Exception Handling }; enum class DebugCompressionType { diff --git a/llvm/lib/Analysis/EHPersonalities.cpp b/llvm/lib/Analysis/EHPersonalities.cpp --- a/llvm/lib/Analysis/EHPersonalities.cpp +++ b/llvm/lib/Analysis/EHPersonalities.cpp @@ -39,6 +39,7 @@ .Case("ProcessCLRException", EHPersonality::CoreCLR) .Case("rust_eh_personality", EHPersonality::Rust) .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX) + .Case("__xlcxx_personality_v1", EHPersonality::XL_CXX) .Default(EHPersonality::Unknown); } @@ -57,6 +58,8 @@ case EHPersonality::CoreCLR: return "ProcessCLRException"; case EHPersonality::Rust: return "rust_eh_personality"; case EHPersonality::Wasm_CXX: return "__gxx_wasm_personality_v0"; + case EHPersonality::XL_CXX: + return "__xlcxx_personality_v1"; case EHPersonality::Unknown: llvm_unreachable("Unknown EHPersonality!"); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp b/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/AsmPrinter/AIXException.cpp @@ -0,0 +1,82 @@ +//===-- CodeGen/AsmPrinter/AIXException.cpp - AIX Exception Impl ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing AIX exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCSectionXCOFF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +AIXException::AIXException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {} + +void AIXException::emitExceptionInfoTable(const MCSymbol *LSDA, + const MCSymbol *PerSym) { + // Generate EH Info Table. + // The EH Info Table, aka, 'compat unwind section' on AIX, have the following + // format: struct eh_info_t { + // unsigned version; /* EH info verion 0 */ + // #if defined(__64BIT__) + // char _pad[4]; /* padding */ + // #endif + // unsigned long lsda; /* Pointer to LSDA */ + // unsigned long personality; /* Pointer to the personality routine */ + // } + + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getCompactUnwindSection()); + MCSymbol *EHInfoLabel = MMI->getContext().getOrCreateSymbol( + "__ehinfo." + Twine(Asm->getFunctionNumber())); + Asm->OutStreamer->emitLabel(EHInfoLabel); + + // Version number. + Asm->emitInt32(0); + + const DataLayout &DL = MMI->getModule()->getDataLayout(); + const unsigned PointerSize = DL.getPointerSize(); + + // Add necessary paddings in 64 bit mode. + Asm->OutStreamer->emitValueToAlignment(PointerSize); + + // LSDA location. + Asm->OutStreamer->emitValue(MCSymbolRefExpr::create(LSDA, Asm->OutContext), + PointerSize); + + // Personality routine. + Asm->OutStreamer->emitValue(MCSymbolRefExpr::create(PerSym, Asm->OutContext), + PointerSize); +} + +void AIXException::endFunction(const MachineFunction *MF) { + const Function &F = MF->getFunction(); + bool HasLandingPads = !MF->getLandingPads().empty(); + const Function *Per = nullptr; + if (F.hasPersonalityFn()) + Per = dyn_cast(F.getPersonalityFn()->stripPointerCasts()); + bool EmitEHBlock = + HasLandingPads || (F.hasPersonalityFn() && + !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + F.needsUnwindTableEntry()); + + if (!EmitEHBlock) + return; + + const MCSymbol *LSDALabel = emitExceptionTable(); + const MCSymbol *PerSym = Asm->TM.getSymbol(Per); + + emitExceptionInfoTable(LSDALabel, PerSym); +} + +} // End of namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -380,6 +380,9 @@ case ExceptionHandling::Wasm: ES = new WasmException(this); break; + case ExceptionHandling::AIX: + ES = new AIXException(this); + break; } if (ES) Handlers.emplace_back(std::unique_ptr(ES), EHTimerName, diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -98,6 +98,12 @@ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8 : return "indirect pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel | + dwarf::DW_EH_PE_sdata4: + return "indirect datarel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel | + dwarf::DW_EH_PE_sdata8: + return "indirect datarel sdata8"; } return ""; @@ -138,8 +144,7 @@ } } -void AsmPrinter::emitTTypeReference(const GlobalValue *GV, - unsigned Encoding) const { +void AsmPrinter::emitTTypeReference(const GlobalValue *GV, unsigned Encoding) { if (GV) { const TargetLoweringObjectFile &TLOF = getObjFileLowering(); diff --git a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt --- a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_component_library(LLVMAsmPrinter AccelTable.cpp AddressPool.cpp + AIXException.cpp ARMException.cpp AsmPrinter.cpp AsmPrinterDwarf.cpp diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -92,6 +92,20 @@ /// Gather and emit post-function exception information. void endFunction(const MachineFunction *) override; }; + +class LLVM_LIBRARY_VISIBILITY AIXException : public DwarfCFIExceptionBase { + /// This is AIX's compat unwind section, which unwinder would use + /// to find the location of LSDA area and personality rountine. + void emitExceptionInfoTable(const MCSymbol *LSDA, const MCSymbol *PerSym); + +public: + AIXException(AsmPrinter *A); + + void endModule() override {} + void beginFunction(const MachineFunction *MF) override {} + + void endFunction(const MachineFunction *MF) override; +}; } // End of namespace llvm #endif diff --git a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp --- a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -288,11 +288,13 @@ assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); - // For Dwarf exception handling (SjLj handling doesn't use this). If some - // instruction between the previous try-range and this one may throw, - // create a call-site entry with no landing pad for the region between the - // try-ranges. - if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) { + // For Dwarf and AIX exception handling (SjLj handling doesn't use this). + // If some instruction between the previous try-range and this one may + // throw, create a call-site entry with no landing pad for the region + // between the try-ranges. + if (SawPotentiallyThrowing && + (Asm->MAI->usesCFIForEH() || + Asm->MAI->getExceptionHandlingType() == ExceptionHandling::AIX)) { CallSites.push_back({LastLabel, BeginLabel, nullptr, 0}); PreviousIsInvoke = false; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2272,9 +2272,13 @@ void TargetLoweringObjectFileXCOFF::Initialize(MCContext &Ctx, const TargetMachine &TgtM) { TargetLoweringObjectFile::Initialize(Ctx, TgtM); - TTypeEncoding = 0; + TTypeEncoding = + dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel | + (TgtM.getTargetTriple().isArch32Bit() ? dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_sdata8); PersonalityEncoding = 0; LSDAEncoding = 0; + CallSiteEncoding = dwarf::DW_EH_PE_udata4; } MCSection *TargetLoweringObjectFileXCOFF::getStaticCtorSection( diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -735,6 +735,7 @@ LLVM_FALLTHROUGH; case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: + case ExceptionHandling::AIX: addPass(createDwarfEHPass(getOptLevel())); break; case ExceptionHandling::WinEH: diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp --- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp @@ -37,6 +37,8 @@ HasDotTypeDotSizeDirective = false; UseIntegratedAssembler = false; NeedsFunctionDescriptors = true; + + ExceptionsType = ExceptionHandling::AIX; } bool MCAsmInfoXCOFF::isAcceptableChar(char C) const { diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -883,6 +883,14 @@ // The TOC-base always has 0 size, but 4 byte alignment. TOCBaseSection->setAlignment(Align(4)); + LSDASection = Ctx->getXCOFFSection(".gcc_except_table", + XCOFF::StorageMappingClass::XMC_RO, + XCOFF::XTY_SD, SectionKind::getReadOnly()); + + CompactUnwindSection = + Ctx->getXCOFFSection(".eh_info_table", XCOFF::StorageMappingClass::XMC_RW, + XCOFF::XTY_SD, SectionKind::getData()); + // DWARF sections for XCOFF are not csects. They are special STYP_DWARF // sections, and the individual DWARF sections are distinguished by their // section subtype. diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -193,6 +193,8 @@ void emitInstruction(const MachineInstr *MI) override; bool doFinalization(Module &M) override; + + void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override; }; } // end anonymous namespace @@ -2056,6 +2058,23 @@ } } +void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV, + unsigned Encoding) { + if (GV) { + MCSymbol *TypeInfoSym = TM.getSymbol(GV); + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym); + const MCSymbol *TOCBaseSym = + cast(getObjFileLowering().getTOCBaseSection()) + ->getQualNameSymbol(); + auto &Ctx = OutStreamer->getContext(); + const MCExpr *Exp = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCEntry, Ctx), + MCSymbolRefExpr::create(TOCBaseSym, Ctx), Ctx); + OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding)); + } else + OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding)); +} + // Return a pass that prints the PPC assembly code for a MachineFunction to the // given output stream. static AsmPrinter * diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3109,6 +3109,7 @@ case EHPersonality::MSVC_CXX: case EHPersonality::CoreCLR: case EHPersonality::Wasm_CXX: + case EHPersonality::XL_CXX: return TypeInfo->isNullValue(); } llvm_unreachable("invalid enum"); diff --git a/llvm/test/CodeGen/PowerPC/aix-exception.ll b/llvm/test/CodeGen/PowerPC/aix-exception.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-exception.ll @@ -0,0 +1,152 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec < %s | \ +; RUN: FileCheck --check-prefixes=ASM,ASM32 %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec < %s | \ +; RUN: FileCheck --check-prefixes=ASM,ASM64 %s + +@_ZTIi = external constant i8* + +define void @_Z9throwFuncv() { +entry: + %exception = call i8* @__cxa_allocate_exception(i32 4) #2 + %0 = bitcast i8* %exception to i32* + store i32 1, i32* %0, align 16 + call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3 + unreachable +} + +; ASM: ._Z9throwFuncv: +; ASM: bl .__cxa_allocate_exception[PR] +; ASM: nop +; ASM32: lwz 4, L..C0(2) +; ASM64: ld 4, L..C0(2) +; ASM: bl .__cxa_throw[PR] +; ASM: nop + +define i32 @_Z9catchFuncv() personality i8* bitcast (i32 (...)* @__xlcxx_personality_v1 to i8*) { +entry: + %retval = alloca i32, align 4 + %exn.slot = alloca i8*, align 4 + %ehselector.slot = alloca i32, align 4 + %0 = alloca i32, align 4 + invoke void @_Z9throwFuncv() + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %entry + br label %try.cont + +lpad: ; preds = %entry + %1 = landingpad { i8*, i32 } + catch i8* bitcast (i8** @_ZTIi to i8*) + %2 = extractvalue { i8*, i32 } %1, 0 + store i8* %2, i8** %exn.slot, align 4 + %3 = extractvalue { i8*, i32 } %1, 1 + store i32 %3, i32* %ehselector.slot, align 4 + br label %catch.dispatch + +catch.dispatch: ; preds = %lpad + %sel = load i32, i32* %ehselector.slot, align 4 + %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 + %matches = icmp eq i32 %sel, %4 + br i1 %matches, label %catch, label %eh.resume + +catch: ; preds = %catch.dispatch + %exn = load i8*, i8** %exn.slot, align 4 + %5 = call i8* @__cxa_begin_catch(i8* %exn) #2 + %6 = bitcast i8* %5 to i32* + %7 = load i32, i32* %6, align 4 + store i32 %7, i32* %0, align 4 + store i32 2, i32* %retval, align 4 + call void @__cxa_end_catch() #2 + br label %return + +try.cont: ; preds = %invoke.cont + store i32 1, i32* %retval, align 4 + br label %return + +return: ; preds = %try.cont, %catch + %8 = load i32, i32* %retval, align 4 + ret i32 %8 + +eh.resume: ; preds = %catch.dispatch + %exn1 = load i8*, i8** %exn.slot, align 4 + %sel2 = load i32, i32* %ehselector.slot, align 4 + %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn1, 0 + %lpad.val3 = insertvalue { i8*, i32 } %lpad.val, i32 %sel2, 1 + resume { i8*, i32 } %lpad.val3 +} + +; ASM: ._Z9catchFuncv: +; ASM: L..func_begin0: +; ASM: # %bb.0: # %entry +; ASM: mflr 0 +; ASM: L..tmp0: +; ASM: bl ._Z9throwFuncv +; ASM: nop +; ASM: L..tmp1: +; ASM: # %bb.1: # %invoke.cont +; ASM: li 3, 1 +; ASM: L..BB1_2: # %return +; ASM: mtlr 0 +; ASM: blr +; ASM: L..BB1_3: # %lpad +; ASM: L..tmp2: +; ASM: bl .__cxa_begin_catch[PR] +; ASM: nop +; ASM: bl .__cxa_end_catch[PR] +; ASM: nop +; ASM: b L..BB1_2 +; ASM: L..func_end0: + +; ASM: .csect .gcc_except_table[RO],2 +; ASM: .align 2 +; ASM: GCC_except_table1: +; ASM: L..exception0: +; 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: +; ASM: .byte 3 # Call site Encoding = udata4 +; ASM: .uleb128 L..cst_end0-L..cst_begin0 +; ASM: L..cst_begin0: +; 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 +; ASM: .byte 1 # On action: 1 +; ASM: .vbyte 4, L..tmp1-L..func_begin0 # >> Call Site 2 << +; ASM: .vbyte 4, L..func_end0-L..tmp1 # Call between L..tmp1 and L..func_end0 +; ASM: .vbyte 4, 0 # has no landing pad +; ASM: .byte 0 # On action: cleanup +; ASM: L..cst_end0: +; ASM: .byte 1 # >> Action Record 1 << +; ASM: # Catch TypeInfo 1 +; ASM: .byte 0 # No further actions +; ASM: .align 2 +; ASM: # >> Catch TypeInfos << +; ASM32: .vbyte 4, L..C0-TOC[TC0] # TypeInfo 1 +; ASM64: .vbyte 8, L..C0-TOC[TC0] # TypeInfo 1 +; ASM: L..ttbase0: +; ASM: .align 2 +; ASM: .csect .eh_info_table[RW],2 +; ASM: __ehinfo.1: +; ASM: .vbyte 4, 0 +; ASM32: .align 2 +; ASM32: .vbyte 4, GCC_except_table1 +; ASM32: .vbyte 4, __xlcxx_personality_v1[DS] +; ASM64: .align 3 +; ASM64: .vbyte 8, GCC_except_table1 +; ASM64: .vbyte 8, __xlcxx_personality_v1[DS] + +; ASM: .toc +; ASM: L..C0: +; ASM: .tc _ZTIi[TC],_ZTIi[UA] + +declare i8* @__cxa_allocate_exception(i32) +declare void @__cxa_throw(i8*, i8*, i8*) +declare i32 @__xlcxx_personality_v1(...) +declare i32 @llvm.eh.typeid.for(i8*) +declare i8* @__cxa_begin_catch(i8*) +declare void @__cxa_end_catch()