[IR/AsmWriter] Output escape sequences if the first character isdigit()
authorFilipe Cabecinhas <me@filcab.net>
Tue, 2 Jun 2015 21:25:08 +0000 (21:25 +0000)
committerFilipe Cabecinhas <me@filcab.net>
Tue, 2 Jun 2015 21:25:08 +0000 (21:25 +0000)
If the first character in a metadata attachment's name is a digit, it has
to be output using an escape sequence, otherwise it's not valid text IR.

Removed an over-zealous assert from LLVMContext which didn't allow this.
The rule should only apply to text IR. Actual names can have any sequence
of non-NUL bytes.

Also added some documentation on accepted names.

Bug found with AFL fuzz.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238867 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.rst
lib/IR/AsmWriter.cpp
lib/IR/LLVMContext.cpp
test/Assembler/metadata.ll

index 397d5fe3756734dfddf4f49209952b3f757878f4..0996820f724f8652b79c8c990014288085b3e5ff 100644 (file)
@@ -834,6 +834,11 @@ Named metadata is a collection of metadata. :ref:`Metadata
 nodes <metadata>` (but not metadata strings) are the only valid
 operands for a named metadata.
 
+#. Named metadata are represented as a string of characters with the
+   metadata prefix. The rules for metadata names are the same as for
+   identifiers, but quoted names are not allowed. ``"\xx"`` type escapes
+   are still valid, which allows any character to be part of a name.
+
 Syntax::
 
     ; Some unnamed metadata nodes, which are referenced by the named metadata.
index 86bcd658185987cffb79e32d22258fea04fbe008..715aad8b03afd82a2e76d1da13c2e522293cb534 100644 (file)
@@ -2215,9 +2215,8 @@ void AssemblyWriter::printModule(const Module *M) {
   }
 }
 
-void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
-  Out << '!';
-  StringRef Name = NMD->getName();
+static void printMetadataIdentifier(StringRef Name,
+                                    formatted_raw_ostream &Out) {
   if (Name.empty()) {
     Out << "<empty name> ";
   } else {
@@ -2235,6 +2234,11 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
         Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
     }
   }
+}
+
+void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
+  Out << '!';
+  printMetadataIdentifier(NMD->getName(), Out);
   Out << " = !{";
   for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
     if (i)
@@ -3006,9 +3010,10 @@ void AssemblyWriter::printMetadataAttachments(
   for (const auto &I : MDs) {
     unsigned Kind = I.first;
     Out << Separator;
-    if (Kind < MDNames.size())
-      Out << "!" << MDNames[Kind];
-    else
+    if (Kind < MDNames.size()) {
+      Out << "!";
+      printMetadataIdentifier(MDNames[Kind], Out);
+    } else
       Out << "!<unknown kind #" << Kind << ">";
     Out << ' ';
     WriteAsOperandInternal(Out, I.second, &TypePrinter, &Machine, TheModule);
index e8bf442b3e1db59ced07f9dac8bc2e87b4caab0c..7bcd829f9f5e0cd0897d6b88556ec793df8dc15f 100644 (file)
@@ -242,9 +242,6 @@ void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
 
 /// Return a unique non-zero ID for the specified metadata kind.
 unsigned LLVMContext::getMDKindID(StringRef Name) const {
-  assert(!std::isdigit(Name.front()) &&
-         "Named metadata may not start with a digit");
-
   // If this is new, assign it its ID.
   return pImpl->CustomMDKindNames.insert(
                                      std::make_pair(
index 8d5e91fb332fa18a136b7e6c99edbb83654dbdfa..052ac1b5097e04a96b7f642b493a5f83971e7666 100644 (file)
@@ -22,6 +22,13 @@ define void @test3() !bar !3 {
   unreachable, !bar !4
 }
 
+; CHECK-LABEL: define void @test_attachment_name() {
+; CHECK:   unreachable, !\342abc !4
+define void @test_attachment_name() {
+  ;; Escape the first character when printing text IR, since it's a digit
+  unreachable, !\34\32abc !4
+}
+
 !0 = !DILocation(line: 662302, column: 26, scope: !1)
 !1 = !DISubprogram(name: "foo")
 !2 = distinct !{}