xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for writing DWARF exception info into asm files.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "DwarfException.h"
140b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
17*81ad6265SDimitry Andric #include "llvm/IR/Function.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric ARMException::ARMException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {}
230b57cec5SDimitry Andric 
24*81ad6265SDimitry Andric ARMException::~ARMException() = default;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric ARMTargetStreamer &ARMException::getTargetStreamer() {
270b57cec5SDimitry Andric   MCTargetStreamer &TS = *Asm->OutStreamer->getTargetStreamer();
280b57cec5SDimitry Andric   return static_cast<ARMTargetStreamer &>(TS);
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric void ARMException::beginFunction(const MachineFunction *MF) {
320b57cec5SDimitry Andric   if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
330b57cec5SDimitry Andric     getTargetStreamer().emitFnStart();
340b57cec5SDimitry Andric   // See if we need call frame info.
35fe6060f1SDimitry Andric   AsmPrinter::CFISection CFISecType = Asm->getFunctionCFISectionType(*MF);
36fe6060f1SDimitry Andric   assert(CFISecType != AsmPrinter::CFISection::EH &&
370b57cec5SDimitry Andric          "non-EH CFI not yet supported in prologue with EHABI lowering");
380b57cec5SDimitry Andric 
39fe6060f1SDimitry Andric   if (CFISecType == AsmPrinter::CFISection::Debug) {
400b57cec5SDimitry Andric     if (!hasEmittedCFISections) {
41fe6060f1SDimitry Andric       if (Asm->getModuleCFISectionType() == AsmPrinter::CFISection::Debug)
425ffd83dbSDimitry Andric         Asm->OutStreamer->emitCFISections(false, true);
430b57cec5SDimitry Andric       hasEmittedCFISections = true;
440b57cec5SDimitry Andric     }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric     shouldEmitCFI = true;
475ffd83dbSDimitry Andric     Asm->OutStreamer->emitCFIStartProc(false);
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information.
520b57cec5SDimitry Andric ///
530b57cec5SDimitry Andric void ARMException::endFunction(const MachineFunction *MF) {
540b57cec5SDimitry Andric   ARMTargetStreamer &ATS = getTargetStreamer();
550b57cec5SDimitry Andric   const Function &F = MF->getFunction();
560b57cec5SDimitry Andric   const Function *Per = nullptr;
570b57cec5SDimitry Andric   if (F.hasPersonalityFn())
580b57cec5SDimitry Andric     Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
590b57cec5SDimitry Andric   bool forceEmitPersonality =
600b57cec5SDimitry Andric     F.hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
610b57cec5SDimitry Andric     F.needsUnwindTableEntry();
620b57cec5SDimitry Andric   bool shouldEmitPersonality = forceEmitPersonality ||
630b57cec5SDimitry Andric     !MF->getLandingPads().empty();
640b57cec5SDimitry Andric   if (!Asm->MF->getFunction().needsUnwindTableEntry() &&
650b57cec5SDimitry Andric       !shouldEmitPersonality)
660b57cec5SDimitry Andric     ATS.emitCantUnwind();
670b57cec5SDimitry Andric   else if (shouldEmitPersonality) {
680b57cec5SDimitry Andric     // Emit references to personality.
690b57cec5SDimitry Andric     if (Per) {
700b57cec5SDimitry Andric       MCSymbol *PerSym = Asm->getSymbol(Per);
710b57cec5SDimitry Andric       ATS.emitPersonality(PerSym);
720b57cec5SDimitry Andric     }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric     // Emit .handlerdata directive.
750b57cec5SDimitry Andric     ATS.emitHandlerData();
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric     // Emit actual exception table
780b57cec5SDimitry Andric     emitExceptionTable();
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
820b57cec5SDimitry Andric     ATS.emitFnEnd();
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric void ARMException::emitTypeInfos(unsigned TTypeEncoding,
860b57cec5SDimitry Andric                                  MCSymbol *TTBaseLabel) {
870b57cec5SDimitry Andric   const MachineFunction *MF = Asm->MF;
880b57cec5SDimitry Andric   const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
890b57cec5SDimitry Andric   const std::vector<unsigned> &FilterIds = MF->getFilterIds();
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   int Entry = 0;
940b57cec5SDimitry Andric   // Emit the Catch TypeInfos.
950b57cec5SDimitry Andric   if (VerboseAsm && !TypeInfos.empty()) {
960b57cec5SDimitry Andric     Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
97*81ad6265SDimitry Andric     Asm->OutStreamer->addBlankLine();
980b57cec5SDimitry Andric     Entry = TypeInfos.size();
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   for (const GlobalValue *GV : reverse(TypeInfos)) {
1020b57cec5SDimitry Andric     if (VerboseAsm)
1030b57cec5SDimitry Andric       Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
1045ffd83dbSDimitry Andric     Asm->emitTTypeReference(GV, TTypeEncoding);
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1075ffd83dbSDimitry Andric   Asm->OutStreamer->emitLabel(TTBaseLabel);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // Emit the Exception Specifications.
1100b57cec5SDimitry Andric   if (VerboseAsm && !FilterIds.empty()) {
1110b57cec5SDimitry Andric     Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
112*81ad6265SDimitry Andric     Asm->OutStreamer->addBlankLine();
1130b57cec5SDimitry Andric     Entry = 0;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric   for (std::vector<unsigned>::const_iterator
1160b57cec5SDimitry Andric          I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
1170b57cec5SDimitry Andric     unsigned TypeID = *I;
1180b57cec5SDimitry Andric     if (VerboseAsm) {
1190b57cec5SDimitry Andric       --Entry;
1200b57cec5SDimitry Andric       if (TypeID != 0)
1210b57cec5SDimitry Andric         Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
1220b57cec5SDimitry Andric     }
1230b57cec5SDimitry Andric 
1245ffd83dbSDimitry Andric     Asm->emitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]),
1250b57cec5SDimitry Andric                             TTypeEncoding);
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric }
128