1*0b57cec5SDimitry Andric //===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains support for writing DWARF exception info into asm files. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "DwarfException.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 15*0b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 17*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 18*0b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 19*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 20*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 22*0b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 23*0b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 24*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 26*0b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric ARMException::ARMException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {} 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric ARMException::~ARMException() {} 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric ARMTargetStreamer &ARMException::getTargetStreamer() { 34*0b57cec5SDimitry Andric MCTargetStreamer &TS = *Asm->OutStreamer->getTargetStreamer(); 35*0b57cec5SDimitry Andric return static_cast<ARMTargetStreamer &>(TS); 36*0b57cec5SDimitry Andric } 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric void ARMException::beginFunction(const MachineFunction *MF) { 39*0b57cec5SDimitry Andric if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) 40*0b57cec5SDimitry Andric getTargetStreamer().emitFnStart(); 41*0b57cec5SDimitry Andric // See if we need call frame info. 42*0b57cec5SDimitry Andric AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); 43*0b57cec5SDimitry Andric assert(MoveType != AsmPrinter::CFI_M_EH && 44*0b57cec5SDimitry Andric "non-EH CFI not yet supported in prologue with EHABI lowering"); 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric if (MoveType == AsmPrinter::CFI_M_Debug) { 47*0b57cec5SDimitry Andric if (!hasEmittedCFISections) { 48*0b57cec5SDimitry Andric if (Asm->needsOnlyDebugCFIMoves()) 49*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFISections(false, true); 50*0b57cec5SDimitry Andric hasEmittedCFISections = true; 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric shouldEmitCFI = true; 54*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFIStartProc(false); 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 59*0b57cec5SDimitry Andric /// 60*0b57cec5SDimitry Andric void ARMException::endFunction(const MachineFunction *MF) { 61*0b57cec5SDimitry Andric ARMTargetStreamer &ATS = getTargetStreamer(); 62*0b57cec5SDimitry Andric const Function &F = MF->getFunction(); 63*0b57cec5SDimitry Andric const Function *Per = nullptr; 64*0b57cec5SDimitry Andric if (F.hasPersonalityFn()) 65*0b57cec5SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 66*0b57cec5SDimitry Andric bool forceEmitPersonality = 67*0b57cec5SDimitry Andric F.hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 68*0b57cec5SDimitry Andric F.needsUnwindTableEntry(); 69*0b57cec5SDimitry Andric bool shouldEmitPersonality = forceEmitPersonality || 70*0b57cec5SDimitry Andric !MF->getLandingPads().empty(); 71*0b57cec5SDimitry Andric if (!Asm->MF->getFunction().needsUnwindTableEntry() && 72*0b57cec5SDimitry Andric !shouldEmitPersonality) 73*0b57cec5SDimitry Andric ATS.emitCantUnwind(); 74*0b57cec5SDimitry Andric else if (shouldEmitPersonality) { 75*0b57cec5SDimitry Andric // Emit references to personality. 76*0b57cec5SDimitry Andric if (Per) { 77*0b57cec5SDimitry Andric MCSymbol *PerSym = Asm->getSymbol(Per); 78*0b57cec5SDimitry Andric Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); 79*0b57cec5SDimitry Andric ATS.emitPersonality(PerSym); 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric // Emit .handlerdata directive. 83*0b57cec5SDimitry Andric ATS.emitHandlerData(); 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric // Emit actual exception table 86*0b57cec5SDimitry Andric emitExceptionTable(); 87*0b57cec5SDimitry Andric } 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) 90*0b57cec5SDimitry Andric ATS.emitFnEnd(); 91*0b57cec5SDimitry Andric } 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric void ARMException::emitTypeInfos(unsigned TTypeEncoding, 94*0b57cec5SDimitry Andric MCSymbol *TTBaseLabel) { 95*0b57cec5SDimitry Andric const MachineFunction *MF = Asm->MF; 96*0b57cec5SDimitry Andric const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 97*0b57cec5SDimitry Andric const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric int Entry = 0; 102*0b57cec5SDimitry Andric // Emit the Catch TypeInfos. 103*0b57cec5SDimitry Andric if (VerboseAsm && !TypeInfos.empty()) { 104*0b57cec5SDimitry Andric Asm->OutStreamer->AddComment(">> Catch TypeInfos <<"); 105*0b57cec5SDimitry Andric Asm->OutStreamer->AddBlankLine(); 106*0b57cec5SDimitry Andric Entry = TypeInfos.size(); 107*0b57cec5SDimitry Andric } 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric for (const GlobalValue *GV : reverse(TypeInfos)) { 110*0b57cec5SDimitry Andric if (VerboseAsm) 111*0b57cec5SDimitry Andric Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); 112*0b57cec5SDimitry Andric Asm->EmitTTypeReference(GV, TTypeEncoding); 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric Asm->OutStreamer->EmitLabel(TTBaseLabel); 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric // Emit the Exception Specifications. 118*0b57cec5SDimitry Andric if (VerboseAsm && !FilterIds.empty()) { 119*0b57cec5SDimitry Andric Asm->OutStreamer->AddComment(">> Filter TypeInfos <<"); 120*0b57cec5SDimitry Andric Asm->OutStreamer->AddBlankLine(); 121*0b57cec5SDimitry Andric Entry = 0; 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric for (std::vector<unsigned>::const_iterator 124*0b57cec5SDimitry Andric I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 125*0b57cec5SDimitry Andric unsigned TypeID = *I; 126*0b57cec5SDimitry Andric if (VerboseAsm) { 127*0b57cec5SDimitry Andric --Entry; 128*0b57cec5SDimitry Andric if (TypeID != 0) 129*0b57cec5SDimitry Andric Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric Asm->EmitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]), 133*0b57cec5SDimitry Andric TTypeEncoding); 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric } 136