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 10f9448bf3SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11f9448bf3SDimitry Andric #include "llvm/ADT/DenseMap.h" 12d88c1a5aSDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 13f9448bf3SDimitry Andric #include "llvm/ADT/StringRef.h" 147d523365SDimitry Andric #include "llvm/ADT/TinyPtrVector.h" 15f22ef01cSRoman Divacky #include "llvm/CodeGen/MachineFunction.h" 16d88c1a5aSDimitry Andric #include "llvm/CodeGen/MachineFunctionInitializer.h" 17f9448bf3SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 18f22ef01cSRoman Divacky #include "llvm/CodeGen/Passes.h" 19f9448bf3SDimitry Andric #include "llvm/IR/BasicBlock.h" 20139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h" 21d88c1a5aSDimitry Andric #include "llvm/IR/Instructions.h" 22139f7f9bSDimitry Andric #include "llvm/IR/Module.h" 23f9448bf3SDimitry Andric #include "llvm/IR/Value.h" 24f9448bf3SDimitry Andric #include "llvm/IR/ValueHandle.h" 25f9448bf3SDimitry Andric #include "llvm/MC/MCContext.h" 26f22ef01cSRoman Divacky #include "llvm/MC/MCSymbol.h" 27f9448bf3SDimitry Andric #include "llvm/Pass.h" 28f9448bf3SDimitry Andric #include "llvm/Support/Casting.h" 29f22ef01cSRoman Divacky #include "llvm/Support/ErrorHandling.h" 30d88c1a5aSDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 31d88c1a5aSDimitry Andric #include "llvm/Target/TargetMachine.h" 32f9448bf3SDimitry Andric #include <algorithm> 33f9448bf3SDimitry Andric #include <cassert> 34f9448bf3SDimitry Andric #include <memory> 35f9448bf3SDimitry Andric #include <utility> 36f9448bf3SDimitry Andric #include <vector> 37f9448bf3SDimitry Andric 38f22ef01cSRoman Divacky using namespace llvm; 39f22ef01cSRoman Divacky using namespace llvm::dwarf; 40f22ef01cSRoman Divacky 413861d79fSDimitry Andric // Handle the Pass registration stuff necessary to use DataLayout's. 42d8866befSDimitry Andric INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo", 432754fe60SDimitry Andric "Machine Module Information", false, false) 44f22ef01cSRoman Divacky char MachineModuleInfo::ID = 0; 45f22ef01cSRoman Divacky 46f22ef01cSRoman Divacky // Out of line virtual method. 47f9448bf3SDimitry Andric MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; 48f22ef01cSRoman Divacky 49f22ef01cSRoman Divacky namespace llvm { 50f9448bf3SDimitry Andric 517d523365SDimitry Andric class MMIAddrLabelMapCallbackPtr final : CallbackVH { 52f9448bf3SDimitry Andric MMIAddrLabelMap *Map = nullptr; 53f9448bf3SDimitry Andric 54f22ef01cSRoman Divacky public: 55f9448bf3SDimitry Andric MMIAddrLabelMapCallbackPtr() = default; 56f9448bf3SDimitry Andric MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V) {} 57f22ef01cSRoman Divacky 58f22ef01cSRoman Divacky void setPtr(BasicBlock *BB) { 59f22ef01cSRoman Divacky ValueHandleBase::operator=(BB); 60f22ef01cSRoman Divacky } 61f22ef01cSRoman Divacky 62f22ef01cSRoman Divacky void setMap(MMIAddrLabelMap *map) { Map = map; } 63f22ef01cSRoman Divacky 6491bc56edSDimitry Andric void deleted() override; 6591bc56edSDimitry Andric void allUsesReplacedWith(Value *V2) override; 66f22ef01cSRoman Divacky }; 67f22ef01cSRoman Divacky 68f22ef01cSRoman Divacky class MMIAddrLabelMap { 69f22ef01cSRoman Divacky MCContext &Context; 70f22ef01cSRoman Divacky struct AddrLabelSymEntry { 71d88c1a5aSDimitry Andric /// The symbols for the label. 723dac3a9bSDimitry Andric TinyPtrVector<MCSymbol *> Symbols; 73f22ef01cSRoman Divacky 74f22ef01cSRoman Divacky Function *Fn; // The containing function of the BasicBlock. 75f22ef01cSRoman Divacky unsigned Index; // The index in BBCallbacks for the BasicBlock. 76f22ef01cSRoman Divacky }; 77f22ef01cSRoman Divacky 78f22ef01cSRoman Divacky DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry> AddrLabelSymbols; 79f22ef01cSRoman Divacky 80d88c1a5aSDimitry Andric /// Callbacks for the BasicBlock's that we have entries for. We use this so 81d88c1a5aSDimitry Andric /// we get notified if a block is deleted or RAUWd. 82f22ef01cSRoman Divacky std::vector<MMIAddrLabelMapCallbackPtr> BBCallbacks; 83f22ef01cSRoman Divacky 84d88c1a5aSDimitry Andric /// This is a per-function list of symbols whose corresponding BasicBlock got 85d88c1a5aSDimitry Andric /// deleted. These symbols need to be emitted at some point in the file, so 86d88c1a5aSDimitry Andric /// AsmPrinter emits them after the function body. 87f22ef01cSRoman Divacky DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>> 88f22ef01cSRoman Divacky DeletedAddrLabelsNeedingEmission; 89f22ef01cSRoman Divacky 90f9448bf3SDimitry Andric public: 91f22ef01cSRoman Divacky MMIAddrLabelMap(MCContext &context) : Context(context) {} 92f9448bf3SDimitry Andric 93f22ef01cSRoman Divacky ~MMIAddrLabelMap() { 94f22ef01cSRoman Divacky assert(DeletedAddrLabelsNeedingEmission.empty() && 95f22ef01cSRoman Divacky "Some labels for deleted blocks never got emitted"); 96f22ef01cSRoman Divacky } 97f22ef01cSRoman Divacky 983dac3a9bSDimitry Andric ArrayRef<MCSymbol *> getAddrLabelSymbolToEmit(BasicBlock *BB); 99f22ef01cSRoman Divacky 100f22ef01cSRoman Divacky void takeDeletedSymbolsForFunction(Function *F, 101f22ef01cSRoman Divacky std::vector<MCSymbol*> &Result); 102f22ef01cSRoman Divacky 103f22ef01cSRoman Divacky void UpdateForDeletedBlock(BasicBlock *BB); 104f22ef01cSRoman Divacky void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New); 105f22ef01cSRoman Divacky }; 106f9448bf3SDimitry Andric 107f9448bf3SDimitry Andric } // end namespace llvm 108f22ef01cSRoman Divacky 1093dac3a9bSDimitry Andric ArrayRef<MCSymbol *> MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) { 110f22ef01cSRoman Divacky assert(BB->hasAddressTaken() && 111f22ef01cSRoman Divacky "Shouldn't get label for block without address taken"); 112f22ef01cSRoman Divacky AddrLabelSymEntry &Entry = AddrLabelSymbols[BB]; 113f22ef01cSRoman Divacky 114f22ef01cSRoman Divacky // If we already had an entry for this block, just return it. 1153dac3a9bSDimitry Andric if (!Entry.Symbols.empty()) { 116f22ef01cSRoman Divacky assert(BB->getParent() == Entry.Fn && "Parent changed"); 1173dac3a9bSDimitry Andric return Entry.Symbols; 118f22ef01cSRoman Divacky } 119f22ef01cSRoman Divacky 120f22ef01cSRoman Divacky // Otherwise, this is a new entry, create a new symbol for it and add an 121f22ef01cSRoman Divacky // entry to BBCallbacks so we can be notified if the BB is deleted or RAUWd. 12297bc6c73SDimitry Andric BBCallbacks.emplace_back(BB); 123f22ef01cSRoman Divacky BBCallbacks.back().setMap(this); 124f22ef01cSRoman Divacky Entry.Index = BBCallbacks.size() - 1; 125f22ef01cSRoman Divacky Entry.Fn = BB->getParent(); 1263dac3a9bSDimitry Andric Entry.Symbols.push_back(Context.createTempSymbol()); 1273dac3a9bSDimitry Andric return Entry.Symbols; 128f22ef01cSRoman Divacky } 129f22ef01cSRoman Divacky 130d88c1a5aSDimitry Andric /// If we have any deleted symbols for F, return them. 131f22ef01cSRoman Divacky void MMIAddrLabelMap:: 132f22ef01cSRoman Divacky takeDeletedSymbolsForFunction(Function *F, std::vector<MCSymbol*> &Result) { 133f22ef01cSRoman Divacky DenseMap<AssertingVH<Function>, std::vector<MCSymbol*>>::iterator I = 134f22ef01cSRoman Divacky DeletedAddrLabelsNeedingEmission.find(F); 135f22ef01cSRoman Divacky 136f22ef01cSRoman Divacky // If there are no entries for the function, just return. 137f22ef01cSRoman Divacky if (I == DeletedAddrLabelsNeedingEmission.end()) return; 138f22ef01cSRoman Divacky 139f22ef01cSRoman Divacky // Otherwise, take the list. 140f22ef01cSRoman Divacky std::swap(Result, I->second); 141f22ef01cSRoman Divacky DeletedAddrLabelsNeedingEmission.erase(I); 142f22ef01cSRoman Divacky } 143f22ef01cSRoman Divacky 144f22ef01cSRoman Divacky void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) { 145f22ef01cSRoman Divacky // If the block got deleted, there is no need for the symbol. If the symbol 146f22ef01cSRoman Divacky // was already emitted, we can just forget about it, otherwise we need to 147f22ef01cSRoman Divacky // queue it up for later emission when the function is output. 1483dac3a9bSDimitry Andric AddrLabelSymEntry Entry = std::move(AddrLabelSymbols[BB]); 149f22ef01cSRoman Divacky AddrLabelSymbols.erase(BB); 1503dac3a9bSDimitry Andric assert(!Entry.Symbols.empty() && "Didn't have a symbol, why a callback?"); 15191bc56edSDimitry Andric BBCallbacks[Entry.Index] = nullptr; // Clear the callback. 152f22ef01cSRoman Divacky 15391bc56edSDimitry Andric assert((BB->getParent() == nullptr || BB->getParent() == Entry.Fn) && 154f22ef01cSRoman Divacky "Block/parent mismatch"); 155f22ef01cSRoman Divacky 1563dac3a9bSDimitry Andric for (MCSymbol *Sym : Entry.Symbols) { 157f22ef01cSRoman Divacky if (Sym->isDefined()) 158f22ef01cSRoman Divacky return; 159f22ef01cSRoman Divacky 160f22ef01cSRoman Divacky // If the block is not yet defined, we need to emit it at the end of the 161f22ef01cSRoman Divacky // function. Add the symbol to the DeletedAddrLabelsNeedingEmission list 162f22ef01cSRoman Divacky // for the containing Function. Since the block is being deleted, its 163f22ef01cSRoman Divacky // parent may already be removed, we have to get the function from 'Entry'. 164f22ef01cSRoman Divacky DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym); 165f22ef01cSRoman Divacky } 166f22ef01cSRoman Divacky } 167f22ef01cSRoman Divacky 168f22ef01cSRoman Divacky void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) { 169f22ef01cSRoman Divacky // Get the entry for the RAUW'd block and remove it from our map. 1703dac3a9bSDimitry Andric AddrLabelSymEntry OldEntry = std::move(AddrLabelSymbols[Old]); 171f22ef01cSRoman Divacky AddrLabelSymbols.erase(Old); 1723dac3a9bSDimitry Andric assert(!OldEntry.Symbols.empty() && "Didn't have a symbol, why a callback?"); 173f22ef01cSRoman Divacky 174f22ef01cSRoman Divacky AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New]; 175f22ef01cSRoman Divacky 176f22ef01cSRoman Divacky // If New is not address taken, just move our symbol over to it. 1773dac3a9bSDimitry Andric if (NewEntry.Symbols.empty()) { 178f22ef01cSRoman Divacky BBCallbacks[OldEntry.Index].setPtr(New); // Update the callback. 1793dac3a9bSDimitry Andric NewEntry = std::move(OldEntry); // Set New's entry. 180f22ef01cSRoman Divacky return; 181f22ef01cSRoman Divacky } 182f22ef01cSRoman Divacky 18391bc56edSDimitry Andric BBCallbacks[OldEntry.Index] = nullptr; // Update the callback. 184f22ef01cSRoman Divacky 1853dac3a9bSDimitry Andric // Otherwise, we need to add the old symbols to the new block's set. 1863dac3a9bSDimitry Andric NewEntry.Symbols.insert(NewEntry.Symbols.end(), OldEntry.Symbols.begin(), 1873dac3a9bSDimitry Andric OldEntry.Symbols.end()); 188f22ef01cSRoman Divacky } 189f22ef01cSRoman Divacky 190f22ef01cSRoman Divacky void MMIAddrLabelMapCallbackPtr::deleted() { 191f22ef01cSRoman Divacky Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr())); 192f22ef01cSRoman Divacky } 193f22ef01cSRoman Divacky 194f22ef01cSRoman Divacky void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { 195f22ef01cSRoman Divacky Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2)); 196f22ef01cSRoman Divacky } 197f22ef01cSRoman Divacky 198d88c1a5aSDimitry Andric MachineModuleInfo::MachineModuleInfo(const TargetMachine *TM) 199d88c1a5aSDimitry Andric : ImmutablePass(ID), TM(*TM), 200d88c1a5aSDimitry Andric Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(), 201d88c1a5aSDimitry Andric TM->getObjFileLowering(), nullptr, false) { 2022754fe60SDimitry Andric initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); 203f22ef01cSRoman Divacky } 204f22ef01cSRoman Divacky 205f9448bf3SDimitry Andric MachineModuleInfo::~MachineModuleInfo() = default; 206f22ef01cSRoman Divacky 207139f7f9bSDimitry Andric bool MachineModuleInfo::doInitialization(Module &M) { 20891bc56edSDimitry Andric ObjFileMMI = nullptr; 209139f7f9bSDimitry Andric CurCallSite = 0; 21039d628a0SDimitry Andric DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; 21191bc56edSDimitry Andric AddrLabelSymbols = nullptr; 212d88c1a5aSDimitry Andric TheModule = &M; 213139f7f9bSDimitry Andric 214f22ef01cSRoman Divacky return false; 215f22ef01cSRoman Divacky } 216f22ef01cSRoman Divacky 217139f7f9bSDimitry Andric bool MachineModuleInfo::doFinalization(Module &M) { 218139f7f9bSDimitry Andric Personalities.clear(); 219139f7f9bSDimitry Andric 220f22ef01cSRoman Divacky delete AddrLabelSymbols; 22191bc56edSDimitry Andric AddrLabelSymbols = nullptr; 222139f7f9bSDimitry Andric 223139f7f9bSDimitry Andric Context.reset(); 224139f7f9bSDimitry Andric 225139f7f9bSDimitry Andric delete ObjFileMMI; 22691bc56edSDimitry Andric ObjFileMMI = nullptr; 227139f7f9bSDimitry Andric 228f22ef01cSRoman Divacky return false; 229f22ef01cSRoman Divacky } 230f22ef01cSRoman Divacky 231f22ef01cSRoman Divacky //===- Address of Block Management ----------------------------------------===// 232f22ef01cSRoman Divacky 2333dac3a9bSDimitry Andric ArrayRef<MCSymbol *> 2343dac3a9bSDimitry Andric MachineModuleInfo::getAddrLabelSymbolToEmit(const BasicBlock *BB) { 235f22ef01cSRoman Divacky // Lazily create AddrLabelSymbols. 23691bc56edSDimitry Andric if (!AddrLabelSymbols) 237f22ef01cSRoman Divacky AddrLabelSymbols = new MMIAddrLabelMap(Context); 238f22ef01cSRoman Divacky return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast<BasicBlock*>(BB)); 239f22ef01cSRoman Divacky } 240f22ef01cSRoman Divacky 241f22ef01cSRoman Divacky void MachineModuleInfo:: 242f22ef01cSRoman Divacky takeDeletedSymbolsForFunction(const Function *F, 243f22ef01cSRoman Divacky std::vector<MCSymbol*> &Result) { 244f22ef01cSRoman Divacky // If no blocks have had their addresses taken, we're done. 24591bc56edSDimitry Andric if (!AddrLabelSymbols) return; 246f22ef01cSRoman Divacky return AddrLabelSymbols-> 247f22ef01cSRoman Divacky takeDeletedSymbolsForFunction(const_cast<Function*>(F), Result); 248f22ef01cSRoman Divacky } 249f22ef01cSRoman Divacky 250d88c1a5aSDimitry Andric /// \name Exception Handling 251d88c1a5aSDimitry Andric /// \{ 252f22ef01cSRoman Divacky 253875ed548SDimitry Andric void MachineModuleInfo::addPersonality(const Function *Personality) { 254f22ef01cSRoman Divacky for (unsigned i = 0; i < Personalities.size(); ++i) 255f22ef01cSRoman Divacky if (Personalities[i] == Personality) 256f22ef01cSRoman Divacky return; 257f22ef01cSRoman Divacky Personalities.push_back(Personality); 258f22ef01cSRoman Divacky } 259f22ef01cSRoman Divacky 260d88c1a5aSDimitry Andric /// \} 261d88c1a5aSDimitry Andric 262d88c1a5aSDimitry Andric MachineFunction &MachineModuleInfo::getMachineFunction(const Function &F) { 263d88c1a5aSDimitry Andric // Shortcut for the common case where a sequence of MachineFunctionPasses 264d88c1a5aSDimitry Andric // all query for the same Function. 265d88c1a5aSDimitry Andric if (LastRequest == &F) 266d88c1a5aSDimitry Andric return *LastResult; 267d88c1a5aSDimitry Andric 268d88c1a5aSDimitry Andric auto I = MachineFunctions.insert( 269d88c1a5aSDimitry Andric std::make_pair(&F, std::unique_ptr<MachineFunction>())); 270d88c1a5aSDimitry Andric MachineFunction *MF; 271d88c1a5aSDimitry Andric if (I.second) { 272d88c1a5aSDimitry Andric // No pre-existing machine function, create a new one. 273d88c1a5aSDimitry Andric MF = new MachineFunction(&F, TM, NextFnNum++, *this); 274d88c1a5aSDimitry Andric // Update the set entry. 275d88c1a5aSDimitry Andric I.first->second.reset(MF); 276d88c1a5aSDimitry Andric 277d88c1a5aSDimitry Andric if (MFInitializer) 278d88c1a5aSDimitry Andric if (MFInitializer->initializeMachineFunction(*MF)) 279d88c1a5aSDimitry Andric report_fatal_error("Unable to initialize machine function"); 280d88c1a5aSDimitry Andric } else { 281d88c1a5aSDimitry Andric MF = I.first->second.get(); 282f22ef01cSRoman Divacky } 283f22ef01cSRoman Divacky 284d88c1a5aSDimitry Andric LastRequest = &F; 285d88c1a5aSDimitry Andric LastResult = MF; 286d88c1a5aSDimitry Andric return *MF; 287f22ef01cSRoman Divacky } 288f22ef01cSRoman Divacky 289d88c1a5aSDimitry Andric void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { 290d88c1a5aSDimitry Andric MachineFunctions.erase(&F); 291d88c1a5aSDimitry Andric LastRequest = nullptr; 292d88c1a5aSDimitry Andric LastResult = nullptr; 293f22ef01cSRoman Divacky } 294f22ef01cSRoman Divacky 295d88c1a5aSDimitry Andric namespace { 296f9448bf3SDimitry Andric 297d88c1a5aSDimitry Andric /// This pass frees the MachineFunction object associated with a Function. 298d88c1a5aSDimitry Andric class FreeMachineFunction : public FunctionPass { 299d88c1a5aSDimitry Andric public: 300d88c1a5aSDimitry Andric static char ID; 301f9448bf3SDimitry Andric 302d88c1a5aSDimitry Andric FreeMachineFunction() : FunctionPass(ID) {} 303d88c1a5aSDimitry Andric 304d88c1a5aSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 305d88c1a5aSDimitry Andric AU.addRequired<MachineModuleInfo>(); 306d88c1a5aSDimitry Andric AU.addPreserved<MachineModuleInfo>(); 307ff0cc061SDimitry Andric } 308ff0cc061SDimitry Andric 309d88c1a5aSDimitry Andric bool runOnFunction(Function &F) override { 310d88c1a5aSDimitry Andric MachineModuleInfo &MMI = getAnalysis<MachineModuleInfo>(); 311d88c1a5aSDimitry Andric MMI.deleteMachineFunctionFor(F); 312d88c1a5aSDimitry Andric return true; 313ff0cc061SDimitry Andric } 3147a7e6055SDimitry Andric 3157a7e6055SDimitry Andric StringRef getPassName() const override { 3167a7e6055SDimitry Andric return "Free MachineFunction"; 3177a7e6055SDimitry Andric } 318d88c1a5aSDimitry Andric }; 319f9448bf3SDimitry Andric 320d88c1a5aSDimitry Andric } // end anonymous namespace 321ff0cc061SDimitry Andric 322f9448bf3SDimitry Andric char FreeMachineFunction::ID; 323f9448bf3SDimitry Andric 324f9448bf3SDimitry Andric FunctionPass *llvm::createFreeMachineFunctionPass() { 325d88c1a5aSDimitry Andric return new FreeMachineFunction(); 326f22ef01cSRoman Divacky } 327f22ef01cSRoman Divacky 328d88c1a5aSDimitry Andric //===- MMI building helpers -----------------------------------------------===// 329f22ef01cSRoman Divacky 330d88c1a5aSDimitry Andric void llvm::computeUsesVAFloatArgument(const CallInst &I, 331d88c1a5aSDimitry Andric MachineModuleInfo &MMI) { 332d88c1a5aSDimitry Andric FunctionType *FT = 333d88c1a5aSDimitry Andric cast<FunctionType>(I.getCalledValue()->getType()->getContainedType(0)); 334d88c1a5aSDimitry Andric if (FT->isVarArg() && !MMI.usesVAFloatArgument()) { 335d88c1a5aSDimitry Andric for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { 336d88c1a5aSDimitry Andric Type *T = I.getArgOperand(i)->getType(); 337d88c1a5aSDimitry Andric for (auto i : post_order(T)) { 338d88c1a5aSDimitry Andric if (i->isFloatingPointTy()) { 339d88c1a5aSDimitry Andric MMI.setUsesVAFloatArgument(true); 340d88c1a5aSDimitry Andric return; 341f22ef01cSRoman Divacky } 342f22ef01cSRoman Divacky } 3436122f3e6SDimitry Andric } 344f22ef01cSRoman Divacky } 345f22ef01cSRoman Divacky } 346