if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return GV->getParent();
+
+ if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) {
+ for (const User *U : MAV->users())
+ if (isa<Instruction>(U))
+ if (const Module *M = getModuleFromVal(U))
+ return M;
+ return nullptr;
+ }
+
return nullptr;
}
/// TheFunction - The function for which we are holding slot numbers.
const Function* TheFunction;
bool FunctionProcessed;
+ bool ShouldInitializeAllMetadata;
/// mMap - The slot map for the module level data.
ValueMap mMap;
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext;
public:
- /// Construct from a module
- explicit SlotTracker(const Module *M);
+ /// Construct from a module.
+ ///
+ /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
+ /// functions, giving correct numbering for metadata referenced only from
+ /// within a function (even if no functions have been initialized).
+ explicit SlotTracker(const Module *M,
+ bool ShouldInitializeAllMetadata = false);
/// Construct from a function, starting out in incorp state.
- explicit SlotTracker(const Function *F);
+ ///
+ /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
+ /// functions, giving correct numbering for metadata referenced only from
+ /// within a function (even if no functions have been initialized).
+ explicit SlotTracker(const Function *F,
+ bool ShouldInitializeAllMetadata = false);
/// Return the slot number of the specified value in it's type
/// plane. If something is not in the SlotTracker, return -1.
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();
+ /// Add all of the metadata from a function.
+ void processFunctionMetadata(const Function &F);
+
/// Add all of the metadata from an instruction.
void processInstructionMetadata(const Instruction &I);
// Module level constructor. Causes the contents of the Module (sans functions)
// to be added to the slot table.
-SlotTracker::SlotTracker(const Module *M)
- : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), mNext(0),
+SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
+ : TheModule(M), TheFunction(nullptr), FunctionProcessed(false),
+ ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0),
fNext(0), mdnNext(0), asNext(0) {}
// Function level constructor. Causes the contents of the Module and the one
// function provided to be added to the slot table.
-SlotTracker::SlotTracker(const Function *F)
+SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
: TheModule(F ? F->getParent() : nullptr), TheFunction(F),
- FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {}
+ FunctionProcessed(false),
+ ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0),
+ fNext(0), mdnNext(0), asNext(0) {}
inline void SlotTracker::initialize() {
if (TheModule) {
// Add all the unnamed functions to the table.
CreateModuleSlot(I);
+ if (ShouldInitializeAllMetadata)
+ processFunctionMetadata(*I);
+
// Add all the function attributes to the table.
// FIXME: Add attributes of other objects?
AttributeSet FnAttrs = I->getAttributes().getFnAttributes();
ST_DEBUG("end processFunction!\n");
}
+void SlotTracker::processFunctionMetadata(const Function &F) {
+ for (auto &BB : F)
+ for (auto &I : BB)
+ processInstructionMetadata(I);
+}
+
void SlotTracker::processInstructionMetadata(const Instruction &I) {
// Process metadata used directly by intrinsics.
if (const CallInst *CI = dyn_cast<CallInst>(&I))
}
}
+static bool isReferencingMDNode(const Instruction &I) {
+ if (const auto *CI = dyn_cast<CallInst>(&I))
+ if (Function *F = CI->getCalledFunction())
+ if (F->isIntrinsic())
+ for (auto &Op : I.operands())
+ if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
+ if (isa<MDNode>(V->getMetadata()))
+ return true;
+ return false;
+}
+
void Value::print(raw_ostream &ROS) const {
formatted_raw_ostream OS(ROS);
if (const Instruction *I = dyn_cast<Instruction>(this)) {
const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr;
- SlotTracker SlotTable(F);
+ SlotTracker SlotTable(
+ F,
+ /* ShouldInitializeAllMetadata */ isReferencingMDNode(*I));
AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr);
W.printInstruction(*I);
} else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) {
AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr);
W.printBasicBlock(BB);
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
- SlotTracker SlotTable(GV->getParent());
+ SlotTracker SlotTable(GV->getParent(),
+ /* ShouldInitializeAllMetadata */ isa<Function>(GV));
AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr);
if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
W.printGlobal(V);
else
W.printAlias(cast<GlobalAlias>(GV));
} else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
- V->getMetadata()->print(ROS);
+ V->getMetadata()->print(ROS, getModuleFromVal(V));
} else if (const Constant *C = dyn_cast<Constant>(this)) {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
// Fast path: Don't construct and populate a TypePrinting object if we
// won't be needing any types printed.
- if (!PrintType && ((!isa<Constant>(this) && !isa<MetadataAsValue>(this)) ||
- hasName() || isa<GlobalValue>(this))) {
+ bool IsMetadata = isa<MetadataAsValue>(this);
+ if (!PrintType && ((!isa<Constant>(this) && !IsMetadata) || hasName() ||
+ isa<GlobalValue>(this))) {
WriteAsOperandInternal(O, this, nullptr, nullptr, M);
return;
}
O << ' ';
}
- WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M);
+ SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata);
+ WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M);
}
-void Metadata::print(raw_ostream &ROS) const {
+static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
+ const Module *M, bool OnlyAsOperand) {
formatted_raw_ostream OS(ROS);
- if (auto *N = dyn_cast<MDNode>(this)) {
- SlotTracker SlotTable(static_cast<Function *>(nullptr));
- AssemblyWriter W(OS, SlotTable, nullptr, nullptr);
- W.printMDNodeBody(N);
+ auto *N = dyn_cast<MDNode>(&MD);
+ TypePrinting TypePrinter;
+ SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ N);
+ if (M)
+ TypePrinter.incorporateTypes(*M);
+
+ WriteAsOperandInternal(OS, &MD, &TypePrinter, &Machine, M,
+ /* FromValue */ true);
+ if (OnlyAsOperand || !N)
return;
- }
- printAsOperand(OS);
+
+ OS << " = ";
+ WriteMDNodeBodyInternal(OS, N, &TypePrinter, &Machine, M);
}
-void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType,
- const Module *M) const {
- formatted_raw_ostream OS(ROS);
+void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
+ printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ true);
+}
- std::unique_ptr<TypePrinting> TypePrinter;
- if (PrintType) {
- TypePrinter.reset(new TypePrinting);
- if (M)
- TypePrinter->incorporateTypes(*M);
- }
- WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M,
- /* FromValue */ true);
+void Metadata::print(raw_ostream &OS, const Module *M) const {
+ printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ false);
}
// Value::dump - allow easy printing of Values from the debugger.
void NamedMDNode::dump() const { print(dbgs()); }
LLVM_DUMP_METHOD
-void Metadata::dump() const {
- print(dbgs());
+void Metadata::dump(const Module *M) const {
+ print(dbgs(), M);
dbgs() << '\n';
}
std::string Expected;
{
raw_string_ostream OS(Expected);
- OS << "!{";
+ OS << "<" << (void *)N << "> = !{";
C->printAsOperand(OS);
OS << ", ";
S->printAsOperand(OS);
EXPECT_EQ(Expected, Actual);
}
+#define EXPECT_PRINTER_EQ(EXPECTED, PRINT) \
+ do { \
+ std::string Actual_; \
+ raw_string_ostream OS(Actual_); \
+ PRINT; \
+ OS.flush(); \
+ std::string Expected_(EXPECTED); \
+ EXPECT_EQ(Expected_, Actual_); \
+ } while (false)
+
+TEST_F(MDNodeTest, PrintFromModule) {
+ Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7);
+ MDString *S = MDString::get(Context, "foo");
+ MDNode *N0 = getNode();
+ MDNode *N1 = getNode(N0);
+ MDNode *N2 = getNode(N0, N1);
+
+ Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};
+ MDNode *N = MDNode::get(Context, Args);
+ Module M("test", Context);
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");
+ NMD->addOperand(N);
+
+ std::string Expected;
+ {
+ raw_string_ostream OS(Expected);
+ OS << "!0 = !{";
+ C->printAsOperand(OS);
+ OS << ", ";
+ S->printAsOperand(OS);
+ OS << ", null, !1, !2, !3}";
+ }
+
+ EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));
+}
+
+TEST_F(MDNodeTest, PrintFromFunction) {
+ Module M("test", Context);
+ auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);
+ auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);
+ auto *BB0 = BasicBlock::Create(Context, "entry", F0);
+ auto *BB1 = BasicBlock::Create(Context, "entry", F1);
+ auto *R0 = ReturnInst::Create(Context, BB0);
+ auto *R1 = ReturnInst::Create(Context, BB1);
+ auto *N0 = MDNode::getDistinct(Context, None);
+ auto *N1 = MDNode::getDistinct(Context, None);
+ R0->setMetadata("md", N0);
+ R1->setMetadata("md", N1);
+
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, &M));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, &M));
+}
+
+TEST_F(MDNodeTest, PrintFromMetadataAsValue) {
+ Module M("test", Context);
+
+ auto *Intrinsic =
+ Function::Create(FunctionType::get(Type::getVoidTy(Context),
+ Type::getMetadataTy(Context), false),
+ GlobalValue::ExternalLinkage, "llvm.intrinsic", &M);
+
+ auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);
+ auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);
+ auto *BB0 = BasicBlock::Create(Context, "entry", F0);
+ auto *BB1 = BasicBlock::Create(Context, "entry", F1);
+ auto *N0 = MDNode::getDistinct(Context, None);
+ auto *N1 = MDNode::getDistinct(Context, None);
+ auto *MAV0 = MetadataAsValue::get(Context, N0);
+ auto *MAV1 = MetadataAsValue::get(Context, N1);
+ CallInst::Create(Intrinsic, MAV0, "", BB0);
+ CallInst::Create(Intrinsic, MAV1, "", BB1);
+
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS));
+ EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false));
+ EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false));
+ EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true));
+ EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true));
+}
+#undef EXPECT_PRINTER_EQ
+
TEST_F(MDNodeTest, NullOperand) {
// metadata !{}
MDNode *Empty = MDNode::get(Context, None);