1*9880d681SAndroid Build Coastguard Worker //===-- EHStreamer.h - Exception Handling Directive Streamer ---*- C++ -*--===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker // 10*9880d681SAndroid Build Coastguard Worker // This file contains support for writing exception info into assembly files. 11*9880d681SAndroid Build Coastguard Worker // 12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 13*9880d681SAndroid Build Coastguard Worker 14*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H 15*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H 16*9880d681SAndroid Build Coastguard Worker 17*9880d681SAndroid Build Coastguard Worker #include "AsmPrinterHandler.h" 18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h" 19*9880d681SAndroid Build Coastguard Worker 20*9880d681SAndroid Build Coastguard Worker namespace llvm { 21*9880d681SAndroid Build Coastguard Worker struct LandingPadInfo; 22*9880d681SAndroid Build Coastguard Worker class MachineModuleInfo; 23*9880d681SAndroid Build Coastguard Worker class MachineInstr; 24*9880d681SAndroid Build Coastguard Worker class MachineFunction; 25*9880d681SAndroid Build Coastguard Worker class MCSymbol; 26*9880d681SAndroid Build Coastguard Worker class MCSymbolRefExpr; 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker template <typename T> 29*9880d681SAndroid Build Coastguard Worker class SmallVectorImpl; 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Worker /// Emits exception handling directives. 32*9880d681SAndroid Build Coastguard Worker class LLVM_LIBRARY_VISIBILITY EHStreamer : public AsmPrinterHandler { 33*9880d681SAndroid Build Coastguard Worker protected: 34*9880d681SAndroid Build Coastguard Worker /// Target of directive emission. 35*9880d681SAndroid Build Coastguard Worker AsmPrinter *Asm; 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Worker /// Collected machine module information. 38*9880d681SAndroid Build Coastguard Worker MachineModuleInfo *MMI; 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Worker /// How many leading type ids two landing pads have in common. 41*9880d681SAndroid Build Coastguard Worker static unsigned sharedTypeIDs(const LandingPadInfo *L, 42*9880d681SAndroid Build Coastguard Worker const LandingPadInfo *R); 43*9880d681SAndroid Build Coastguard Worker 44*9880d681SAndroid Build Coastguard Worker /// Structure holding a try-range and the associated landing pad. 45*9880d681SAndroid Build Coastguard Worker struct PadRange { 46*9880d681SAndroid Build Coastguard Worker // The index of the landing pad. 47*9880d681SAndroid Build Coastguard Worker unsigned PadIndex; 48*9880d681SAndroid Build Coastguard Worker // The index of the begin and end labels in the landing pad's label lists. 49*9880d681SAndroid Build Coastguard Worker unsigned RangeIndex; 50*9880d681SAndroid Build Coastguard Worker }; 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Worker typedef DenseMap<MCSymbol *, PadRange> RangeMapType; 53*9880d681SAndroid Build Coastguard Worker 54*9880d681SAndroid Build Coastguard Worker /// Structure describing an entry in the actions table. 55*9880d681SAndroid Build Coastguard Worker struct ActionEntry { 56*9880d681SAndroid Build Coastguard Worker int ValueForTypeID; // The value to write - may not be equal to the type id. 57*9880d681SAndroid Build Coastguard Worker int NextAction; 58*9880d681SAndroid Build Coastguard Worker unsigned Previous; 59*9880d681SAndroid Build Coastguard Worker }; 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard Worker /// Structure describing an entry in the call-site table. 62*9880d681SAndroid Build Coastguard Worker struct CallSiteEntry { 63*9880d681SAndroid Build Coastguard Worker // The 'try-range' is BeginLabel .. EndLabel. 64*9880d681SAndroid Build Coastguard Worker MCSymbol *BeginLabel; // Null indicates the start of the function. 65*9880d681SAndroid Build Coastguard Worker MCSymbol *EndLabel; // Null indicates the end of the function. 66*9880d681SAndroid Build Coastguard Worker 67*9880d681SAndroid Build Coastguard Worker // LPad contains the landing pad start labels. 68*9880d681SAndroid Build Coastguard Worker const LandingPadInfo *LPad; // Null indicates that there is no landing pad. 69*9880d681SAndroid Build Coastguard Worker unsigned Action; 70*9880d681SAndroid Build Coastguard Worker }; 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Worker /// Compute the actions table and gather the first action index for each 73*9880d681SAndroid Build Coastguard Worker /// landing pad site. 74*9880d681SAndroid Build Coastguard Worker unsigned computeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs, 75*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<ActionEntry> &Actions, 76*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<unsigned> &FirstActions); 77*9880d681SAndroid Build Coastguard Worker 78*9880d681SAndroid Build Coastguard Worker void computePadMap(const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 79*9880d681SAndroid Build Coastguard Worker RangeMapType &PadMap); 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Worker /// Compute the call-site table. The entry for an invoke has a try-range 82*9880d681SAndroid Build Coastguard Worker /// containing the call, a non-zero landing pad and an appropriate action. 83*9880d681SAndroid Build Coastguard Worker /// The entry for an ordinary call has a try-range containing the call and 84*9880d681SAndroid Build Coastguard Worker /// zero for the landing pad and the action. Calls marked 'nounwind' have 85*9880d681SAndroid Build Coastguard Worker /// no entry and must not be contained in the try-range of any entry - they 86*9880d681SAndroid Build Coastguard Worker /// form gaps in the table. Entries must be ordered by try-range address. 87*9880d681SAndroid Build Coastguard Worker void computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, 88*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<const LandingPadInfo *> &LPs, 89*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<unsigned> &FirstActions); 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker /// Emit landing pads and actions. 92*9880d681SAndroid Build Coastguard Worker /// 93*9880d681SAndroid Build Coastguard Worker /// The general organization of the table is complex, but the basic concepts 94*9880d681SAndroid Build Coastguard Worker /// are easy. First there is a header which describes the location and 95*9880d681SAndroid Build Coastguard Worker /// organization of the three components that follow. 96*9880d681SAndroid Build Coastguard Worker /// 1. The landing pad site information describes the range of code covered 97*9880d681SAndroid Build Coastguard Worker /// by the try. In our case it's an accumulation of the ranges covered 98*9880d681SAndroid Build Coastguard Worker /// by the invokes in the try. There is also a reference to the landing 99*9880d681SAndroid Build Coastguard Worker /// pad that handles the exception once processed. Finally an index into 100*9880d681SAndroid Build Coastguard Worker /// the actions table. 101*9880d681SAndroid Build Coastguard Worker /// 2. The action table, in our case, is composed of pairs of type ids 102*9880d681SAndroid Build Coastguard Worker /// and next action offset. Starting with the action index from the 103*9880d681SAndroid Build Coastguard Worker /// landing pad site, each type Id is checked for a match to the current 104*9880d681SAndroid Build Coastguard Worker /// exception. If it matches then the exception and type id are passed 105*9880d681SAndroid Build Coastguard Worker /// on to the landing pad. Otherwise the next action is looked up. This 106*9880d681SAndroid Build Coastguard Worker /// chain is terminated with a next action of zero. If no type id is 107*9880d681SAndroid Build Coastguard Worker /// found the frame is unwound and handling continues. 108*9880d681SAndroid Build Coastguard Worker /// 3. Type id table contains references to all the C++ typeinfo for all 109*9880d681SAndroid Build Coastguard Worker /// catches in the function. This tables is reversed indexed base 1. 110*9880d681SAndroid Build Coastguard Worker void emitExceptionTable(); 111*9880d681SAndroid Build Coastguard Worker 112*9880d681SAndroid Build Coastguard Worker virtual void emitTypeInfos(unsigned TTypeEncoding); 113*9880d681SAndroid Build Coastguard Worker 114*9880d681SAndroid Build Coastguard Worker // Helpers for for identifying what kind of clause an EH typeid or selector 115*9880d681SAndroid Build Coastguard Worker // corresponds to. Negative selectors are for filter clauses, the zero 116*9880d681SAndroid Build Coastguard Worker // selector is for cleanups, and positive selectors are for catch clauses. isFilterEHSelector(int Selector)117*9880d681SAndroid Build Coastguard Worker static bool isFilterEHSelector(int Selector) { return Selector < 0; } isCleanupEHSelector(int Selector)118*9880d681SAndroid Build Coastguard Worker static bool isCleanupEHSelector(int Selector) { return Selector == 0; } isCatchEHSelector(int Selector)119*9880d681SAndroid Build Coastguard Worker static bool isCatchEHSelector(int Selector) { return Selector > 0; } 120*9880d681SAndroid Build Coastguard Worker 121*9880d681SAndroid Build Coastguard Worker public: 122*9880d681SAndroid Build Coastguard Worker EHStreamer(AsmPrinter *A); 123*9880d681SAndroid Build Coastguard Worker ~EHStreamer() override; 124*9880d681SAndroid Build Coastguard Worker 125*9880d681SAndroid Build Coastguard Worker // Unused. setSymbolSize(const MCSymbol * Sym,uint64_t Size)126*9880d681SAndroid Build Coastguard Worker void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} beginInstruction(const MachineInstr * MI)127*9880d681SAndroid Build Coastguard Worker void beginInstruction(const MachineInstr *MI) override {} endInstruction()128*9880d681SAndroid Build Coastguard Worker void endInstruction() override {} 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard Worker /// Return `true' if this is a call to a function marked `nounwind'. Return 131*9880d681SAndroid Build Coastguard Worker /// `false' otherwise. 132*9880d681SAndroid Build Coastguard Worker static bool callToNoUnwindFunction(const MachineInstr *MI); 133*9880d681SAndroid Build Coastguard Worker }; 134*9880d681SAndroid Build Coastguard Worker } 135*9880d681SAndroid Build Coastguard Worker 136*9880d681SAndroid Build Coastguard Worker #endif 137*9880d681SAndroid Build Coastguard Worker 138