LLVM 24.0.0git
StringToOffsetTable.cpp
Go to the documentation of this file.
1//===- StringToOffsetTable.cpp - Emit a big concatenated string -*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
12#include "llvm/TableGen/Error.h"
13#include "llvm/TableGen/Main.h"
14
15using namespace llvm;
16
18 auto [II, Inserted] = StringOffset.insert({Str, size()});
19 if (Inserted) {
20 // Add the string to the aggregate if this is the first time found.
21 AggregateString.append(Str.begin(), Str.end());
22 if (AppendZero)
23 AggregateString += '\0';
24 }
25
26 return II->second;
27}
28
30 const Twine &Name) const {
31 // String table entries must be null terminated.
32 if (!AppendZero)
33 PrintFatalError("llvm::StringTable requires null terminated strings");
34
35 OS << formatv(R"(
36#ifdef __GNUC__
37#pragma GCC diagnostic push
38#pragma GCC diagnostic ignored "-Woverlength-strings"
39#endif
40{} constexpr char {}{}Storage[] =)",
41 ClassPrefix.empty() ? "static" : "",
42 UsePrefixForStorageMember ? ClassPrefix : "", Name);
43
44 // MSVC silently miscompiles string literals longer than 64k in some
45 // circumstances. The build system sets EmitLongStrLiterals to false when it
46 // detects that it is targetting MSVC. When that option is false and the
47 // string table is longer than 64k, emit it as an array of character
48 // literals.
49 bool UseChars = !EmitLongStrLiterals && AggregateString.size() > (64 * 1024);
50 OS << (UseChars ? "{\n" : "\n");
51
52 ListSeparator LineSep(UseChars ? ",\n" : "\n");
53 SmallVector<StringRef> Strings(split(AggregateString, '\0'));
54 // We should always have an empty string at the start, and because these are
55 // null terminators rather than separators, we'll have one at the end as
56 // well. Skip the end one.
57 assert(Strings.front().empty() && "Expected empty initial string!");
58 assert(Strings.back().empty() &&
59 "Expected empty string at the end due to terminators!");
60 Strings.pop_back();
61 for (StringRef Str : Strings) {
62 OS << LineSep << " ";
63 // If we can, just emit this as a string literal to be concatenated.
64 if (!UseChars) {
65 OS << "\"";
66 OS.write_escaped(Str);
67 OS << "\\0\"";
68 continue;
69 }
70
71 ListSeparator CharSep(", ");
72 for (char C : Str) {
73 OS << CharSep << "'";
74 if (C == '\'')
75 OS << "\\'";
76 else
77 OS.write_escaped(StringRef(&C, 1));
78 OS << "'";
79 }
80 OS << CharSep << "'\\0'";
81 }
82 OS << LineSep << (UseChars ? "};" : " ;");
83
84 OS << R"(
85#ifdef __GNUC__
86#pragma GCC diagnostic pop
87#endif
88)";
89}
92 const Twine &Name) const {
94 OS << formatv(R"(
95{1} llvm::StringTable
96{2}{0} = {0}Storage;
97)",
98 Name, ClassPrefix.empty() ? "static constexpr" : "const",
99 ClassPrefix);
100}
101
103 // Escape the string.
104 SmallString<256> EscapedStr;
105 raw_svector_ostream(EscapedStr).write_escaped(AggregateString);
106
107 O << " \"";
108 unsigned CharsPrinted = 0;
109 for (unsigned i = 0, e = EscapedStr.size(); i != e; ++i) {
110 if (CharsPrinted > 70) {
111 O << "\"\n \"";
112 CharsPrinted = 0;
113 }
114 O << EscapedStr[i];
115 ++CharsPrinted;
116
117 // Print escape sequences all together.
118 if (EscapedStr[i] != '\\')
119 continue;
120
121 assert(i + 1 < EscapedStr.size() && "Incomplete escape sequence!");
122 if (isDigit(EscapedStr[i + 1])) {
123 assert(isDigit(EscapedStr[i + 2]) && isDigit(EscapedStr[i + 3]) &&
124 "Expected 3 digit octal escape!");
125 O << EscapedStr[++i];
126 O << EscapedStr[++i];
127 O << EscapedStr[++i];
128 CharsPrinted += 3;
129 if (i + 1 < EscapedStr.size() && isDigit(EscapedStr[i + 1])) {
130 // If a digit follows after an octal literal, separate the string
131 // literals to silence MSVC warning C4125.
132 O << "\" \"";
133 CharsPrinted += 3;
134 }
135 } else {
136 O << EscapedStr[++i];
137 ++CharsPrinted;
138 }
139 }
140 O << "\"";
141}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
uint64_t IntrinsicInst * II
A helper class to return the specified delimiter string after the first invocation of operator String...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM_ABI unsigned GetOrAddStringOffset(StringRef Str)
LLVM_ABI void EmitStringTableDef(raw_ostream &OS, const Twine &Name) const
LLVM_ABI void EmitString(raw_ostream &O) const
LLVM_ABI void EmitStringTableStorageDef(raw_ostream &OS, const Twine &Name) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
A raw_ostream that writes to an SmallVector or SmallString.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void PrintFatalError(const Twine &Msg)
Definition Error.cpp:132
LLVM_ABI cl::opt< bool > EmitLongStrLiterals
Controls emitting large character arrays as strings or character arrays.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...