METADATA_DERIVED_TYPE = 17, // [distinct, ...]
METADATA_COMPOSITE_TYPE= 18, // [distinct, ...]
METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types]
- METADATA_COMPILE_UNIT = 20 // [distinct, ...]
+ METADATA_COMPILE_UNIT = 20, // [distinct, ...]
+ METADATA_SUBPROGRAM = 21 // [distinct, ...]
};
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
StringRef getDisplayName() const { return getStringOperand(3); }
StringRef getLinkageName() const { return getStringOperand(4); }
+ MDString *getRawName() const { return getOperandAs<MDString>(2); }
+ MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); }
+
Metadata *getType() const { return getOperand(5); }
Metadata *getContainingType() const { return getOperand(6); }
struct MDField : public MDFieldImpl<Metadata *> {
MDField() : ImplTy(nullptr) {}
};
+struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> {
+ MDConstant() : ImplTy(nullptr) {}
+};
struct MDStringField : public MDFieldImpl<std::string> {
MDStringField() : ImplTy(std::string()) {}
};
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
+ if (Lex.getKind() == lltok::kw_null) {
+ Lex.Lex();
+ Result.assign(nullptr);
+ return false;
+ }
+
Metadata *MD;
if (ParseMetadata(MD, nullptr))
return true;
return false;
}
+template <>
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDConstant &Result) {
+ Metadata *MD;
+ if (ParseValueAsMetadata(MD, "expected constant", nullptr))
+ return true;
+
+ Result.assign(cast<ConstantAsMetadata>(MD));
+ return false;
+}
+
template <>
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
std::string S;
return false;
}
+/// ParseMDSubprogram:
+/// ::= !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoo",
+/// file: !1, line: 7, type: !2, isLocal: false,
+/// isDefinition: true, scopeLine: 8, containingType: !3,
+/// virtuality: 2, virtualIndex: 10, flags: 11,
+/// isOptimized: false, function: void ()* @_Z3foov,
+/// templateParams: !4, declaration: !5, variables: !6)
bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) {
- return TokError("unimplemented parser");
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
+ OPTIONAL(scope, MDField, ); \
+ REQUIRED(name, MDStringField, ); \
+ OPTIONAL(linkageName, MDStringField, ); \
+ OPTIONAL(file, MDField, ); \
+ OPTIONAL(line, LineField, ); \
+ OPTIONAL(type, MDField, ); \
+ OPTIONAL(isLocal, MDBoolField, ); \
+ OPTIONAL(isDefinition, MDBoolField, (true)); \
+ OPTIONAL(scopeLine, LineField, ); \
+ OPTIONAL(containingType, MDField, ); \
+ OPTIONAL(virtuality, MDUnsignedField, (0, dwarf::DW_VIRTUALITY_max)); \
+ OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \
+ OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX)); \
+ OPTIONAL(isOptimized, MDBoolField, ); \
+ OPTIONAL(function, MDConstant, ); \
+ OPTIONAL(templateParams, MDField, ); \
+ OPTIONAL(declaration, MDField, ); \
+ OPTIONAL(variables, MDField, );
+ PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+ Result = GET_OR_DISTINCT(
+ MDSubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val,
+ line.Val, type.Val, isLocal.Val, isDefinition.Val,
+ scopeLine.Val, containingType.Val, virtuality.Val,
+ virtualIndex.Val, flags.Val, isOptimized.Val, function.Val,
+ templateParams.Val, declaration.Val, variables.Val));
+ return false;
}
+
bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) {
return TokError("unimplemented parser");
}
/// ::= i32 %local
/// ::= i32 @global
/// ::= i32 7
-bool LLParser::ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS) {
+bool LLParser::ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
+ PerFunctionState *PFS) {
Type *Ty;
LocTy Loc;
- if (ParseType(Ty, "expected metadata operand", Loc))
+ if (ParseType(Ty, TypeMsg, Loc))
return true;
if (Ty->isMetadataTy())
return Error(Loc, "invalid metadata-value-metadata roundtrip");
// ValueAsMetadata:
// <type> <value>
if (Lex.getKind() != lltok::exclaim)
- return ParseValueAsMetadata(MD, PFS);
+ return ParseValueAsMetadata(MD, "expected metadata operand", PFS);
// '!'.
assert(Lex.getKind() == lltok::exclaim && "Expected '!' here");
bool ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts);
bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
bool ParseMetadataAsValue(Value *&V, PerFunctionState &PFS);
- bool ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS);
+ bool ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
+ PerFunctionState *PFS);
bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS);
bool ParseMDTuple(MDNode *&MD, bool IsDistinct = false);
bool ParseMDNode(MDNode *&MD);
NextMDValueNo++);
break;
}
+ case bitc::METADATA_SUBPROGRAM: {
+ if (Record.size() != 19)
+ return Error("Invalid record");
+
+ MDValueList.AssignValue(
+ GET_OR_DISTINCT(
+ MDSubprogram, Record[0],
+ (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
+ getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
+ getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
+ getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
+ Record[14], getMDOrNull(Record[15]), getMDOrNull(Record[16]),
+ getMDOrNull(Record[17]), getMDOrNull(Record[18]))),
+ NextMDValueNo++);
+ break;
+ }
case bitc::METADATA_STRING: {
std::string String(Record.begin(), Record.end());
llvm::UpgradeMDStringConstant(String);
Record.clear();
}
-static void WriteMDSubprogram(const MDSubprogram *, const ValueEnumerator &,
- BitstreamWriter &, SmallVectorImpl<uint64_t> &,
- unsigned) {
- llvm_unreachable("write not implemented");
+static void WriteMDSubprogram(const MDSubprogram *N,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &Record,
+ unsigned Abbrev) {
+ Record.push_back(N->isDistinct());
+ Record.push_back(VE.getMetadataOrNullID(N->getScope()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
+ Record.push_back(VE.getMetadataOrNullID(N->getRawLinkageName()));
+ Record.push_back(VE.getMetadataOrNullID(N->getFile()));
+ Record.push_back(N->getLine());
+ Record.push_back(VE.getMetadataOrNullID(N->getType()));
+ Record.push_back(N->isLocalToUnit());
+ Record.push_back(N->isDefinition());
+ Record.push_back(N->getScopeLine());
+ Record.push_back(VE.getMetadataOrNullID(N->getContainingType()));
+ Record.push_back(N->getVirtuality());
+ Record.push_back(N->getVirtualIndex());
+ Record.push_back(N->getFlags());
+ Record.push_back(N->isOptimized());
+ Record.push_back(VE.getMetadataOrNullID(N->getFunction()));
+ Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams()));
+ Record.push_back(VE.getMetadataOrNullID(N->getDeclaration()));
+ Record.push_back(VE.getMetadataOrNullID(N->getVariables()));
+
+ Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev);
+ Record.clear();
}
+
static void WriteMDLexicalBlock(const MDLexicalBlock *, const ValueEnumerator &,
BitstreamWriter &, SmallVectorImpl<uint64_t> &,
unsigned) {
Out << ")";
}
-static void writeMDSubprogram(raw_ostream &, const MDSubprogram *,
- TypePrinting *, SlotTracker *, const Module *) {
- llvm_unreachable("write not implemented");
+static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDSubprogram(";
+ FieldSeparator FS;
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ Out << FS << "name: \"" << N->getName() << "\"";
+ if (!N->getLinkageName().empty())
+ Out << FS << "linkageName: \"" << N->getLinkageName() << "\"";
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine,
+ Context);
+ }
+ Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false");
+ Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false");
+ if (N->getScopeLine())
+ Out << FS << "scopeLine: " << N->getScopeLine();
+ if (N->getContainingType()) {
+ Out << FS << "containingType: ";
+ writeMetadataAsOperand(Out, N->getContainingType(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getVirtuality())
+ Out << FS << "virtuality: " << N->getVirtuality();
+ if (N->getVirtualIndex())
+ Out << FS << "virtualIndex: " << N->getVirtualIndex();
+ if (N->getFlags())
+ Out << FS << "flags: " << N->getFlags();
+ Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false");
+ if (N->getFunction()) {
+ Out << FS << "function: ";
+ writeMetadataAsOperand(Out, N->getFunction(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getTemplateParams()) {
+ Out << FS << "templateParams: ";
+ writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getDeclaration()) {
+ Out << FS << "declaration: ";
+ writeMetadataAsOperand(Out, N->getDeclaration(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getVariables()) {
+ Out << FS << "variables: ";
+ writeMetadataAsOperand(Out, N->getVariables(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
}
+
static void writeMDLexicalBlock(raw_ostream &, const MDLexicalBlock *,
TypePrinting *, SlotTracker *, const Module *) {
llvm_unreachable("write not implemented");
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:38: error: missing required field 'name'
+!0 = !MDSubprogram(linkageName: "foo")
--- /dev/null
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+declare void @_Z3foov()
+
+; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
+
+!0 = distinct !{}
+!1 = !{!"path/to/file", !"/path/to/dir"}
+!2 = !MDFile(filename: "path/to/file", directory: "/path/to/dir")
+!3 = distinct !{}
+!4 = distinct !{}
+!5 = distinct !{}
+!6 = distinct !{}
+!7 = distinct !{}
+
+; CHECK: !8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov", file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, scopeLine: 8, containingType: !4, virtuality: 2, virtualIndex: 10, flags: 11, isOptimized: true, function: void ()* @_Z3foov, templateParams: !5, declaration: !6, variables: !7)
+!8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov",
+ file: !2, line: 7, type: !3, isLocal: true,
+ isDefinition: false, scopeLine: 8, containingType: !4,
+ virtuality: 2, virtualIndex: 10, flags: 11,
+ isOptimized: true, function: void ()* @_Z3foov,
+ templateParams: !5, declaration: !6, variables: !7)
+
+; CHECK: !9 = !MDSubprogram(scope: null, name: "bar", isLocal: false, isDefinition: true, isOptimized: false)
+!9 = !MDSubprogram(name: "bar")
+