[llvm] r342161 - Common infrastructure for reading a profile remapping file and building
Richard Smith via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 13 11:51:44 PDT 2018
Author: rsmith
Date: Thu Sep 13 11:51:44 2018
New Revision: 342161
URL: http://llvm.org/viewvc/llvm-project?rev=342161&view=rev
Log:
Common infrastructure for reading a profile remapping file and building
a mangling remapper from it.
Differential Revision: https://reviews.llvm.org/D51246
Added:
llvm/trunk/include/llvm/Support/SymbolRemappingReader.h
llvm/trunk/lib/Support/SymbolRemappingReader.cpp
llvm/trunk/unittests/Support/SymbolRemappingReaderTest.cpp
Modified:
llvm/trunk/lib/Support/CMakeLists.txt
llvm/trunk/unittests/Support/CMakeLists.txt
Added: llvm/trunk/include/llvm/Support/SymbolRemappingReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/SymbolRemappingReader.h?rev=342161&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/SymbolRemappingReader.h (added)
+++ llvm/trunk/include/llvm/Support/SymbolRemappingReader.h Thu Sep 13 11:51:44 2018
@@ -0,0 +1,133 @@
+//===- SymbolRemappingReader.h - Read symbol remapping file -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains definitions needed for reading and applying symbol
+// remapping files.
+//
+// Support is provided only for the Itanium C++ name mangling scheme for now.
+//
+// NOTE: If you are making changes to this file format, please remember
+// to document them in the Clang documentation at
+// tools/clang/docs/UsersManual.rst.
+//
+// File format
+// -----------
+//
+// The symbol remappings are written as an ASCII text file. Blank lines and
+// lines starting with a # are ignored. All other lines specify a kind of
+// mangled name fragment, along with two fragments of that kind that should
+// be treated as equivalent, separated by spaces.
+//
+// See http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling for a
+// description of the Itanium name mangling scheme.
+//
+// The accepted fragment kinds are:
+//
+// * name A <name>, such as 6foobar or St3__1
+// * type A <type>, such as Ss or N4llvm9StringRefE
+// * encoding An <encoding> (a complete mangling without the leading _Z)
+//
+// For example:
+//
+// # Ignore int / long differences to treat symbols from 32-bit and 64-bit
+// # builds with differing size_t / ptrdiff_t / intptr_t as equivalent.
+// type i l
+// type j m
+//
+// # Ignore differences between libc++ and libstdc++, and between libstdc++'s
+// # C++98 and C++11 ABIs.
+// name 3std St3__1
+// name 3std St7__cxx11
+//
+// # Remap a function overload to a specialization of a template (including
+// # any local symbols declared within it).
+// encoding N2NS1fEi N2NS1fIiEEvT_
+//
+// # Substitutions must be remapped separately from namespace 'std' for now.
+// name Sa NSt3__19allocatorE
+// name Sb NSt3__112basic_stringE
+// type Ss NSt3__112basic_stringIcSt11char_traitsIcESaE
+// # ...
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SYMBOLREMAPPINGREADER_H
+#define LLVM_SUPPORT_SYMBOLREMAPPINGREADER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ItaniumManglingCanonicalizer.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+
+class SymbolRemappingParseError : public ErrorInfo<SymbolRemappingParseError> {
+public:
+ SymbolRemappingParseError(StringRef File, int64_t Line, Twine Message)
+ : File(File), Line(Line), Message(Message.str()) {}
+
+ void log(llvm::raw_ostream &OS) const override {
+ OS << File << ':' << Line << ": " << Message;
+ }
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+
+ StringRef getFileName() const { return File; }
+ int64_t getLineNum() const { return Line; }
+ StringRef getMessage() const { return Message; }
+
+ static char ID;
+
+private:
+ std::string File;
+ int64_t Line;
+ std::string Message;
+};
+
+/// Reader for symbol remapping files.
+///
+/// Remaps the symbol names in profile data to match those in the program
+/// according to a set of rules specified in a given file.
+class SymbolRemappingReader {
+public:
+ /// Read remappings from the given buffer, which must live as long as
+ /// the remapper.
+ Error read(MemoryBuffer &B);
+
+ /// A Key represents an equivalence class of symbol names.
+ using Key = uintptr_t;
+
+ /// Construct a key for the given symbol, or return an existing one if an
+ /// equivalent name has already been inserted. The symbol name must live
+ /// as long as the remapper.
+ ///
+ /// The result will be Key() if the name cannot be remapped (typically
+ /// because it is not a valid mangled name).
+ Key insert(StringRef FunctionName) {
+ return Canonicalizer.canonicalize(FunctionName);
+ }
+
+ /// Map the given symbol name into the key for the corresponding equivalence
+ /// class.
+ ///
+ /// The result will typically be Key() if no equivalent symbol has been
+ /// inserted, but this is not guaranteed: a Key different from all keys ever
+ /// returned by \c insert may be returned instead.
+ Key lookup(StringRef FunctionName) {
+ return Canonicalizer.lookup(FunctionName);
+ }
+
+private:
+ ItaniumManglingCanonicalizer Canonicalizer;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_SYMBOLREMAPPINGREADER_H
Modified: llvm/trunk/lib/Support/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=342161&r1=342160&r2=342161&view=diff
==============================================================================
--- llvm/trunk/lib/Support/CMakeLists.txt (original)
+++ llvm/trunk/lib/Support/CMakeLists.txt Thu Sep 13 11:51:44 2018
@@ -122,6 +122,7 @@ add_llvm_library(LLVMSupport
StringPool.cpp
StringSaver.cpp
StringRef.cpp
+ SymbolRemappingReader.cpp
SystemUtils.cpp
TarWriter.cpp
TargetParser.cpp
Added: llvm/trunk/lib/Support/SymbolRemappingReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/SymbolRemappingReader.cpp?rev=342161&view=auto
==============================================================================
--- llvm/trunk/lib/Support/SymbolRemappingReader.cpp (added)
+++ llvm/trunk/lib/Support/SymbolRemappingReader.cpp Thu Sep 13 11:51:44 2018
@@ -0,0 +1,81 @@
+//===- SymbolRemappingReader.cpp - Read symbol remapping file -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains definitions needed for reading and applying symbol
+// remapping files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SymbolRemappingReader.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/LineIterator.h"
+
+using namespace llvm;
+
+char SymbolRemappingParseError::ID;
+
+/// Load a set of name remappings from a text file.
+///
+/// See the documentation at the top of the file for an explanation of
+/// the expected format.
+Error SymbolRemappingReader::read(MemoryBuffer &B) {
+ line_iterator LineIt(B, /*SkipBlanks=*/true, '#');
+
+ auto ReportError = [&](Twine Msg) {
+ return llvm::make_error<SymbolRemappingParseError>(
+ B.getBufferIdentifier(), LineIt.line_number(), Msg);
+ };
+
+ for (; !LineIt.is_at_eof(); ++LineIt) {
+ StringRef Line = *LineIt;
+ Line = Line.ltrim(' ');
+ // line_iterator only detects comments starting in column 1.
+ if (Line.startswith("#") || Line.empty())
+ continue;
+
+ SmallVector<StringRef, 4> Parts;
+ Line.split(Parts, ' ', /*MaxSplits*/-1, /*KeepEmpty*/false);
+
+ if (Parts.size() != 3)
+ return ReportError("Expected 'kind mangled_name mangled_name', "
+ "found '" + Line + "'");
+
+ using FK = ItaniumManglingCanonicalizer::FragmentKind;
+ Optional<FK> FragmentKind = StringSwitch<Optional<FK>>(Parts[0])
+ .Case("name", FK::Name)
+ .Case("type", FK::Type)
+ .Case("encoding", FK::Encoding)
+ .Default(None);
+ if (!FragmentKind)
+ return ReportError("Invalid kind, expected 'name', 'type', or 'encoding',"
+ " found '" + Parts[0] + "'");
+
+ using EE = ItaniumManglingCanonicalizer::EquivalenceError;
+ switch (Canonicalizer.addEquivalence(*FragmentKind, Parts[1], Parts[2])) {
+ case EE::Success:
+ break;
+
+ case EE::ManglingAlreadyUsed:
+ return ReportError("Manglings '" + Parts[1] + "' and '" + Parts[2] + "' "
+ "have both been used in prior remappings. Move this "
+ "remapping earlier in the file.");
+
+ case EE::InvalidFirstMangling:
+ return ReportError("Could not demangle '" + Parts[1] + "' "
+ "as a <" + Parts[0] + ">; invalid mangling?");
+
+ case EE::InvalidSecondMangling:
+ return ReportError("Could not demangle '" + Parts[2] + "' "
+ "as a <" + Parts[0] + ">; invalid mangling?");
+ }
+ }
+
+ return Error::success();
+}
Modified: llvm/trunk/unittests/Support/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=342161&r1=342160&r2=342161&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/CMakeLists.txt (original)
+++ llvm/trunk/unittests/Support/CMakeLists.txt Thu Sep 13 11:51:44 2018
@@ -54,6 +54,7 @@ add_llvm_unittest(SupportTests
SpecialCaseListTest.cpp
StringPool.cpp
SwapByteOrderTest.cpp
+ SymbolRemappingReaderTest.cpp
TarWriterTest.cpp
TargetParserTest.cpp
TaskQueueTest.cpp
Added: llvm/trunk/unittests/Support/SymbolRemappingReaderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/SymbolRemappingReaderTest.cpp?rev=342161&view=auto
==============================================================================
--- llvm/trunk/unittests/Support/SymbolRemappingReaderTest.cpp (added)
+++ llvm/trunk/unittests/Support/SymbolRemappingReaderTest.cpp Thu Sep 13 11:51:44 2018
@@ -0,0 +1,96 @@
+//===- unittests/Support/SymbolRemappingReaderTest.cpp --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SymbolRemappingReader.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+class SymbolRemappingReaderTest : public testing::Test {
+public:
+ std::unique_ptr<MemoryBuffer> Buffer;
+ SymbolRemappingReader Reader;
+
+ std::string readWithErrors(StringRef Text, StringRef BufferName) {
+ Buffer = MemoryBuffer::getMemBuffer(Text, BufferName);
+ Error E = Reader.read(*Buffer);
+ EXPECT_TRUE((bool)E);
+ return toString(std::move(E));
+ }
+
+ void read(StringRef Text, StringRef BufferName) {
+ Buffer = MemoryBuffer::getMemBuffer(Text, BufferName);
+ Error E = Reader.read(*Buffer);
+ EXPECT_FALSE((bool)E);
+ }
+};
+} // unnamed namespace
+
+TEST_F(SymbolRemappingReaderTest, ParseErrors) {
+ EXPECT_EQ(readWithErrors("error", "foo.map"),
+ "foo.map:1: Expected 'kind mangled_name mangled_name', "
+ "found 'error'");
+
+ EXPECT_EQ(readWithErrors("error m1 m2", "foo.map"),
+ "foo.map:1: Invalid kind, expected 'name', 'type', or 'encoding', "
+ "found 'error'");
+}
+
+TEST_F(SymbolRemappingReaderTest, DemanglingErrors) {
+ EXPECT_EQ(readWithErrors("type i banana", "foo.map"),
+ "foo.map:1: Could not demangle 'banana' as a <type>; "
+ "invalid mangling?");
+ EXPECT_EQ(readWithErrors("name i 1X", "foo.map"),
+ "foo.map:1: Could not demangle 'i' as a <name>; "
+ "invalid mangling?");
+ EXPECT_EQ(readWithErrors("name 1X 1fv", "foo.map"),
+ "foo.map:1: Could not demangle '1fv' as a <name>; "
+ "invalid mangling?");
+ EXPECT_EQ(readWithErrors("encoding 1fv 1f1gE", "foo.map"),
+ "foo.map:1: Could not demangle '1f1gE' as a <encoding>; "
+ "invalid mangling?");
+}
+
+TEST_F(SymbolRemappingReaderTest, BadMappingOrder) {
+ StringRef Map = R"(
+ # N::foo == M::bar
+ name N1N3fooE N1M3barE
+
+ # N:: == M::
+ name 1N 1M
+ )";
+ EXPECT_EQ(readWithErrors(Map, "foo.map"),
+ "foo.map:6: Manglings '1N' and '1M' have both been used in prior "
+ "remappings. Move this remapping earlier in the file.");
+}
+
+TEST_F(SymbolRemappingReaderTest, RemappingsAdded) {
+ StringRef Map = R"(
+ # A::foo == B::bar
+ name N1A3fooE N1B3barE
+
+ # int == long
+ type i l
+
+ # void f<int>() = void g<int>()
+ encoding 1fIiEvv 1gIiEvv
+ )";
+
+ read(Map, "foo.map");
+ auto Key = Reader.insert("_ZN1B3bar3bazIiEEvv");
+ EXPECT_NE(Key, SymbolRemappingReader::Key());
+ EXPECT_EQ(Key, Reader.lookup("_ZN1A3foo3bazIlEEvv"));
+ EXPECT_NE(Key, Reader.lookup("_ZN1C3foo3bazIlEEvv"));
+
+ Key = Reader.insert("_Z1fIiEvv");
+ EXPECT_NE(Key, SymbolRemappingReader::Key());
+ EXPECT_EQ(Key, Reader.lookup("_Z1gIlEvv"));
+}
More information about the llvm-commits
mailing list