16b943ff3SDimitry Andric //===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===// 26b943ff3SDimitry Andric // 3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66b943ff3SDimitry Andric // 76b943ff3SDimitry Andric //===----------------------------------------------------------------------===// 86b943ff3SDimitry Andric // 96b943ff3SDimitry Andric // This file contains support for writing DWARF exception info into asm files. 106b943ff3SDimitry Andric // 116b943ff3SDimitry Andric //===----------------------------------------------------------------------===// 126b943ff3SDimitry Andric 136b943ff3SDimitry Andric #include "DwarfException.h" 144a16efa3SDimitry Andric #include "llvm/ADT/Twine.h" 156b943ff3SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 166b943ff3SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 17145449b1SDimitry Andric #include "llvm/IR/Function.h" 186b943ff3SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 196b943ff3SDimitry Andric #include "llvm/MC/MCStreamer.h" 206b943ff3SDimitry Andric using namespace llvm; 216b943ff3SDimitry Andric ARMException(AsmPrinter * A)22e3b55780SDimitry AndricARMException::ARMException(AsmPrinter *A) : EHStreamer(A) {} 236b943ff3SDimitry Andric 24145449b1SDimitry Andric ARMException::~ARMException() = default; 256b943ff3SDimitry Andric getTargetStreamer()26f8af5cf6SDimitry AndricARMTargetStreamer &ARMException::getTargetStreamer() { 275a5ac124SDimitry Andric MCTargetStreamer &TS = *Asm->OutStreamer->getTargetStreamer(); 28f8af5cf6SDimitry Andric return static_cast<ARMTargetStreamer &>(TS); 29f8af5cf6SDimitry Andric } 30f8af5cf6SDimitry Andric beginFunction(const MachineFunction * MF)315ca98fd9SDimitry Andricvoid ARMException::beginFunction(const MachineFunction *MF) { 325ca98fd9SDimitry Andric if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) 33f8af5cf6SDimitry Andric getTargetStreamer().emitFnStart(); 345ca98fd9SDimitry Andric // See if we need call frame info. 35344a3780SDimitry Andric AsmPrinter::CFISection CFISecType = Asm->getFunctionCFISectionType(*MF); 36344a3780SDimitry Andric assert(CFISecType != AsmPrinter::CFISection::EH && 375ca98fd9SDimitry Andric "non-EH CFI not yet supported in prologue with EHABI lowering"); 38b915e9e0SDimitry Andric 39344a3780SDimitry Andric if (CFISecType == AsmPrinter::CFISection::Debug) { 40b915e9e0SDimitry Andric if (!hasEmittedCFISections) { 41344a3780SDimitry Andric if (Asm->getModuleCFISectionType() == AsmPrinter::CFISection::Debug) 42cfca06d7SDimitry Andric Asm->OutStreamer->emitCFISections(false, true); 43b915e9e0SDimitry Andric hasEmittedCFISections = true; 44b915e9e0SDimitry Andric } 45b915e9e0SDimitry Andric 465ca98fd9SDimitry Andric shouldEmitCFI = true; 47cfca06d7SDimitry Andric Asm->OutStreamer->emitCFIStartProc(false); 485ca98fd9SDimitry Andric } 496b943ff3SDimitry Andric } 506b943ff3SDimitry Andric markFunctionEnd()51e3b55780SDimitry Andricvoid ARMException::markFunctionEnd() { 52e3b55780SDimitry Andric if (shouldEmitCFI) 53e3b55780SDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 54e3b55780SDimitry Andric } 55e3b55780SDimitry Andric 565ca98fd9SDimitry Andric /// endFunction - Gather and emit post-function exception information. 576b943ff3SDimitry Andric /// endFunction(const MachineFunction * MF)585a5ac124SDimitry Andricvoid ARMException::endFunction(const MachineFunction *MF) { 59f8af5cf6SDimitry Andric ARMTargetStreamer &ATS = getTargetStreamer(); 60044eb2f6SDimitry Andric const Function &F = MF->getFunction(); 61ee8648bdSDimitry Andric const Function *Per = nullptr; 62044eb2f6SDimitry Andric if (F.hasPersonalityFn()) 63044eb2f6SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 64ee8648bdSDimitry Andric bool forceEmitPersonality = 65044eb2f6SDimitry Andric F.hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 66044eb2f6SDimitry Andric F.needsUnwindTableEntry(); 67ee8648bdSDimitry Andric bool shouldEmitPersonality = forceEmitPersonality || 68b915e9e0SDimitry Andric !MF->getLandingPads().empty(); 69044eb2f6SDimitry Andric if (!Asm->MF->getFunction().needsUnwindTableEntry() && 70ee8648bdSDimitry Andric !shouldEmitPersonality) 71f8af5cf6SDimitry Andric ATS.emitCantUnwind(); 72ee8648bdSDimitry Andric else if (shouldEmitPersonality) { 736b943ff3SDimitry Andric // Emit references to personality. 74ee8648bdSDimitry Andric if (Per) { 75ee8648bdSDimitry Andric MCSymbol *PerSym = Asm->getSymbol(Per); 76f8af5cf6SDimitry Andric ATS.emitPersonality(PerSym); 776b943ff3SDimitry Andric } 786b943ff3SDimitry Andric 794a16efa3SDimitry Andric // Emit .handlerdata directive. 80f8af5cf6SDimitry Andric ATS.emitHandlerData(); 816b943ff3SDimitry Andric 826b943ff3SDimitry Andric // Emit actual exception table 835ca98fd9SDimitry Andric emitExceptionTable(); 8463faed5bSDimitry Andric } 856b943ff3SDimitry Andric 865ca98fd9SDimitry Andric if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) 87f8af5cf6SDimitry Andric ATS.emitFnEnd(); 886b943ff3SDimitry Andric } 894a16efa3SDimitry Andric emitTypeInfos(unsigned TTypeEncoding,MCSymbol * TTBaseLabel)90eb11fae6SDimitry Andricvoid ARMException::emitTypeInfos(unsigned TTypeEncoding, 91eb11fae6SDimitry Andric MCSymbol *TTBaseLabel) { 92b915e9e0SDimitry Andric const MachineFunction *MF = Asm->MF; 93b915e9e0SDimitry Andric const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 94b915e9e0SDimitry Andric const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 954a16efa3SDimitry Andric 965a5ac124SDimitry Andric bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 974a16efa3SDimitry Andric 984a16efa3SDimitry Andric int Entry = 0; 994a16efa3SDimitry Andric // Emit the Catch TypeInfos. 1004a16efa3SDimitry Andric if (VerboseAsm && !TypeInfos.empty()) { 1015a5ac124SDimitry Andric Asm->OutStreamer->AddComment(">> Catch TypeInfos <<"); 102145449b1SDimitry Andric Asm->OutStreamer->addBlankLine(); 1034a16efa3SDimitry Andric Entry = TypeInfos.size(); 1044a16efa3SDimitry Andric } 1054a16efa3SDimitry Andric 106dd58ef01SDimitry Andric for (const GlobalValue *GV : reverse(TypeInfos)) { 1074a16efa3SDimitry Andric if (VerboseAsm) 1085a5ac124SDimitry Andric Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); 109cfca06d7SDimitry Andric Asm->emitTTypeReference(GV, TTypeEncoding); 1104a16efa3SDimitry Andric } 1114a16efa3SDimitry Andric 112cfca06d7SDimitry Andric Asm->OutStreamer->emitLabel(TTBaseLabel); 113eb11fae6SDimitry Andric 1144a16efa3SDimitry Andric // Emit the Exception Specifications. 1154a16efa3SDimitry Andric if (VerboseAsm && !FilterIds.empty()) { 1165a5ac124SDimitry Andric Asm->OutStreamer->AddComment(">> Filter TypeInfos <<"); 117145449b1SDimitry Andric Asm->OutStreamer->addBlankLine(); 1184a16efa3SDimitry Andric Entry = 0; 1194a16efa3SDimitry Andric } 1204a16efa3SDimitry Andric for (std::vector<unsigned>::const_iterator 1214a16efa3SDimitry Andric I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 1224a16efa3SDimitry Andric unsigned TypeID = *I; 1234a16efa3SDimitry Andric if (VerboseAsm) { 1244a16efa3SDimitry Andric --Entry; 1254a16efa3SDimitry Andric if (TypeID != 0) 1265a5ac124SDimitry Andric Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); 1274a16efa3SDimitry Andric } 1284a16efa3SDimitry Andric 129cfca06d7SDimitry Andric Asm->emitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]), 1304a16efa3SDimitry Andric TTypeEncoding); 1314a16efa3SDimitry Andric } 1324a16efa3SDimitry Andric } 133