std::string GCOVProfiler::mangleName(DICompileUnit CU, const char *NewStem) { if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { MDNode *N = GCov->getOperand(i); if (N->getNumOperands() != 2) continue; MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1)); if (!GCovFile || !CompileUnit) continue; if (CompileUnit == CU) { SmallString<128> Filename = GCovFile->getString(); sys::path::replace_extension(Filename, NewStem); return Filename.str(); } } } SmallString<128> Filename = CU.getFilename(); sys::path::replace_extension(Filename, NewStem); StringRef FName = sys::path::filename(Filename); SmallString<128> CurPath; if (sys::fs::current_path(CurPath)) return FName; sys::path::append(CurPath, FName); return CurPath.str(); }
Action* IRParser::parseAction(MDNode* node){ Value* tagValue = node->getOperand(0); ActionTag* tag = new ActionTag(); if (tagValue != NULL){ MDNode* tagArray = cast<MDNode>(tagValue); for (unsigned i = 0, e = tagArray->getNumOperands(); i != e; ++i) { MDString* tagMD = cast<MDString>(tagArray->getOperand(i)); tag->add(tagMD->getString()); } } Pattern* ip = parsePattern(inputs, node->getOperand(1)); Pattern* op = parsePattern(outputs, node->getOperand(2)); Pattern* pp = parsePattern(inputs, node->getOperand(3)); Procedure* scheduler = parseProc(cast<MDNode>(node->getOperand(4))); Procedure* body = parseProc(cast<MDNode>(node->getOperand(5))); Action* action = new Action(tag, ip, op, pp, scheduler, body, actor); putAction(tag, action); return action; }
/// \brief Find string metadata for loop, if it exists return true, else return /// false. bool llvm::findStringMetadataForLoop(Loop *TheLoop, StringRef Name) { MDNode *LoopID = TheLoop->getLoopID(); // Return false if LoopID is false. if (!LoopID) return false; // First operand should refer to the loop id itself. assert(LoopID->getNumOperands() > 0 && "requires at least one operand"); assert(LoopID->getOperand(0) == LoopID && "invalid loop id"); // Iterate over LoopID operands and look for MDString Metadata for (unsigned i = 1, e = LoopID->getNumOperands(); i < e; ++i) { MDNode *MD = dyn_cast<MDNode>(LoopID->getOperand(i)); if (!MD) continue; MDString *S = dyn_cast<MDString>(MD->getOperand(0)); if (!S) continue; // Return true if MDString holds expected MetaData. if (Name.equals(S->getString())) return true; } return false; }
/// parseMetadata - Parse metadata from the module void LTOModule::parseMetadata() { // Linker Options if (Value *Val = getModule().getModuleFlag("Linker Options")) { MDNode *LinkerOptions = cast<MDNode>(Val); for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); StringRef Op = _linkeropt_strings. GetOrCreateValue(MDOption->getString()).getKey(); StringRef DepLibName = _target->getSubtargetImpl() ->getTargetLowering() ->getObjFileLowering() .getDepLibFromLinkerOpt(Op); if (!DepLibName.empty()) _deplibs.push_back(DepLibName.data()); else if (!Op.empty()) _linkeropts.push_back(Op.data()); } } } // Add other interesting metadata here. }
/// emitModuleFlags - Perform code emission for module flags. void TargetLoweringObjectFileMachO:: emitModuleFlags(MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags, Mangler &Mang, const TargetMachine &TM) const { unsigned VersionVal = 0; unsigned ImageInfoFlags = 0; MDNode *LinkerOptions = nullptr; StringRef SectionVal; for (ArrayRef<Module::ModuleFlagEntry>::iterator i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) { const Module::ModuleFlagEntry &MFE = *i; // Ignore flags with 'Require' behavior. if (MFE.Behavior == Module::Require) continue; StringRef Key = MFE.Key->getString(); Value *Val = MFE.Val; if (Key == "Objective-C Image Info Version") { VersionVal = cast<ConstantInt>(Val)->getZExtValue(); } else if (Key == "Objective-C Garbage Collection" || Key == "Objective-C GC Only" || Key == "Objective-C Is Simulated") { ImageInfoFlags |= cast<ConstantInt>(Val)->getZExtValue(); } else if (Key == "Objective-C Image Info Section") { SectionVal = cast<MDString>(Val)->getString(); } else if (Key == "Linker Options") { LinkerOptions = cast<MDNode>(Val); } } // Emit the linker options if present. if (LinkerOptions) { for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); SmallVector<std::string, 4> StrOptions; // Convert to strings. for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); StrOptions.push_back(MDOption->getString()); } Streamer.EmitLinkerOptions(StrOptions); } } // The section is mandatory. If we don't have it, then we don't have GC info. if (SectionVal.empty()) return; StringRef Segment, Section; unsigned TAA = 0, StubSize = 0; bool TAAParsed; std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier(SectionVal, Segment, Section, TAA, TAAParsed, StubSize); if (!ErrorCode.empty()) // If invalid, report the error with report_fatal_error. report_fatal_error("Invalid section specifier '" + Section + "': " + ErrorCode + "."); // Get the section. const MCSectionMachO *S = getContext().getMachOSection(Segment, Section, TAA, StubSize, SectionKind::getDataNoRel()); Streamer.SwitchSection(S); Streamer.EmitLabel(getContext(). GetOrCreateSymbol(StringRef("L_OBJC_IMAGE_INFO"))); Streamer.EmitIntValue(VersionVal, 4); Streamer.EmitIntValue(ImageInfoFlags, 4); Streamer.AddBlankLine(); }
bool TaskDebugBranchCheck::hasAnnotation(Instruction* i, Value *V, StringRef Ann, uint8_t level) { // Check instruction metadata. //errs() << "0th If\n"; if (Instruction *I = dyn_cast<Instruction>(V)) { if (I->getOpcode() == Instruction::GetElementPtr) { MDNode *MD = i->getMetadata("tyann"); if (MD) { MDString *MDS = cast<MDString>(MD->getOperand(0)); if (MDS->getString().equals(Ann)) { return true; } else return false; } else return false; } MDNode *MD = I->getMetadata("tyann"); //errs() << *V << " 1st If\n"; if (MD) { //errs() << "2nd If\n"; MDString *MDS = cast<MDString>(MD->getOperand(0)); if (MDS->getString().equals(Ann)) { //errs() << "3rd If\n"; //return true; #if 1 ConstantAsMetadata *CAM = cast<ConstantAsMetadata>(MD->getOperand(1)); ConstantInt *CI = cast<ConstantInt>(CAM->getValue()); if (CI->getValue() == level) { //errs() << CI->getValue() << "Level true\n"; return true; } else { //errs() << CI->getValue() << "Level false\n"; return false; } #endif } } } else if (GlobalValue *G = dyn_cast<GlobalValue>(V)) { MDNode *MD = i->getMetadata("tyann"); if (MD) { //errs() << "2nd If\n"; MDString *MDS = cast<MDString>(MD->getOperand(0)); if (MDS->getString().equals(Ann)) { //errs() << "3rd If\n"; return true; #if 0 ConstantAsMetadata *CAM = cast<ConstantAsMetadata>(MD->getOperand(1)); ConstantInt *CI = cast<ConstantInt>(CAM->getValue()); if (CI->getValue() == level) { //errs() << CI->getValue() << "Level true\n"; return true; } else { //errs() << CI->getValue() << "Level false\n"; return false; } #endif } } } // TODO: Check for annotations on globals, parameters. return false; }
/// Merge the linker flags in Src into the Dest module. Error IRLinker::linkModuleFlagsMetadata() { // If the source module has no module flags, we are done. const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); if (!SrcModFlags) return Error::success(); // If the destination module doesn't have module flags yet, then just copy // over the source module's flags. NamedMDNode *DstModFlags = DstM.getOrInsertModuleFlagsMetadata(); if (DstModFlags->getNumOperands() == 0) { for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) DstModFlags->addOperand(SrcModFlags->getOperand(I)); return Error::success(); } // First build a map of the existing module flags and requirements. DenseMap<MDString *, std::pair<MDNode *, unsigned>> Flags; SmallSetVector<MDNode *, 16> Requirements; for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = DstModFlags->getOperand(I); ConstantInt *Behavior = mdconst::extract<ConstantInt>(Op->getOperand(0)); MDString *ID = cast<MDString>(Op->getOperand(1)); if (Behavior->getZExtValue() == Module::Require) { Requirements.insert(cast<MDNode>(Op->getOperand(2))); } else { Flags[ID] = std::make_pair(Op, I); } } // Merge in the flags from the source module, and also collect its set of // requirements. for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) { MDNode *SrcOp = SrcModFlags->getOperand(I); ConstantInt *SrcBehavior = mdconst::extract<ConstantInt>(SrcOp->getOperand(0)); MDString *ID = cast<MDString>(SrcOp->getOperand(1)); MDNode *DstOp; unsigned DstIndex; std::tie(DstOp, DstIndex) = Flags.lookup(ID); unsigned SrcBehaviorValue = SrcBehavior->getZExtValue(); // If this is a requirement, add it and continue. if (SrcBehaviorValue == Module::Require) { // If the destination module does not already have this requirement, add // it. if (Requirements.insert(cast<MDNode>(SrcOp->getOperand(2)))) { DstModFlags->addOperand(SrcOp); } continue; } // If there is no existing flag with this ID, just add it. if (!DstOp) { Flags[ID] = std::make_pair(SrcOp, DstModFlags->getNumOperands()); DstModFlags->addOperand(SrcOp); continue; } // Otherwise, perform a merge. ConstantInt *DstBehavior = mdconst::extract<ConstantInt>(DstOp->getOperand(0)); unsigned DstBehaviorValue = DstBehavior->getZExtValue(); // If either flag has override behavior, handle it first. if (DstBehaviorValue == Module::Override) { // Diagnose inconsistent flags which both have override behavior. if (SrcBehaviorValue == Module::Override && SrcOp->getOperand(2) != DstOp->getOperand(2)) return stringErr("linking module flags '" + ID->getString() + "': IDs have conflicting override values"); continue; } else if (SrcBehaviorValue == Module::Override) { // Update the destination flag to that of the source. DstModFlags->setOperand(DstIndex, SrcOp); Flags[ID].first = SrcOp; continue; } // Diagnose inconsistent merge behavior types. if (SrcBehaviorValue != DstBehaviorValue) return stringErr("linking module flags '" + ID->getString() + "': IDs have conflicting behaviors"); auto replaceDstValue = [&](MDNode *New) { Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New}; MDNode *Flag = MDNode::get(DstM.getContext(), FlagOps); DstModFlags->setOperand(DstIndex, Flag); Flags[ID].first = Flag; }; // Perform the merge for standard behavior types. switch (SrcBehaviorValue) { case Module::Require: case Module::Override: llvm_unreachable("not possible"); case Module::Error: { // Emit an error if the values differ. if (SrcOp->getOperand(2) != DstOp->getOperand(2)) return stringErr("linking module flags '" + ID->getString() + "': IDs have conflicting values"); continue; } case Module::Warning: { // Emit a warning if the values differ. if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { emitWarning("linking module flags '" + ID->getString() + "': IDs have conflicting values"); } continue; } case Module::Append: { MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2)); MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2)); SmallVector<Metadata *, 8> MDs; MDs.reserve(DstValue->getNumOperands() + SrcValue->getNumOperands()); MDs.append(DstValue->op_begin(), DstValue->op_end()); MDs.append(SrcValue->op_begin(), SrcValue->op_end()); replaceDstValue(MDNode::get(DstM.getContext(), MDs)); break; } case Module::AppendUnique: { SmallSetVector<Metadata *, 16> Elts; MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2)); MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2)); Elts.insert(DstValue->op_begin(), DstValue->op_end()); Elts.insert(SrcValue->op_begin(), SrcValue->op_end()); replaceDstValue(MDNode::get(DstM.getContext(), makeArrayRef(Elts.begin(), Elts.end()))); break; } } } // Check all of the requirements. for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { MDNode *Requirement = Requirements[I]; MDString *Flag = cast<MDString>(Requirement->getOperand(0)); Metadata *ReqValue = Requirement->getOperand(1); MDNode *Op = Flags[Flag].first; if (!Op || Op->getOperand(2) != ReqValue) return stringErr("linking module flags '" + Flag->getString() + "': does not have the required value"); } return Error::success(); }
/// PrepareMonoLSDA - Collect information needed by EmitMonoLSDA /// /// This function collects information available only during EndFunction which is needed /// by EmitMonoLSDA and stores it into EHFrameInfo. It is the same as the /// beginning of EmitExceptionTable. /// void DwarfMonoException::PrepareMonoLSDA(FunctionEHFrameInfo *EHFrameInfo) { const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); const MachineFunction *MF = Asm->MF; // Sort the landing pads in order of their type ids. This is used to fold // duplicate actions. SmallVector<const LandingPadInfo *, 64> LandingPads; LandingPads.reserve(PadInfos.size()); for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) LandingPads.push_back(&PadInfos[i]); std::sort(LandingPads.begin(), LandingPads.end(), [](const LandingPadInfo *L, const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; }); // Invokes and nounwind calls have entries in PadMap (due to being bracketed // by try-range labels when lowered). Ordinary calls do not, so appropriate // try-ranges for them need be deduced when using DWARF exception handling. RangeMapType PadMap; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; PadMap[BeginLabel] = P; } } // Compute the call-site table. SmallVector<MonoCallSiteEntry, 64> CallSites; MCSymbol *LastLabel = 0; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (!MI->isLabel()) { continue; } MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); assert(BeginLabel && "Invalid label!"); RangeMapType::iterator L = PadMap.find(BeginLabel); if (L == PadMap.end()) continue; PadRange P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); // Mono emits one landing pad for each CLR exception clause, // and the type info contains the clause index assert (LandingPad->TypeIds.size() == 1); assert (LandingPad->LandingPadLabel); LastLabel = LandingPad->EndLabels[P.RangeIndex]; MonoCallSiteEntry Site = {BeginLabel, LastLabel, LandingPad->LandingPadLabel, LandingPad->TypeIds [0]}; assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && "Invalid landing pad!"); // FIXME: This doesn't work because it includes ranges outside clauses #if 0 // Try to merge with the previous call-site. if (CallSites.size()) { MonoCallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.TypeID == Prev.TypeID) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; continue; } } #endif // Otherwise, create a new call-site. CallSites.push_back(Site); } } // // Compute a mapping from method names to their AOT method index // if (FuncIndexes.size () == 0) { const Module *m = MMI->getModule (); NamedMDNode *indexes = m->getNamedMetadata ("mono.function_indexes"); if (indexes) { for (unsigned int i = 0; i < indexes->getNumOperands (); ++i) { MDNode *n = indexes->getOperand (i); MDString *s = (MDString*)n->getOperand (0); ConstantInt *idx = (ConstantInt*)n->getOperand (1); FuncIndexes.GetOrCreateValue (s->getString (), (int)idx->getLimitedValue () + 1); } } } MonoEHFrameInfo *MonoEH = &EHFrameInfo->MonoEH; // Save information for EmitMonoLSDA MonoEH->MF = Asm->MF; MonoEH->FunctionNumber = Asm->getFunctionNumber(); MonoEH->CallSites.insert(MonoEH->CallSites.begin(), CallSites.begin(), CallSites.end()); MonoEH->TypeInfos = TypeInfos; MonoEH->PadInfos = PadInfos; MonoEH->MonoMethodIdx = FuncIndexes.lookup (Asm->MF->getFunction ()->getName ()) - 1; //outs()<<"A:"<<Asm->MF->getFunction()->getName() << " " << MonoEH->MonoMethodIdx << "\n"; int ThisSlot = Asm->MF->getMonoInfo()->getThisStackSlot(); if (ThisSlot != -1) { unsigned FrameReg; MonoEH->ThisOffset = Asm->MF->getTarget ().getSubtargetImpl ()->getFrameLowering ()->getFrameIndexReference (*Asm->MF, ThisSlot, FrameReg); MonoEH->FrameReg = Asm->MF->getTarget ().getSubtargetImpl ()->getRegisterInfo ()->getDwarfRegNum (FrameReg, true); } else { MonoEH->FrameReg = -1; } }
/// linkModuleFlagsMetadata - Merge the linker flags in Src into the Dest /// module. bool ModuleLinker::linkModuleFlagsMetadata() { const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); if (!SrcModFlags) return false; NamedMDNode *DstModFlags = DstM->getOrInsertModuleFlagsMetadata(); // If the destination module doesn't have module flags yet, then just copy // over the source module's flags. if (DstModFlags->getNumOperands() == 0) { for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) DstModFlags->addOperand(SrcModFlags->getOperand(I)); return false; } bool HasErr = false; // Otherwise, we have to merge them based on their behaviors. First, // categorize all of the nodes in the modules' module flags. If an error or // warning occurs, then emit the appropriate message(s). DenseMap<MDString*, MDNode*> ErrorNode; DenseMap<MDString*, MDNode*> WarningNode; DenseMap<MDString*, MDNode*> OverrideNode; DenseMap<MDString*, SmallSetVector<MDNode*, 8> > RequireNodes; SmallSetVector<MDString*, 16> SeenIDs; HasErr |= categorizeModuleFlagNodes(SrcModFlags, ErrorNode, WarningNode, OverrideNode, RequireNodes, SeenIDs); HasErr |= categorizeModuleFlagNodes(DstModFlags, ErrorNode, WarningNode, OverrideNode, RequireNodes, SeenIDs); // Check that there isn't both an error and warning node for a flag. for (SmallSetVector<MDString*, 16>::iterator I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { MDString *ID = *I; if (ErrorNode[ID] && WarningNode[ID]) HasErr = emitError("linking module flags '" + ID->getString() + "': IDs have conflicting behaviors"); } // Early exit if we had an error. if (HasErr) return true; // Get the destination's module flags ready for new operands. DstModFlags->dropAllReferences(); // Add all of the module flags to the destination module. DenseMap<MDString*, SmallVector<MDNode*, 4> > AddedNodes; for (SmallSetVector<MDString*, 16>::iterator I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { MDString *ID = *I; if (OverrideNode[ID]) { DstModFlags->addOperand(OverrideNode[ID]); AddedNodes[ID].push_back(OverrideNode[ID]); } else if (ErrorNode[ID]) { DstModFlags->addOperand(ErrorNode[ID]); AddedNodes[ID].push_back(ErrorNode[ID]); } else if (WarningNode[ID]) { DstModFlags->addOperand(WarningNode[ID]); AddedNodes[ID].push_back(WarningNode[ID]); } for (SmallSetVector<MDNode*, 8>::iterator II = RequireNodes[ID].begin(), IE = RequireNodes[ID].end(); II != IE; ++II) DstModFlags->addOperand(*II); } // Now check that all of the requirements have been satisfied. for (SmallSetVector<MDString*, 16>::iterator I = SeenIDs.begin(), E = SeenIDs.end(); I != E; ++I) { MDString *ID = *I; SmallSetVector<MDNode*, 8> &Set = RequireNodes[ID]; for (SmallSetVector<MDNode*, 8>::iterator II = Set.begin(), IE = Set.end(); II != IE; ++II) { MDNode *Node = *II; assert(isa<MDNode>(Node->getOperand(2)) && "Module flag's third operand must be an MDNode!"); MDNode *Val = cast<MDNode>(Node->getOperand(2)); MDString *ReqID = cast<MDString>(Val->getOperand(0)); Value *ReqVal = Val->getOperand(1); bool HasValue = false; for (SmallVectorImpl<MDNode*>::iterator RI = AddedNodes[ReqID].begin(), RE = AddedNodes[ReqID].end(); RI != RE; ++RI) { MDNode *ReqNode = *RI; if (ReqNode->getOperand(2) == ReqVal) { HasValue = true; break; } } if (!HasValue) HasErr = emitError("linking module flags '" + ReqID->getString() + "': does not have the required value"); } } return HasErr; }
std::vector<SDBuildCHA::nmd_t> SDBuildCHA::extractMetadata(NamedMDNode* md) { std::set<vtbl_name_t> classes; std::vector<SDBuildCHA::nmd_t> infoVec; unsigned op = 0; do { SDBuildCHA::nmd_t info; MDString* infoMDstr = dyn_cast_or_null<MDString>(md->getOperand(op++)->getOperand(0)); assert(infoMDstr); info.className = infoMDstr->getString().str(); GlobalVariable* classVtbl = sd_mdnodeToGV(md->getOperand(op++)); if (classVtbl) { info.className = classVtbl->getName(); } unsigned numOperands = sd_getNumberFromMDTuple(md->getOperand(op++)->getOperand(0)); for (unsigned i = op; i < op + numOperands; ++i) { SDBuildCHA::nmd_sub_t subInfo; llvm::MDTuple* tup = dyn_cast<llvm::MDTuple>(md->getOperand(i)); assert(tup); assert(tup->getNumOperands() == 5); subInfo.order = sd_getNumberFromMDTuple(tup->getOperand(0)); subInfo.start = sd_getNumberFromMDTuple(tup->getOperand(1)); subInfo.end = sd_getNumberFromMDTuple(tup->getOperand(2)); subInfo.addressPoint = sd_getNumberFromMDTuple(tup->getOperand(3)); llvm::MDTuple* parentsTup = dyn_cast<llvm::MDTuple>(tup->getOperand(4)); unsigned numParents = sd_getNumberFromMDTuple(parentsTup->getOperand(0)); for (int j = 0; j < numParents; j++) { vtbl_name_t ptName = sd_getStringFromMDTuple(parentsTup->getOperand(1+j*3)); unsigned ptIdx = sd_getNumberFromMDTuple(parentsTup->getOperand(1+j*3+1)); GlobalVariable* parentVtable = sd_mdnodeToGV(parentsTup->getOperand(1+j*3+2).get()); if (parentVtable) { ptName = parentVtable->getName(); } subInfo.parents.insert(vtbl_t(ptName, ptIdx)); } bool currRangeCheck = (subInfo.start <= subInfo.addressPoint && subInfo.addressPoint <= subInfo.end); bool prevVtblCheck = (i == op || (--info.subVTables.end())->end < subInfo.start); assert(currRangeCheck && prevVtblCheck); info.subVTables.push_back(subInfo); } op += numOperands; if (classes.count(info.className) == 0) { classes.insert(info.className); infoVec.push_back(info); } } while (op < md->getNumOperands()); return infoVec; }