13b0f4066SDimitry Andric //===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===//
23b0f4066SDimitry Andric //
33b0f4066SDimitry Andric //                     The LLVM Compiler Infrastructure
43b0f4066SDimitry Andric //
53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source
63b0f4066SDimitry Andric // License. See LICENSE.TXT for details.
73b0f4066SDimitry Andric //
83b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
93b0f4066SDimitry Andric //
103b0f4066SDimitry Andric // This file contains support for writing DWARF exception info into asm files.
113b0f4066SDimitry Andric //
123b0f4066SDimitry Andric //===----------------------------------------------------------------------===//
133b0f4066SDimitry Andric 
143b0f4066SDimitry Andric #include "DwarfException.h"
15139f7f9bSDimitry Andric #include "llvm/ADT/Twine.h"
163b0f4066SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
173b0f4066SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
18139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
1991bc56edSDimitry Andric #include "llvm/IR/Mangler.h"
20139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
213b0f4066SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
223b0f4066SDimitry Andric #include "llvm/MC/MCExpr.h"
233b0f4066SDimitry Andric #include "llvm/MC/MCSection.h"
243b0f4066SDimitry Andric #include "llvm/MC/MCStreamer.h"
253b0f4066SDimitry Andric #include "llvm/MC/MCSymbol.h"
263b0f4066SDimitry Andric #include "llvm/Support/FormattedStream.h"
27139f7f9bSDimitry Andric #include "llvm/Target/TargetOptions.h"
283b0f4066SDimitry Andric using namespace llvm;
293b0f4066SDimitry Andric 
ARMException(AsmPrinter * A)30ff0cc061SDimitry Andric ARMException::ARMException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {}
313b0f4066SDimitry Andric 
~ARMException()323b0f4066SDimitry Andric ARMException::~ARMException() {}
333b0f4066SDimitry Andric 
getTargetStreamer()34f785676fSDimitry Andric ARMTargetStreamer &ARMException::getTargetStreamer() {
35ff0cc061SDimitry Andric   MCTargetStreamer &TS = *Asm->OutStreamer->getTargetStreamer();
36f785676fSDimitry Andric   return static_cast<ARMTargetStreamer &>(TS);
37f785676fSDimitry Andric }
38f785676fSDimitry Andric 
beginFunction(const MachineFunction * MF)3991bc56edSDimitry Andric void ARMException::beginFunction(const MachineFunction *MF) {
4091bc56edSDimitry Andric   if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
41f785676fSDimitry Andric     getTargetStreamer().emitFnStart();
4291bc56edSDimitry Andric   // See if we need call frame info.
4391bc56edSDimitry Andric   AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
4491bc56edSDimitry Andric   assert(MoveType != AsmPrinter::CFI_M_EH &&
4591bc56edSDimitry Andric          "non-EH CFI not yet supported in prologue with EHABI lowering");
46d88c1a5aSDimitry Andric 
4791bc56edSDimitry Andric   if (MoveType == AsmPrinter::CFI_M_Debug) {
48d88c1a5aSDimitry Andric     if (!hasEmittedCFISections) {
4995ec533aSDimitry Andric       if (Asm->needsOnlyDebugCFIMoves())
50d88c1a5aSDimitry Andric         Asm->OutStreamer->EmitCFISections(false, true);
51d88c1a5aSDimitry Andric       hasEmittedCFISections = true;
52d88c1a5aSDimitry Andric     }
53d88c1a5aSDimitry Andric 
5491bc56edSDimitry Andric     shouldEmitCFI = true;
55ff0cc061SDimitry Andric     Asm->OutStreamer->EmitCFIStartProc(false);
5691bc56edSDimitry Andric   }
573b0f4066SDimitry Andric }
583b0f4066SDimitry Andric 
5991bc56edSDimitry Andric /// endFunction - Gather and emit post-function exception information.
603b0f4066SDimitry Andric ///
endFunction(const MachineFunction * MF)61ff0cc061SDimitry Andric void ARMException::endFunction(const MachineFunction *MF) {
62f785676fSDimitry Andric   ARMTargetStreamer &ATS = getTargetStreamer();
632cab237bSDimitry Andric   const Function &F = MF->getFunction();
64875ed548SDimitry Andric   const Function *Per = nullptr;
652cab237bSDimitry Andric   if (F.hasPersonalityFn())
662cab237bSDimitry Andric     Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
67875ed548SDimitry Andric   bool forceEmitPersonality =
682cab237bSDimitry Andric     F.hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
692cab237bSDimitry Andric     F.needsUnwindTableEntry();
70875ed548SDimitry Andric   bool shouldEmitPersonality = forceEmitPersonality ||
71d88c1a5aSDimitry Andric     !MF->getLandingPads().empty();
722cab237bSDimitry Andric   if (!Asm->MF->getFunction().needsUnwindTableEntry() &&
73875ed548SDimitry Andric       !shouldEmitPersonality)
74f785676fSDimitry Andric     ATS.emitCantUnwind();
75875ed548SDimitry Andric   else if (shouldEmitPersonality) {
763b0f4066SDimitry Andric     // Emit references to personality.
77875ed548SDimitry Andric     if (Per) {
78875ed548SDimitry Andric       MCSymbol *PerSym = Asm->getSymbol(Per);
79ff0cc061SDimitry Andric       Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global);
80f785676fSDimitry Andric       ATS.emitPersonality(PerSym);
813b0f4066SDimitry Andric     }
823b0f4066SDimitry Andric 
83139f7f9bSDimitry Andric     // Emit .handlerdata directive.
84f785676fSDimitry Andric     ATS.emitHandlerData();
853b0f4066SDimitry Andric 
863b0f4066SDimitry Andric     // Emit actual exception table
8791bc56edSDimitry Andric     emitExceptionTable();
88dff0c46cSDimitry Andric   }
893b0f4066SDimitry Andric 
9091bc56edSDimitry Andric   if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
91f785676fSDimitry Andric     ATS.emitFnEnd();
923b0f4066SDimitry Andric }
93139f7f9bSDimitry Andric 
emitTypeInfos(unsigned TTypeEncoding,MCSymbol * TTBaseLabel)94*4ba319b5SDimitry Andric void ARMException::emitTypeInfos(unsigned TTypeEncoding,
95*4ba319b5SDimitry Andric                                  MCSymbol *TTBaseLabel) {
96d88c1a5aSDimitry Andric   const MachineFunction *MF = Asm->MF;
97d88c1a5aSDimitry Andric   const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
98d88c1a5aSDimitry Andric   const std::vector<unsigned> &FilterIds = MF->getFilterIds();
99139f7f9bSDimitry Andric 
100ff0cc061SDimitry Andric   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
101139f7f9bSDimitry Andric 
102139f7f9bSDimitry Andric   int Entry = 0;
103139f7f9bSDimitry Andric   // Emit the Catch TypeInfos.
104139f7f9bSDimitry Andric   if (VerboseAsm && !TypeInfos.empty()) {
105ff0cc061SDimitry Andric     Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
106ff0cc061SDimitry Andric     Asm->OutStreamer->AddBlankLine();
107139f7f9bSDimitry Andric     Entry = TypeInfos.size();
108139f7f9bSDimitry Andric   }
109139f7f9bSDimitry Andric 
1107d523365SDimitry Andric   for (const GlobalValue *GV : reverse(TypeInfos)) {
111139f7f9bSDimitry Andric     if (VerboseAsm)
112ff0cc061SDimitry Andric       Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
113139f7f9bSDimitry Andric     Asm->EmitTTypeReference(GV, TTypeEncoding);
114139f7f9bSDimitry Andric   }
115139f7f9bSDimitry Andric 
116*4ba319b5SDimitry Andric   Asm->OutStreamer->EmitLabel(TTBaseLabel);
117*4ba319b5SDimitry Andric 
118139f7f9bSDimitry Andric   // Emit the Exception Specifications.
119139f7f9bSDimitry Andric   if (VerboseAsm && !FilterIds.empty()) {
120ff0cc061SDimitry Andric     Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
121ff0cc061SDimitry Andric     Asm->OutStreamer->AddBlankLine();
122139f7f9bSDimitry Andric     Entry = 0;
123139f7f9bSDimitry Andric   }
124139f7f9bSDimitry Andric   for (std::vector<unsigned>::const_iterator
125139f7f9bSDimitry Andric          I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
126139f7f9bSDimitry Andric     unsigned TypeID = *I;
127139f7f9bSDimitry Andric     if (VerboseAsm) {
128139f7f9bSDimitry Andric       --Entry;
129139f7f9bSDimitry Andric       if (TypeID != 0)
130ff0cc061SDimitry Andric         Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
131139f7f9bSDimitry Andric     }
132139f7f9bSDimitry Andric 
13391bc56edSDimitry Andric     Asm->EmitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]),
134139f7f9bSDimitry Andric                             TTypeEncoding);
135139f7f9bSDimitry Andric   }
136139f7f9bSDimitry Andric }
137