1f22ef01cSRoman Divacky //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky 
10f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineModuleInfo.h"
11139f7f9bSDimitry Andric #include "llvm/ADT/PointerUnion.h"
127d523365SDimitry Andric #include "llvm/ADT/TinyPtrVector.h"
137d523365SDimitry Andric #include "llvm/Analysis/EHPersonalities.h"
14f22ef01cSRoman Divacky #include "llvm/Analysis/ValueTracking.h"
15f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineFunction.h"
16139f7f9bSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
17f22ef01cSRoman Divacky #include "llvm/CodeGen/Passes.h"
18139f7f9bSDimitry Andric #include "llvm/IR/Constants.h"
19139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h"
20139f7f9bSDimitry Andric #include "llvm/IR/GlobalVariable.h"
21139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
226122f3e6SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
23f22ef01cSRoman Divacky #include "llvm/MC/MCSymbol.h"
24f22ef01cSRoman Divacky #include "llvm/Support/Dwarf.h"
25f22ef01cSRoman Divacky #include "llvm/Support/ErrorHandling.h"
26f22ef01cSRoman Divacky using namespace llvm;
27f22ef01cSRoman Divacky using namespace llvm::dwarf;
28f22ef01cSRoman Divacky 
293861d79fSDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's.
30e580952dSDimitry Andric INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo",
312754fe60SDimitry Andric                 "Machine Module Information", false, false)
32f22ef01cSRoman Divacky char MachineModuleInfo::ID = 0;
33f22ef01cSRoman Divacky 
34f22ef01cSRoman Divacky // Out of line virtual method.
35f22ef01cSRoman Divacky MachineModuleInfoImpl::~MachineModuleInfoImpl() {}
36f22ef01cSRoman Divacky 
37f22ef01cSRoman Divacky namespace llvm {
387d523365SDimitry Andric class MMIAddrLabelMapCallbackPtr final : CallbackVH {
39f22ef01cSRoman Divacky   MMIAddrLabelMap *Map;
40f22ef01cSRoman Divacky public:
4191bc56edSDimitry Andric   MMIAddrLabelMapCallbackPtr() : Map(nullptr) {}
4291bc56edSDimitry Andric   MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V), Map(nullptr) {}
43f22ef01cSRoman Divacky 
44f22ef01cSRoman Divacky   void setPtr(BasicBlock *BB) {
45f22ef01cSRoman Divacky     ValueHandleBase::operator=(BB);
46f22ef01cSRoman Divacky   }
47f22ef01cSRoman Divacky 
48f22ef01cSRoman Divacky   void setMap(MMIAddrLabelMap *map) { Map = map; }
49f22ef01cSRoman Divacky 
5091bc56edSDimitry Andric   void deleted() override;
5191bc56edSDimitry Andric   void allUsesReplacedWith(Value *V2) override;
52f22ef01cSRoman Divacky };
53f22ef01cSRoman Divacky 
54f22ef01cSRoman Divacky class MMIAddrLabelMap {
55f22ef01cSRoman Divacky   MCContext &Context;
56f22ef01cSRoman Divacky   struct AddrLabelSymEntry {
573dac3a9bSDimitry Andric     /// Symbols - The symbols for the label.
583dac3a9bSDimitry Andric     TinyPtrVector<MCSymbol *> Symbols;
59f22ef01cSRoman Divacky 
60f22ef01cSRoman Divacky     Function *Fn;   // The containing function of the BasicBlock.
61f22ef01cSRoman Divacky     unsigned Index; // The index in BBCallbacks for the BasicBlock.
62f22ef01cSRoman Divacky   };
63f22ef01cSRoman Divacky 
64f22ef01cSRoman Divacky   DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry> AddrLabelSymbols;
65f22ef01cSRoman Divacky 
66f22ef01cSRoman Divacky   /// BBCallbacks - Callbacks for the BasicBlock's that we have entries for.  We
67f22ef01cSRoman Divacky   /// use this so we get notified if a block is deleted or RAUWd.
68f22ef01cSRoman Divacky   std::vector<MMIAddrLabelMapCallbackPtr> BBCallbacks;
69f22ef01cSRoman Divacky 
70f22ef01cSRoman Divacky   /// DeletedAddrLabelsNeedingEmission - This is a per-function list of symbols
71f22ef01cSRoman Divacky   /// whose corresponding BasicBlock got deleted.  These symbols need to be
72f22ef01cSRoman Divacky   /// emitted at some point in the file, so AsmPrinter emits them after the
73f22ef01cSRoman Divacky   /// function body.
74f22ef01cSRoman Divacky   DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >
75f22ef01cSRoman Divacky     DeletedAddrLabelsNeedingEmission;
76f22ef01cSRoman Divacky public:
77f22ef01cSRoman Divacky 
78f22ef01cSRoman Divacky   MMIAddrLabelMap(MCContext &context) : Context(context) {}
79f22ef01cSRoman Divacky   ~MMIAddrLabelMap() {
80f22ef01cSRoman Divacky     assert(DeletedAddrLabelsNeedingEmission.empty() &&
81f22ef01cSRoman Divacky            "Some labels for deleted blocks never got emitted");
82f22ef01cSRoman Divacky   }
83f22ef01cSRoman Divacky 
843dac3a9bSDimitry Andric   ArrayRef<MCSymbol *> getAddrLabelSymbolToEmit(BasicBlock *BB);
85f22ef01cSRoman Divacky 
86f22ef01cSRoman Divacky   void takeDeletedSymbolsForFunction(Function *F,
87f22ef01cSRoman Divacky                                      std::vector<MCSymbol*> &Result);
88f22ef01cSRoman Divacky 
89f22ef01cSRoman Divacky   void UpdateForDeletedBlock(BasicBlock *BB);
90f22ef01cSRoman Divacky   void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New);
91f22ef01cSRoman Divacky };
923dac3a9bSDimitry Andric }
93f22ef01cSRoman Divacky 
943dac3a9bSDimitry Andric ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
95f22ef01cSRoman Divacky   assert(BB->hasAddressTaken() &&
96f22ef01cSRoman Divacky          "Shouldn't get label for block without address taken");
97f22ef01cSRoman Divacky   AddrLabelSymEntry &Entry = AddrLabelSymbols[BB];
98f22ef01cSRoman Divacky 
99f22ef01cSRoman Divacky   // If we already had an entry for this block, just return it.
1003dac3a9bSDimitry Andric   if (!Entry.Symbols.empty()) {
101f22ef01cSRoman Divacky     assert(BB->getParent() == Entry.Fn && "Parent changed");
1023dac3a9bSDimitry Andric     return Entry.Symbols;
103f22ef01cSRoman Divacky   }
104f22ef01cSRoman Divacky 
105f22ef01cSRoman Divacky   // Otherwise, this is a new entry, create a new symbol for it and add an
106f22ef01cSRoman Divacky   // entry to BBCallbacks so we can be notified if the BB is deleted or RAUWd.
10797bc6c73SDimitry Andric   BBCallbacks.emplace_back(BB);
108f22ef01cSRoman Divacky   BBCallbacks.back().setMap(this);
109f22ef01cSRoman Divacky   Entry.Index = BBCallbacks.size() - 1;
110f22ef01cSRoman Divacky   Entry.Fn = BB->getParent();
1113dac3a9bSDimitry Andric   Entry.Symbols.push_back(Context.createTempSymbol());
1123dac3a9bSDimitry Andric   return Entry.Symbols;
113f22ef01cSRoman Divacky }
114f22ef01cSRoman Divacky 
115f22ef01cSRoman Divacky /// takeDeletedSymbolsForFunction - If we have any deleted symbols for F, return
116f22ef01cSRoman Divacky /// them.
117f22ef01cSRoman Divacky void MMIAddrLabelMap::
118f22ef01cSRoman Divacky takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) {
119f22ef01cSRoman Divacky   DenseMap<AssertingVH<Function>, std::vector<MCSymbol*> >::iterator I =
120f22ef01cSRoman Divacky     DeletedAddrLabelsNeedingEmission.find(F);
121f22ef01cSRoman Divacky 
122f22ef01cSRoman Divacky   // If there are no entries for the function, just return.
123f22ef01cSRoman Divacky   if (I == DeletedAddrLabelsNeedingEmission.end()) return;
124f22ef01cSRoman Divacky 
125f22ef01cSRoman Divacky   // Otherwise, take the list.
126f22ef01cSRoman Divacky   std::swap(Result, I->second);
127f22ef01cSRoman Divacky   DeletedAddrLabelsNeedingEmission.erase(I);
128f22ef01cSRoman Divacky }
129f22ef01cSRoman Divacky 
130f22ef01cSRoman Divacky 
131f22ef01cSRoman Divacky void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
132f22ef01cSRoman Divacky   // If the block got deleted, there is no need for the symbol.  If the symbol
133f22ef01cSRoman Divacky   // was already emitted, we can just forget about it, otherwise we need to
134f22ef01cSRoman Divacky   // queue it up for later emission when the function is output.
1353dac3a9bSDimitry Andric   AddrLabelSymEntry Entry = std::move(AddrLabelSymbols[BB]);
136f22ef01cSRoman Divacky   AddrLabelSymbols.erase(BB);
1373dac3a9bSDimitry Andric   assert(!Entry.Symbols.empty() && "Didn't have a symbol, why a callback?");
13891bc56edSDimitry Andric   BBCallbacks[Entry.Index] = nullptr;  // Clear the callback.
139f22ef01cSRoman Divacky 
14091bc56edSDimitry Andric   assert((BB->getParent() == nullptr || BB->getParent() == Entry.Fn) &&
141f22ef01cSRoman Divacky          "Block/parent mismatch");
142f22ef01cSRoman Divacky 
1433dac3a9bSDimitry Andric   for (MCSymbol *Sym : Entry.Symbols) {
144f22ef01cSRoman Divacky     if (Sym->isDefined())
145f22ef01cSRoman Divacky       return;
146f22ef01cSRoman Divacky 
147f22ef01cSRoman Divacky     // If the block is not yet defined, we need to emit it at the end of the
148f22ef01cSRoman Divacky     // function.  Add the symbol to the DeletedAddrLabelsNeedingEmission list
149f22ef01cSRoman Divacky     // for the containing Function.  Since the block is being deleted, its
150f22ef01cSRoman Divacky     // parent may already be removed, we have to get the function from 'Entry'.
151f22ef01cSRoman Divacky     DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym);
152f22ef01cSRoman Divacky   }
153f22ef01cSRoman Divacky }
154f22ef01cSRoman Divacky 
155f22ef01cSRoman Divacky void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
156f22ef01cSRoman Divacky   // Get the entry for the RAUW'd block and remove it from our map.
1573dac3a9bSDimitry Andric   AddrLabelSymEntry OldEntry = std::move(AddrLabelSymbols[Old]);
158f22ef01cSRoman Divacky   AddrLabelSymbols.erase(Old);
1593dac3a9bSDimitry Andric   assert(!OldEntry.Symbols.empty() && "Didn't have a symbol, why a callback?");
160f22ef01cSRoman Divacky 
161f22ef01cSRoman Divacky   AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New];
162f22ef01cSRoman Divacky 
163f22ef01cSRoman Divacky   // If New is not address taken, just move our symbol over to it.
1643dac3a9bSDimitry Andric   if (NewEntry.Symbols.empty()) {
165f22ef01cSRoman Divacky     BBCallbacks[OldEntry.Index].setPtr(New);    // Update the callback.
1663dac3a9bSDimitry Andric     NewEntry = std::move(OldEntry);             // Set New's entry.
167f22ef01cSRoman Divacky     return;
168f22ef01cSRoman Divacky   }
169f22ef01cSRoman Divacky 
17091bc56edSDimitry Andric   BBCallbacks[OldEntry.Index] = nullptr;    // Update the callback.
171f22ef01cSRoman Divacky 
1723dac3a9bSDimitry Andric   // Otherwise, we need to add the old symbols to the new block's set.
1733dac3a9bSDimitry Andric   NewEntry.Symbols.insert(NewEntry.Symbols.end(), OldEntry.Symbols.begin(),
1743dac3a9bSDimitry Andric                           OldEntry.Symbols.end());
175f22ef01cSRoman Divacky }
176f22ef01cSRoman Divacky 
177f22ef01cSRoman Divacky 
178f22ef01cSRoman Divacky void MMIAddrLabelMapCallbackPtr::deleted() {
179f22ef01cSRoman Divacky   Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr()));
180f22ef01cSRoman Divacky }
181f22ef01cSRoman Divacky 
182f22ef01cSRoman Divacky void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) {
183f22ef01cSRoman Divacky   Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2));
184f22ef01cSRoman Divacky }
185f22ef01cSRoman Divacky 
186f22ef01cSRoman Divacky 
187f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
188f22ef01cSRoman Divacky 
1892754fe60SDimitry Andric MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI,
1906122f3e6SDimitry Andric                                      const MCRegisterInfo &MRI,
1916122f3e6SDimitry Andric                                      const MCObjectFileInfo *MOFI)
19291bc56edSDimitry Andric   : ImmutablePass(ID), Context(&MAI, &MRI, MOFI, nullptr, false) {
1932754fe60SDimitry Andric   initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry());
194f22ef01cSRoman Divacky }
195f22ef01cSRoman Divacky 
196f22ef01cSRoman Divacky MachineModuleInfo::MachineModuleInfo()
19791bc56edSDimitry Andric   : ImmutablePass(ID), Context(nullptr, nullptr, nullptr) {
198dff0c46cSDimitry Andric   llvm_unreachable("This MachineModuleInfo constructor should never be called, "
199dff0c46cSDimitry Andric                    "MMI should always be explicitly constructed by "
200dff0c46cSDimitry Andric                    "LLVMTargetMachine");
201f22ef01cSRoman Divacky }
202f22ef01cSRoman Divacky 
203f22ef01cSRoman Divacky MachineModuleInfo::~MachineModuleInfo() {
204f22ef01cSRoman Divacky }
205f22ef01cSRoman Divacky 
206139f7f9bSDimitry Andric bool MachineModuleInfo::doInitialization(Module &M) {
207139f7f9bSDimitry Andric 
20891bc56edSDimitry Andric   ObjFileMMI = nullptr;
209139f7f9bSDimitry Andric   CurCallSite = 0;
2103dac3a9bSDimitry Andric   CallsEHReturn = false;
2113dac3a9bSDimitry Andric   CallsUnwindInit = false;
2127d523365SDimitry Andric   HasEHFunclets = false;
21339d628a0SDimitry Andric   DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
214ff0cc061SDimitry Andric   PersonalityTypeCache = EHPersonality::Unknown;
21591bc56edSDimitry Andric   AddrLabelSymbols = nullptr;
21691bc56edSDimitry Andric   TheModule = nullptr;
217139f7f9bSDimitry Andric 
218f22ef01cSRoman Divacky   return false;
219f22ef01cSRoman Divacky }
220f22ef01cSRoman Divacky 
221139f7f9bSDimitry Andric bool MachineModuleInfo::doFinalization(Module &M) {
222139f7f9bSDimitry Andric 
223139f7f9bSDimitry Andric   Personalities.clear();
224139f7f9bSDimitry Andric 
225f22ef01cSRoman Divacky   delete AddrLabelSymbols;
22691bc56edSDimitry Andric   AddrLabelSymbols = nullptr;
227139f7f9bSDimitry Andric 
228139f7f9bSDimitry Andric   Context.reset();
229139f7f9bSDimitry Andric 
230139f7f9bSDimitry Andric   delete ObjFileMMI;
23191bc56edSDimitry Andric   ObjFileMMI = nullptr;
232139f7f9bSDimitry Andric 
233f22ef01cSRoman Divacky   return false;
234f22ef01cSRoman Divacky }
235f22ef01cSRoman Divacky 
236f22ef01cSRoman Divacky /// EndFunction - Discard function meta information.
237f22ef01cSRoman Divacky ///
238f22ef01cSRoman Divacky void MachineModuleInfo::EndFunction() {
239f22ef01cSRoman Divacky   // Clean up frame info.
240f785676fSDimitry Andric   FrameInstructions.clear();
241f22ef01cSRoman Divacky 
242f22ef01cSRoman Divacky   // Clean up exception info.
243f22ef01cSRoman Divacky   LandingPads.clear();
24497bc6c73SDimitry Andric   PersonalityTypeCache = EHPersonality::Unknown;
245f22ef01cSRoman Divacky   CallSiteMap.clear();
246f22ef01cSRoman Divacky   TypeInfos.clear();
247f22ef01cSRoman Divacky   FilterIds.clear();
248f22ef01cSRoman Divacky   FilterEnds.clear();
2493dac3a9bSDimitry Andric   CallsEHReturn = false;
2503dac3a9bSDimitry Andric   CallsUnwindInit = false;
2517d523365SDimitry Andric   HasEHFunclets = false;
25291bc56edSDimitry Andric   VariableDbgInfos.clear();
253f22ef01cSRoman Divacky }
254f22ef01cSRoman Divacky 
255f22ef01cSRoman Divacky //===- Address of Block Management ----------------------------------------===//
256f22ef01cSRoman Divacky 
257f22ef01cSRoman Divacky /// getAddrLabelSymbolToEmit - Return the symbol to be used for the specified
258f22ef01cSRoman Divacky /// basic block when its address is taken.  If other blocks were RAUW'd to
259f22ef01cSRoman Divacky /// this one, we may have to emit them as well, return the whole set.
2603dac3a9bSDimitry Andric ArrayRef<MCSymbol *>
2613dac3a9bSDimitry Andric MachineModuleInfo::getAddrLabelSymbolToEmit(const BasicBlock *BB) {
262f22ef01cSRoman Divacky   // Lazily create AddrLabelSymbols.
26391bc56edSDimitry Andric   if (!AddrLabelSymbols)
264f22ef01cSRoman Divacky     AddrLabelSymbols = new MMIAddrLabelMap(Context);
265f22ef01cSRoman Divacky  return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast<BasicBlock*>(BB));
266f22ef01cSRoman Divacky }
267f22ef01cSRoman Divacky 
268f22ef01cSRoman Divacky 
269f22ef01cSRoman Divacky /// takeDeletedSymbolsForFunction - If the specified function has had any
270f22ef01cSRoman Divacky /// references to address-taken blocks generated, but the block got deleted,
271f22ef01cSRoman Divacky /// return the symbol now so we can emit it.  This prevents emitting a
272f22ef01cSRoman Divacky /// reference to a symbol that has no definition.
273f22ef01cSRoman Divacky void MachineModuleInfo::
274f22ef01cSRoman Divacky takeDeletedSymbolsForFunction(const Function *F,
275f22ef01cSRoman Divacky                               std::vector<MCSymbol*> &Result) {
276f22ef01cSRoman Divacky   // If no blocks have had their addresses taken, we're done.
27791bc56edSDimitry Andric   if (!AddrLabelSymbols) return;
278f22ef01cSRoman Divacky   return AddrLabelSymbols->
279f22ef01cSRoman Divacky      takeDeletedSymbolsForFunction(const_cast<Function*>(F), Result);
280f22ef01cSRoman Divacky }
281f22ef01cSRoman Divacky 
282f22ef01cSRoman Divacky //===- EH -----------------------------------------------------------------===//
283f22ef01cSRoman Divacky 
284f22ef01cSRoman Divacky /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the
285f22ef01cSRoman Divacky /// specified MachineBasicBlock.
286f22ef01cSRoman Divacky LandingPadInfo &MachineModuleInfo::getOrCreateLandingPadInfo
287f22ef01cSRoman Divacky     (MachineBasicBlock *LandingPad) {
288f22ef01cSRoman Divacky   unsigned N = LandingPads.size();
289f22ef01cSRoman Divacky   for (unsigned i = 0; i < N; ++i) {
290f22ef01cSRoman Divacky     LandingPadInfo &LP = LandingPads[i];
291f22ef01cSRoman Divacky     if (LP.LandingPadBlock == LandingPad)
292f22ef01cSRoman Divacky       return LP;
293f22ef01cSRoman Divacky   }
294f22ef01cSRoman Divacky 
295f22ef01cSRoman Divacky   LandingPads.push_back(LandingPadInfo(LandingPad));
296f22ef01cSRoman Divacky   return LandingPads[N];
297f22ef01cSRoman Divacky }
298f22ef01cSRoman Divacky 
299f22ef01cSRoman Divacky /// addInvoke - Provide the begin and end labels of an invoke style call and
300f22ef01cSRoman Divacky /// associate it with a try landing pad block.
301f22ef01cSRoman Divacky void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad,
302f22ef01cSRoman Divacky                                   MCSymbol *BeginLabel, MCSymbol *EndLabel) {
303f22ef01cSRoman Divacky   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
304f22ef01cSRoman Divacky   LP.BeginLabels.push_back(BeginLabel);
305f22ef01cSRoman Divacky   LP.EndLabels.push_back(EndLabel);
306f22ef01cSRoman Divacky }
307f22ef01cSRoman Divacky 
308f22ef01cSRoman Divacky /// addLandingPad - Provide the label of a try LandingPad block.
309f22ef01cSRoman Divacky ///
310f22ef01cSRoman Divacky MCSymbol *MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) {
311ff0cc061SDimitry Andric   MCSymbol *LandingPadLabel = Context.createTempSymbol();
312f22ef01cSRoman Divacky   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
313f22ef01cSRoman Divacky   LP.LandingPadLabel = LandingPadLabel;
314f22ef01cSRoman Divacky   return LandingPadLabel;
315f22ef01cSRoman Divacky }
316f22ef01cSRoman Divacky 
317875ed548SDimitry Andric void MachineModuleInfo::addPersonality(const Function *Personality) {
318f22ef01cSRoman Divacky   for (unsigned i = 0; i < Personalities.size(); ++i)
319f22ef01cSRoman Divacky     if (Personalities[i] == Personality)
320f22ef01cSRoman Divacky       return;
321f22ef01cSRoman Divacky   Personalities.push_back(Personality);
322f22ef01cSRoman Divacky }
323f22ef01cSRoman Divacky 
324f22ef01cSRoman Divacky /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
325f22ef01cSRoman Divacky ///
3266122f3e6SDimitry Andric void MachineModuleInfo::
3276122f3e6SDimitry Andric addCatchTypeInfo(MachineBasicBlock *LandingPad,
32839d628a0SDimitry Andric                  ArrayRef<const GlobalValue *> TyInfo) {
329f22ef01cSRoman Divacky   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
330f22ef01cSRoman Divacky   for (unsigned N = TyInfo.size(); N; --N)
331f22ef01cSRoman Divacky     LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1]));
332f22ef01cSRoman Divacky }
333f22ef01cSRoman Divacky 
334f22ef01cSRoman Divacky /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
335f22ef01cSRoman Divacky ///
3366122f3e6SDimitry Andric void MachineModuleInfo::
3376122f3e6SDimitry Andric addFilterTypeInfo(MachineBasicBlock *LandingPad,
33839d628a0SDimitry Andric                   ArrayRef<const GlobalValue *> TyInfo) {
339f22ef01cSRoman Divacky   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
340f22ef01cSRoman Divacky   std::vector<unsigned> IdsInFilter(TyInfo.size());
341f22ef01cSRoman Divacky   for (unsigned I = 0, E = TyInfo.size(); I != E; ++I)
342f22ef01cSRoman Divacky     IdsInFilter[I] = getTypeIDFor(TyInfo[I]);
343f22ef01cSRoman Divacky   LP.TypeIds.push_back(getFilterIDFor(IdsInFilter));
344f22ef01cSRoman Divacky }
345f22ef01cSRoman Divacky 
346f22ef01cSRoman Divacky /// addCleanup - Add a cleanup action for a landing pad.
347f22ef01cSRoman Divacky ///
348f22ef01cSRoman Divacky void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) {
349f22ef01cSRoman Divacky   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
350f22ef01cSRoman Divacky   LP.TypeIds.push_back(0);
351f22ef01cSRoman Divacky }
352f22ef01cSRoman Divacky 
353ff0cc061SDimitry Andric void MachineModuleInfo::addSEHCatchHandler(MachineBasicBlock *LandingPad,
354ff0cc061SDimitry Andric                                            const Function *Filter,
355ff0cc061SDimitry Andric                                            const BlockAddress *RecoverBA) {
356ff0cc061SDimitry Andric   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
357ff0cc061SDimitry Andric   SEHHandler Handler;
358ff0cc061SDimitry Andric   Handler.FilterOrFinally = Filter;
359ff0cc061SDimitry Andric   Handler.RecoverBA = RecoverBA;
360ff0cc061SDimitry Andric   LP.SEHHandlers.push_back(Handler);
361ff0cc061SDimitry Andric }
362ff0cc061SDimitry Andric 
363ff0cc061SDimitry Andric void MachineModuleInfo::addSEHCleanupHandler(MachineBasicBlock *LandingPad,
364ff0cc061SDimitry Andric                                              const Function *Cleanup) {
365ff0cc061SDimitry Andric   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
366ff0cc061SDimitry Andric   SEHHandler Handler;
367ff0cc061SDimitry Andric   Handler.FilterOrFinally = Cleanup;
368ff0cc061SDimitry Andric   Handler.RecoverBA = nullptr;
369ff0cc061SDimitry Andric   LP.SEHHandlers.push_back(Handler);
370ff0cc061SDimitry Andric }
371ff0cc061SDimitry Andric 
372f22ef01cSRoman Divacky /// TidyLandingPads - Remap landing pad labels and remove any deleted landing
373f22ef01cSRoman Divacky /// pads.
374f22ef01cSRoman Divacky void MachineModuleInfo::TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap) {
375f22ef01cSRoman Divacky   for (unsigned i = 0; i != LandingPads.size(); ) {
376f22ef01cSRoman Divacky     LandingPadInfo &LandingPad = LandingPads[i];
377f22ef01cSRoman Divacky     if (LandingPad.LandingPadLabel &&
378f22ef01cSRoman Divacky         !LandingPad.LandingPadLabel->isDefined() &&
379f22ef01cSRoman Divacky         (!LPMap || (*LPMap)[LandingPad.LandingPadLabel] == 0))
38091bc56edSDimitry Andric       LandingPad.LandingPadLabel = nullptr;
381f22ef01cSRoman Divacky 
382f22ef01cSRoman Divacky     // Special case: we *should* emit LPs with null LP MBB. This indicates
383f22ef01cSRoman Divacky     // "nounwind" case.
384f22ef01cSRoman Divacky     if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) {
385f22ef01cSRoman Divacky       LandingPads.erase(LandingPads.begin() + i);
386f22ef01cSRoman Divacky       continue;
387f22ef01cSRoman Divacky     }
388f22ef01cSRoman Divacky 
389f22ef01cSRoman Divacky     for (unsigned j = 0, e = LandingPads[i].BeginLabels.size(); j != e; ++j) {
390f22ef01cSRoman Divacky       MCSymbol *BeginLabel = LandingPad.BeginLabels[j];
391f22ef01cSRoman Divacky       MCSymbol *EndLabel = LandingPad.EndLabels[j];
392f22ef01cSRoman Divacky       if ((BeginLabel->isDefined() ||
393f22ef01cSRoman Divacky            (LPMap && (*LPMap)[BeginLabel] != 0)) &&
394f22ef01cSRoman Divacky           (EndLabel->isDefined() ||
395f22ef01cSRoman Divacky            (LPMap && (*LPMap)[EndLabel] != 0))) continue;
396f22ef01cSRoman Divacky 
397f22ef01cSRoman Divacky       LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j);
398f22ef01cSRoman Divacky       LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j);
399f22ef01cSRoman Divacky       --j, --e;
400f22ef01cSRoman Divacky     }
401f22ef01cSRoman Divacky 
402f22ef01cSRoman Divacky     // Remove landing pads with no try-ranges.
403f22ef01cSRoman Divacky     if (LandingPads[i].BeginLabels.empty()) {
404f22ef01cSRoman Divacky       LandingPads.erase(LandingPads.begin() + i);
405f22ef01cSRoman Divacky       continue;
406f22ef01cSRoman Divacky     }
407f22ef01cSRoman Divacky 
408f22ef01cSRoman Divacky     // If there is no landing pad, ensure that the list of typeids is empty.
409f22ef01cSRoman Divacky     // If the only typeid is a cleanup, this is the same as having no typeids.
410f22ef01cSRoman Divacky     if (!LandingPad.LandingPadBlock ||
411f22ef01cSRoman Divacky         (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0]))
412f22ef01cSRoman Divacky       LandingPad.TypeIds.clear();
413f22ef01cSRoman Divacky     ++i;
414f22ef01cSRoman Divacky   }
415f22ef01cSRoman Divacky }
416f22ef01cSRoman Divacky 
4176122f3e6SDimitry Andric /// setCallSiteLandingPad - Map the landing pad's EH symbol to the call site
4186122f3e6SDimitry Andric /// indexes.
4196122f3e6SDimitry Andric void MachineModuleInfo::setCallSiteLandingPad(MCSymbol *Sym,
4206122f3e6SDimitry Andric                                               ArrayRef<unsigned> Sites) {
421dff0c46cSDimitry Andric   LPadToCallSiteMap[Sym].append(Sites.begin(), Sites.end());
4226122f3e6SDimitry Andric }
4236122f3e6SDimitry Andric 
424f22ef01cSRoman Divacky /// getTypeIDFor - Return the type id for the specified typeinfo.  This is
425f22ef01cSRoman Divacky /// function wide.
42639d628a0SDimitry Andric unsigned MachineModuleInfo::getTypeIDFor(const GlobalValue *TI) {
427f22ef01cSRoman Divacky   for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i)
428f22ef01cSRoman Divacky     if (TypeInfos[i] == TI) return i + 1;
429f22ef01cSRoman Divacky 
430f22ef01cSRoman Divacky   TypeInfos.push_back(TI);
431f22ef01cSRoman Divacky   return TypeInfos.size();
432f22ef01cSRoman Divacky }
433f22ef01cSRoman Divacky 
434f22ef01cSRoman Divacky /// getFilterIDFor - Return the filter id for the specified typeinfos.  This is
435f22ef01cSRoman Divacky /// function wide.
436f22ef01cSRoman Divacky int MachineModuleInfo::getFilterIDFor(std::vector<unsigned> &TyIds) {
437f22ef01cSRoman Divacky   // If the new filter coincides with the tail of an existing filter, then
438f22ef01cSRoman Divacky   // re-use the existing filter.  Folding filters more than this requires
439f22ef01cSRoman Divacky   // re-ordering filters and/or their elements - probably not worth it.
440f22ef01cSRoman Divacky   for (std::vector<unsigned>::iterator I = FilterEnds.begin(),
441f22ef01cSRoman Divacky        E = FilterEnds.end(); I != E; ++I) {
442f22ef01cSRoman Divacky     unsigned i = *I, j = TyIds.size();
443f22ef01cSRoman Divacky 
444f22ef01cSRoman Divacky     while (i && j)
445f22ef01cSRoman Divacky       if (FilterIds[--i] != TyIds[--j])
446f22ef01cSRoman Divacky         goto try_next;
447f22ef01cSRoman Divacky 
448f22ef01cSRoman Divacky     if (!j)
449f22ef01cSRoman Divacky       // The new filter coincides with range [i, end) of the existing filter.
450f22ef01cSRoman Divacky       return -(1 + i);
451f22ef01cSRoman Divacky 
452f22ef01cSRoman Divacky try_next:;
453f22ef01cSRoman Divacky   }
454f22ef01cSRoman Divacky 
455f22ef01cSRoman Divacky   // Add the new filter.
456f22ef01cSRoman Divacky   int FilterID = -(1 + FilterIds.size());
457f22ef01cSRoman Divacky   FilterIds.reserve(FilterIds.size() + TyIds.size() + 1);
458dff0c46cSDimitry Andric   FilterIds.insert(FilterIds.end(), TyIds.begin(), TyIds.end());
459f22ef01cSRoman Divacky   FilterEnds.push_back(FilterIds.size());
460f22ef01cSRoman Divacky   FilterIds.push_back(0); // terminator
461f22ef01cSRoman Divacky   return FilterID;
462f22ef01cSRoman Divacky }
463