| //===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/CodeGen/MachineModuleInfo.h" | 
 |  | 
 | #include "llvm/Constants.h" | 
 | #include "llvm/Analysis/ValueTracking.h" | 
 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
 | #include "llvm/CodeGen/MachineFunction.h" | 
 | #include "llvm/CodeGen/Passes.h" | 
 | #include "llvm/Target/TargetInstrInfo.h" | 
 | #include "llvm/Target/TargetMachine.h" | 
 | #include "llvm/Target/TargetOptions.h" | 
 | #include "llvm/DerivedTypes.h" | 
 | #include "llvm/GlobalVariable.h" | 
 | #include "llvm/Intrinsics.h" | 
 | #include "llvm/Instructions.h" | 
 | #include "llvm/Module.h" | 
 | #include "llvm/Support/Dwarf.h" | 
 | #include "llvm/Support/Streams.h" | 
 | using namespace llvm; | 
 | using namespace llvm::dwarf; | 
 |  | 
 | // Handle the Pass registration stuff necessary to use TargetData's. | 
 | static RegisterPass<MachineModuleInfo> | 
 | X("machinemoduleinfo", "Module Information"); | 
 | char MachineModuleInfo::ID = 0; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 |    | 
 | MachineModuleInfo::MachineModuleInfo() | 
 | : ImmutablePass(&ID) | 
 | , LabelIDList() | 
 | , FrameMoves() | 
 | , LandingPads() | 
 | , Personalities() | 
 | , CallsEHReturn(0) | 
 | , CallsUnwindInit(0) | 
 | , DbgInfoAvailable(false) | 
 | { | 
 |   // Always emit "no personality" info | 
 |   Personalities.push_back(NULL); | 
 | } | 
 | MachineModuleInfo::~MachineModuleInfo() { | 
 |  | 
 | } | 
 |  | 
 | /// doInitialization - Initialize the state for a new module. | 
 | /// | 
 | bool MachineModuleInfo::doInitialization() { | 
 |   return false; | 
 | } | 
 |  | 
 | /// doFinalization - Tear down the state after completion of a module. | 
 | /// | 
 | bool MachineModuleInfo::doFinalization() { | 
 |   return false; | 
 | } | 
 |  | 
 | /// BeginFunction - Begin gathering function meta information. | 
 | /// | 
 | void MachineModuleInfo::BeginFunction(MachineFunction *MF) { | 
 |   // Coming soon. | 
 | } | 
 |  | 
 | /// EndFunction - Discard function meta information. | 
 | /// | 
 | void MachineModuleInfo::EndFunction() { | 
 |   // Clean up frame info. | 
 |   FrameMoves.clear(); | 
 |    | 
 |   // Clean up exception info. | 
 |   LandingPads.clear(); | 
 |   TypeInfos.clear(); | 
 |   FilterIds.clear(); | 
 |   FilterEnds.clear(); | 
 |   CallsEHReturn = 0; | 
 |   CallsUnwindInit = 0; | 
 | } | 
 |  | 
 | /// AnalyzeModule - Scan the module for global debug information. | 
 | /// | 
 | void MachineModuleInfo::AnalyzeModule(Module &M) { | 
 |   // Insert functions in the llvm.used array into UsedFunctions. | 
 |   GlobalVariable *GV = M.getGlobalVariable("llvm.used"); | 
 |   if (!GV || !GV->hasInitializer()) return; | 
 |  | 
 |   // Should be an array of 'i8*'. | 
 |   ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); | 
 |   if (InitList == 0) return; | 
 |  | 
 |   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { | 
 |     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(InitList->getOperand(i))) | 
 |       if (CE->getOpcode() == Instruction::BitCast) | 
 |         if (Function *F = dyn_cast<Function>(CE->getOperand(0))) | 
 |           UsedFunctions.insert(F); | 
 |   } | 
 | } | 
 |  | 
 | //===-EH-------------------------------------------------------------------===// | 
 |  | 
 | /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the | 
 | /// specified MachineBasicBlock. | 
 | LandingPadInfo &MachineModuleInfo::getOrCreateLandingPadInfo | 
 |     (MachineBasicBlock *LandingPad) { | 
 |   unsigned N = LandingPads.size(); | 
 |   for (unsigned i = 0; i < N; ++i) { | 
 |     LandingPadInfo &LP = LandingPads[i]; | 
 |     if (LP.LandingPadBlock == LandingPad) | 
 |       return LP; | 
 |   } | 
 |    | 
 |   LandingPads.push_back(LandingPadInfo(LandingPad)); | 
 |   return LandingPads[N]; | 
 | } | 
 |  | 
 | /// addInvoke - Provide the begin and end labels of an invoke style call and | 
 | /// associate it with a try landing pad block. | 
 | void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad, | 
 |                                   unsigned BeginLabel, unsigned EndLabel) { | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   LP.BeginLabels.push_back(BeginLabel); | 
 |   LP.EndLabels.push_back(EndLabel); | 
 | } | 
 |  | 
 | /// addLandingPad - Provide the label of a try LandingPad block. | 
 | /// | 
 | unsigned MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) { | 
 |   unsigned LandingPadLabel = NextLabelID(); | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   LP.LandingPadLabel = LandingPadLabel;   | 
 |   return LandingPadLabel; | 
 | } | 
 |  | 
 | /// addPersonality - Provide the personality function for the exception | 
 | /// information. | 
 | void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad, | 
 |                                        Function *Personality) { | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   LP.Personality = Personality; | 
 |  | 
 |   for (unsigned i = 0; i < Personalities.size(); ++i) | 
 |     if (Personalities[i] == Personality) | 
 |       return; | 
 |    | 
 |   Personalities.push_back(Personality); | 
 | } | 
 |  | 
 | /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. | 
 | /// | 
 | void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad, | 
 |                                         std::vector<GlobalVariable *> &TyInfo) { | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   for (unsigned N = TyInfo.size(); N; --N) | 
 |     LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1])); | 
 | } | 
 |  | 
 | /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. | 
 | /// | 
 | void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad, | 
 |                                         std::vector<GlobalVariable *> &TyInfo) { | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   std::vector<unsigned> IdsInFilter(TyInfo.size()); | 
 |   for (unsigned I = 0, E = TyInfo.size(); I != E; ++I) | 
 |     IdsInFilter[I] = getTypeIDFor(TyInfo[I]); | 
 |   LP.TypeIds.push_back(getFilterIDFor(IdsInFilter)); | 
 | } | 
 |  | 
 | /// addCleanup - Add a cleanup action for a landing pad. | 
 | /// | 
 | void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { | 
 |   LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); | 
 |   LP.TypeIds.push_back(0); | 
 | } | 
 |  | 
 | /// TidyLandingPads - Remap landing pad labels and remove any deleted landing | 
 | /// pads. | 
 | void MachineModuleInfo::TidyLandingPads() { | 
 |   for (unsigned i = 0; i != LandingPads.size(); ) { | 
 |     LandingPadInfo &LandingPad = LandingPads[i]; | 
 |     LandingPad.LandingPadLabel = MappedLabel(LandingPad.LandingPadLabel); | 
 |  | 
 |     // Special case: we *should* emit LPs with null LP MBB. This indicates | 
 |     // "nounwind" case. | 
 |     if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) { | 
 |       LandingPads.erase(LandingPads.begin() + i); | 
 |       continue; | 
 |     } | 
 |  | 
 |     for (unsigned j=0; j != LandingPads[i].BeginLabels.size(); ) { | 
 |       unsigned BeginLabel = MappedLabel(LandingPad.BeginLabels[j]); | 
 |       unsigned EndLabel = MappedLabel(LandingPad.EndLabels[j]); | 
 |  | 
 |       if (!BeginLabel || !EndLabel) { | 
 |         LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j); | 
 |         LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j); | 
 |         continue; | 
 |       } | 
 |  | 
 |       LandingPad.BeginLabels[j] = BeginLabel; | 
 |       LandingPad.EndLabels[j] = EndLabel; | 
 |       ++j; | 
 |     } | 
 |  | 
 |     // Remove landing pads with no try-ranges. | 
 |     if (LandingPads[i].BeginLabels.empty()) { | 
 |       LandingPads.erase(LandingPads.begin() + i); | 
 |       continue; | 
 |     } | 
 |  | 
 |     // If there is no landing pad, ensure that the list of typeids is empty. | 
 |     // If the only typeid is a cleanup, this is the same as having no typeids. | 
 |     if (!LandingPad.LandingPadBlock || | 
 |         (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0])) | 
 |       LandingPad.TypeIds.clear(); | 
 |  | 
 |     ++i; | 
 |   } | 
 | } | 
 |  | 
 | /// getTypeIDFor - Return the type id for the specified typeinfo.  This is  | 
 | /// function wide. | 
 | unsigned MachineModuleInfo::getTypeIDFor(GlobalVariable *TI) { | 
 |   for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i) | 
 |     if (TypeInfos[i] == TI) return i + 1; | 
 |  | 
 |   TypeInfos.push_back(TI); | 
 |   return TypeInfos.size(); | 
 | } | 
 |  | 
 | /// getFilterIDFor - Return the filter id for the specified typeinfos.  This is | 
 | /// function wide. | 
 | int MachineModuleInfo::getFilterIDFor(std::vector<unsigned> &TyIds) { | 
 |   // If the new filter coincides with the tail of an existing filter, then | 
 |   // re-use the existing filter.  Folding filters more than this requires | 
 |   // re-ordering filters and/or their elements - probably not worth it. | 
 |   for (std::vector<unsigned>::iterator I = FilterEnds.begin(), | 
 |        E = FilterEnds.end(); I != E; ++I) { | 
 |     unsigned i = *I, j = TyIds.size(); | 
 |  | 
 |     while (i && j) | 
 |       if (FilterIds[--i] != TyIds[--j]) | 
 |         goto try_next; | 
 |  | 
 |     if (!j) | 
 |       // The new filter coincides with range [i, end) of the existing filter. | 
 |       return -(1 + i); | 
 |  | 
 | try_next:; | 
 |   } | 
 |  | 
 |   // Add the new filter. | 
 |   int FilterID = -(1 + FilterIds.size()); | 
 |   FilterIds.reserve(FilterIds.size() + TyIds.size() + 1); | 
 |   for (unsigned I = 0, N = TyIds.size(); I != N; ++I) | 
 |     FilterIds.push_back(TyIds[I]); | 
 |   FilterEnds.push_back(FilterIds.size()); | 
 |   FilterIds.push_back(0); // terminator | 
 |   return FilterID; | 
 | } | 
 |  | 
 | /// getPersonality - Return the personality function for the current function. | 
 | Function *MachineModuleInfo::getPersonality() const { | 
 |   // FIXME: Until PR1414 will be fixed, we're using 1 personality function per | 
 |   // function | 
 |   return !LandingPads.empty() ? LandingPads[0].Personality : NULL; | 
 | } | 
 |  | 
 | /// getPersonalityIndex - Return unique index for current personality | 
 | /// function. NULL personality function should always get zero index. | 
 | unsigned MachineModuleInfo::getPersonalityIndex() const { | 
 |   const Function* Personality = NULL; | 
 |    | 
 |   // Scan landing pads. If there is at least one non-NULL personality - use it. | 
 |   for (unsigned i = 0; i != LandingPads.size(); ++i) | 
 |     if (LandingPads[i].Personality) { | 
 |       Personality = LandingPads[i].Personality; | 
 |       break; | 
 |     } | 
 |    | 
 |   for (unsigned i = 0; i < Personalities.size(); ++i) { | 
 |     if (Personalities[i] == Personality) | 
 |       return i; | 
 |   } | 
 |  | 
 |   // This should never happen | 
 |   assert(0 && "Personality function should be set!"); | 
 |   return 0; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | /// DebugLabelFolding pass - This pass prunes out redundant labels.  This allows | 
 | /// a info consumer to determine if the range of two labels is empty, by seeing | 
 | /// if the labels map to the same reduced label. | 
 |  | 
 | namespace llvm { | 
 |  | 
 | struct DebugLabelFolder : public MachineFunctionPass { | 
 |   static char ID; | 
 |   DebugLabelFolder() : MachineFunctionPass(&ID) {} | 
 |  | 
 |   virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
 |     AU.addPreservedID(MachineLoopInfoID); | 
 |     AU.addPreservedID(MachineDominatorsID); | 
 |     MachineFunctionPass::getAnalysisUsage(AU); | 
 |   } | 
 |  | 
 |   virtual bool runOnMachineFunction(MachineFunction &MF); | 
 |   virtual const char *getPassName() const { return "Label Folder"; } | 
 | }; | 
 |  | 
 | char DebugLabelFolder::ID = 0; | 
 |  | 
 | bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) { | 
 |   // Get machine module info. | 
 |   MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>(); | 
 |   if (!MMI) return false; | 
 |    | 
 |   // Track if change is made. | 
 |   bool MadeChange = false; | 
 |   // No prior label to begin. | 
 |   unsigned PriorLabel = 0; | 
 |    | 
 |   // Iterate through basic blocks. | 
 |   for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); | 
 |        BB != E; ++BB) { | 
 |     // Iterate through instructions. | 
 |     for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { | 
 |       // Is it a label. | 
 |       if (I->isDebugLabel()) { | 
 |         // The label ID # is always operand #0, an immediate. | 
 |         unsigned NextLabel = I->getOperand(0).getImm(); | 
 |          | 
 |         // If there was an immediate prior label. | 
 |         if (PriorLabel) { | 
 |           // Remap the current label to prior label. | 
 |           MMI->RemapLabel(NextLabel, PriorLabel); | 
 |           // Delete the current label. | 
 |           I = BB->erase(I); | 
 |           // Indicate a change has been made. | 
 |           MadeChange = true; | 
 |           continue; | 
 |         } else { | 
 |           // Start a new round. | 
 |           PriorLabel = NextLabel; | 
 |         } | 
 |        } else { | 
 |         // No consecutive labels. | 
 |         PriorLabel = 0; | 
 |       } | 
 |        | 
 |       ++I; | 
 |     } | 
 |   } | 
 |    | 
 |   return MadeChange; | 
 | } | 
 |  | 
 | FunctionPass *createDebugLabelFoldingPass() { return new DebugLabelFolder(); } | 
 |  | 
 | } | 
 |  |