More information about specific metadata nodes recognized by the
optimizers and code generator is found below.
+Specialized Metadata Nodes
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Specialized metadata nodes are custom data structures in metadata (as opposed
+to generic tuples). Their fields are labelled, and can be specified in any
+order.
+
+MDLocation
+""""""""""
+
+``MDLocation`` nodes represent source debug locations. The ``scope:`` field is
+mandatory.
+
+.. code-block:: llvm
+
+ !0 = !MDLocation(line: 2900, column: 42, scope: !1, inlinedAt: !2)
+
'``tbaa``' Metadata
^^^^^^^^^^^^^^^^^^^
METADATA_NAME = 4, // STRING: [values]
METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num]
METADATA_KIND = 6, // [n x [id, name]]
- // 7 is unused.
+ METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?]
METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
return TokError("unexpected type in metadata definition");
bool IsDistinct = EatIfPresent(lltok::kw_distinct);
- if (ParseToken(lltok::exclaim, "Expected '!' here") ||
- ParseMDTuple(Init, IsDistinct))
+ if (Lex.getKind() == lltok::MetadataVar) {
+ if (ParseSpecializedMDNode(Init, IsDistinct))
+ return true;
+ } else if (ParseToken(lltok::exclaim, "Expected '!' here") ||
+ ParseMDTuple(Init, IsDistinct))
return true;
// See if this was forward referenced, if so, handle it.
/// MDNode:
/// ::= !{ ... }
/// ::= !7
+/// ::= !MDLocation(...)
bool LLParser::ParseMDNode(MDNode *&N) {
+ if (Lex.getKind() == lltok::MetadataVar)
+ return ParseSpecializedMDNode(N);
+
return ParseToken(lltok::exclaim, "expected '!' here") ||
ParseMDNodeTail(N);
}
return ParseMDNodeID(N);
}
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
+ MDUnsignedField<uint32_t> &Result) {
+ if (Result.Seen)
+ return Error(Loc,
+ "field '" + Name + "' cannot be specified more than once");
+
+ if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned())
+ return TokError("expected unsigned integer");
+ uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(Result.Max + 1ull);
+
+ if (Val64 > Result.Max)
+ return TokError("value for '" + Name + "' too large, limit is " +
+ Twine(Result.Max));
+ Result.assign(Val64);
+ Lex.Lex();
+ return false;
+}
+
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
+ if (Result.Seen)
+ return Error(Loc,
+ "field '" + Name + "' cannot be specified more than once");
+
+ Metadata *MD;
+ if (ParseMetadata(MD, nullptr))
+ return true;
+
+ Result.assign(MD);
+ return false;
+}
+
+template <class ParserTy>
+bool LLParser::ParseMDFieldsImpl(ParserTy parseField) {
+ assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
+ Lex.Lex();
+
+ if (ParseToken(lltok::lparen, "expected '(' here"))
+ return true;
+ if (EatIfPresent(lltok::rparen))
+ return false;
+
+ do {
+ if (Lex.getKind() != lltok::LabelStr)
+ return TokError("expected field label here");
+
+ if (parseField())
+ return true;
+ } while (EatIfPresent(lltok::comma));
+
+ return ParseToken(lltok::rparen, "expected ')' here");
+}
+
+bool LLParser::ParseSpecializedMDNode(MDNode *&N, bool IsDistinct) {
+ assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
+#define DISPATCH_TO_PARSER(CLASS) \
+ if (Lex.getStrVal() == #CLASS) \
+ return Parse##CLASS(N, IsDistinct);
+
+ DISPATCH_TO_PARSER(MDLocation);
+#undef DISPATCH_TO_PARSER
+
+ return TokError("expected metadata type");
+}
+
+#define PARSE_MD_FIELD(NAME) \
+ do { \
+ if (Lex.getStrVal() == #NAME) { \
+ LocTy Loc = Lex.getLoc(); \
+ Lex.Lex(); \
+ if (ParseMDField(Loc, #NAME, NAME)) \
+ return true; \
+ return false; \
+ } \
+ } while (0)
+
+/// ParseMDLocationFields:
+/// ::= !MDLocation(line: 43, column: 8, scope: !5, inlinedAt: !6)
+bool LLParser::ParseMDLocation(MDNode *&Result, bool IsDistinct) {
+ MDUnsignedField<uint32_t> line(0, ~0u >> 8);
+ MDUnsignedField<uint32_t> column(0, ~0u >> 24);
+ MDField scope;
+ MDField inlinedAt;
+ if (ParseMDFieldsImpl([&]() -> bool {
+ PARSE_MD_FIELD(line);
+ PARSE_MD_FIELD(column);
+ PARSE_MD_FIELD(scope);
+ PARSE_MD_FIELD(inlinedAt);
+ return TokError(Twine("invalid field '") + Lex.getStrVal() + "'");
+ }))
+ return true;
+
+ if (!scope.Seen)
+ return TokError("missing required field 'scope'");
+
+ auto get = (IsDistinct ? MDLocation::getDistinct : MDLocation::get);
+ Result = get(Context, line.Val, column.Val, scope.Val, inlinedAt.Val);
+ return false;
+}
+#undef PARSE_MD_FIELD
+
/// ParseMetadataAsValue
/// ::= metadata i32 %local
/// ::= metadata i32 @global
/// ::= !42
/// ::= !{...}
/// ::= !"string"
+/// ::= !MDLocation(...)
bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
+ if (Lex.getKind() == lltok::MetadataVar) {
+ MDNode *N;
+ if (ParseSpecializedMDNode(N))
+ return true;
+ MD = N;
+ return false;
+ }
+
// ValueAsMetadata:
// <type> <value>
if (Lex.getKind() != lltok::exclaim)
}
};
+ /// Structure to represent an optional metadata field.
+ template <class FieldTy> struct MDFieldImpl {
+ typedef MDFieldImpl ImplTy;
+ FieldTy Val;
+ bool Seen;
+
+ void assign(FieldTy Val) {
+ Seen = true;
+ this->Val = Val;
+ }
+
+ explicit MDFieldImpl(FieldTy Default) : Val(Default), Seen(false) {}
+ };
+ template <class NumTy> struct MDUnsignedField : public MDFieldImpl<NumTy> {
+ typedef typename MDUnsignedField::ImplTy ImplTy;
+ NumTy Max;
+
+ MDUnsignedField(NumTy Default = 0,
+ NumTy Max = std::numeric_limits<NumTy>::max())
+ : ImplTy(Default), Max(Max) {}
+ };
+ struct MDField : public MDFieldImpl<Metadata *> {
+ MDField() : ImplTy(nullptr) {}
+ };
+
class LLParser {
public:
typedef LLLexer::LocTy LocTy;
bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs);
bool ParseInstructionMetadata(Instruction *Inst, PerFunctionState *PFS);
+ bool ParseMDField(LocTy Loc, StringRef Name,
+ MDUnsignedField<uint32_t> &Result);
+ bool ParseMDField(LocTy Loc, StringRef Name, MDField &Result);
+ template <class ParserTy> bool ParseMDFieldsImpl(ParserTy parseField);
+ bool ParseSpecializedMDNode(MDNode *&N, bool IsDistinct = false);
+ bool ParseMDLocation(MDNode *&Result, bool IsDistinct);
+
// Function Parsing.
struct ArgInfo {
LocTy Loc;
NextMDValueNo++);
break;
}
+ case bitc::METADATA_LOCATION: {
+ if (Record.size() != 5)
+ return Error("Invalid record");
+
+ auto get = Record[0] ? MDLocation::getDistinct : MDLocation::get;
+ unsigned Line = Record[1];
+ unsigned Column = Record[2];
+ MDNode *Scope = cast<MDNode>(MDValueList.getValueFwdRef(Record[3]));
+ Metadata *InlinedAt =
+ Record[4] ? MDValueList.getValueFwdRef(Record[4] - 1) : nullptr;
+ MDValueList.AssignValue(get(Context, Line, Column, Scope, InlinedAt),
+ NextMDValueNo++);
+ break;
+ }
case bitc::METADATA_STRING: {
std::string String(Record.begin(), Record.end());
llvm::UpgradeMDStringConstant(String);
Record.clear();
}
+static void WriteMDLocation(const MDLocation *N, const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &Record,
+ unsigned Abbrev) {
+ Record.push_back(N->isDistinct());
+ Record.push_back(N->getLine());
+ Record.push_back(N->getColumn());
+ Record.push_back(VE.getMetadataID(N->getScope()));
+
+ // Always emit the inlined-at location, even though it's optional.
+ if (Metadata *InlinedAt = N->getInlinedAt())
+ Record.push_back(VE.getMetadataID(InlinedAt) + 1);
+ else
+ Record.push_back(0);
+
+ Stream.EmitRecord(bitc::METADATA_LOCATION, Record, Abbrev);
+ Record.clear();
+}
+
static void WriteModuleMetadata(const Module *M,
const ValueEnumerator &VE,
BitstreamWriter &Stream) {
MDSAbbrev = Stream.EmitAbbrev(Abbv);
}
+ unsigned LocAbbrev = 0;
+ if (VE.hasMDLocation()) {
+ // Abbrev for METADATA_LOCATION.
+ //
+ // Assume the column is usually under 128, and always output the inlined-at
+ // location (it's never more expensive than building an array size 1).
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_LOCATION));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
+ LocAbbrev = Stream.EmitAbbrev(Abbv);
+ }
+
unsigned NameAbbrev = 0;
if (!M->named_metadata_empty()) {
// Abbrev for METADATA_NAME.
SmallVector<uint64_t, 64> Record;
for (const Metadata *MD : MDs) {
+ if (const MDLocation *Loc = dyn_cast<MDLocation>(MD)) {
+ WriteMDLocation(Loc, VE, Stream, Record, LocAbbrev);
+ continue;
+ }
if (const MDNode *N = dyn_cast<MDNode>(MD)) {
WriteMDNode(N, VE, Stream, Record);
continue;
return V.first->getType()->isIntOrIntVectorTy();
}
-ValueEnumerator::ValueEnumerator(const Module &M) : HasMDString(false) {
+ValueEnumerator::ValueEnumerator(const Module &M)
+ : HasMDString(false), HasMDLocation(false) {
if (shouldPreserveBitcodeUseListOrder())
UseListOrders = predictUseListOrder(M);
EnumerateValue(C->getValue());
HasMDString |= isa<MDString>(MD);
+ HasMDLocation |= isa<MDLocation>(MD);
// Replace the dummy ID inserted above with the correct one. MDValueMap may
// have changed by inserting operands, so we need a fresh lookup here.
typedef DenseMap<const Metadata *, unsigned> MetadataMapType;
MetadataMapType MDValueMap;
bool HasMDString;
+ bool HasMDLocation;
typedef DenseMap<AttributeSet, unsigned> AttributeGroupMapType;
AttributeGroupMapType AttributeGroupMap;
unsigned getMetadataID(const Metadata *V) const;
bool hasMDString() const { return HasMDString; }
+ bool hasMDLocation() const { return HasMDLocation; }
unsigned getTypeID(Type *T) const {
TypeMapType::const_iterator I = TypeMap.find(T);
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:18: error: invalid field 'bad'
+!0 = !MDLocation(bad: 0)
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+!0 = !{}
+
+; CHECK: <stdin>:[[@LINE+1]]:38: error: field 'line' cannot be specified more than once
+!1 = !MDLocation(line: 3, scope: !0, line: 3)
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+!0 = !{}
+
+; CHECK-NOT: error
+!1 = !MDLocation(column: 255, scope: !0)
+
+; CHECK: <stdin>:[[@LINE+1]]:26: error: value for 'column' too large, limit is 255
+!2 = !MDLocation(column: 256, scope: !0)
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+!0 = !{}
+
+; CHECK-NOT: error
+!1 = !MDLocation(line: 16777215, scope: !0)
+
+; CHECK: <stdin>:[[@LINE+1]]:24: error: value for 'line' too large, limit is 16777215
+!2 = !MDLocation(line: 16777216, scope: !0)
--- /dev/null
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:6: error: expected metadata type
+!0 = !Invalid(field: 0)
--- /dev/null
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+; CHECK: !named = !{!0, !1, !1, !2, !2, !3, !3}
+!named = !{!0, !1, !2, !3, !4, !5, !6}
+
+; CHECK: !0 = !{}
+!0 = !{}
+
+; CHECK-NEXT: !1 = !MDLocation(line: 3, column: 7, scope: !0)
+!1 = !MDLocation(line: 3, column: 7, scope: !0)
+!2 = !MDLocation(scope: !0, column: 7, line: 3)
+
+; CHECK-NEXT: !2 = !MDLocation(line: 3, column: 7, scope: !0, inlinedAt: !1)
+!3 = !MDLocation(scope: !0, inlinedAt: !1, column: 7, line: 3)
+!4 = !MDLocation(column: 7, line: 3, scope: !0, inlinedAt: !1)
+
+; CHECK-NEXT: !3 = !MDLocation(scope: !0)
+!5 = !MDLocation(scope: !0)
+!6 = !MDLocation(scope: !0, column: 0, line: 0)
syn keyword llvmError getresult begin end
" Misc syntax.
-syn match llvmNoName /[%@]\d\+\>/
+syn match llvmNoName /[%@!]\d\+\>/
syn match llvmNumber /-\?\<\d\+\>/
syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/
syn match llvmFloat /\<0x\x\+\>/
syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/
syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/
+" Named metadata and specialized metadata keywords.
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/
+syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/
+syn match llvmType /!\zs\a\+\ze\s*(/
+
" Syntax-highlight dejagnu test commands.
syn match llvmSpecialComment /;\s*RUN:.*$/
syn match llvmSpecialComment /;\s*PR\d*\s*$/