File indexing completed on 2026-05-10 08:44:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
0010 #define LLVM_TABLEGEN_STRINGTOOFFSETTABLE_H
0011
0012 #include "llvm/ADT/SmallString.h"
0013 #include "llvm/ADT/StringExtras.h"
0014 #include "llvm/ADT/StringMap.h"
0015 #include "llvm/Support/FormatVariadic.h"
0016 #include "llvm/Support/raw_ostream.h"
0017 #include <optional>
0018
0019 namespace llvm {
0020
0021
0022
0023
0024
0025 class StringToOffsetTable {
0026 StringMap<unsigned> StringOffset;
0027 std::string AggregateString;
0028
0029 public:
0030 StringToOffsetTable() {
0031
0032
0033 GetOrAddStringOffset("");
0034 }
0035
0036 bool empty() const { return StringOffset.empty(); }
0037 size_t size() const { return AggregateString.size(); }
0038
0039 unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
0040 auto [II, Inserted] = StringOffset.insert({Str, size()});
0041 if (Inserted) {
0042
0043 AggregateString.append(Str.begin(), Str.end());
0044 if (appendZero)
0045 AggregateString += '\0';
0046 }
0047
0048 return II->second;
0049 }
0050
0051
0052
0053 std::optional<unsigned> GetStringOffset(StringRef Str) const {
0054 auto II = StringOffset.find(Str);
0055 if (II == StringOffset.end())
0056 return std::nullopt;
0057 return II->second;
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 void EmitStringTableDef(raw_ostream &OS, const Twine &Name,
0072 const Twine &Indent = "") const {
0073 OS << formatv(R"(
0074 #ifdef __GNUC__
0075 #pragma GCC diagnostic push
0076 #pragma GCC diagnostic ignored "-Woverlength-strings"
0077 #endif
0078 {0}static constexpr char {1}Storage[] = )",
0079 Indent, Name);
0080
0081
0082
0083
0084 bool UseChars = AggregateString.size() > (64 * 1024);
0085 OS << (UseChars ? "{\n" : "\n");
0086
0087 llvm::ListSeparator LineSep(UseChars ? ",\n" : "\n");
0088 llvm::SmallVector<StringRef> Strings(split(AggregateString, '\0'));
0089
0090
0091
0092 assert(Strings.front().empty() && "Expected empty initial string!");
0093 assert(Strings.back().empty() &&
0094 "Expected empty string at the end due to terminators!");
0095 Strings.pop_back();
0096 for (StringRef Str : Strings) {
0097 OS << LineSep << Indent << " ";
0098
0099 if (!UseChars) {
0100 OS << "\"";
0101 OS.write_escaped(Str);
0102 OS << "\\0\"";
0103 continue;
0104 }
0105
0106 llvm::ListSeparator CharSep(", ");
0107 for (char C : Str) {
0108 OS << CharSep << "'";
0109 OS.write_escaped(StringRef(&C, 1));
0110 OS << "'";
0111 }
0112 OS << CharSep << "'\\0'";
0113 }
0114 OS << LineSep << Indent << (UseChars ? "};" : " ;");
0115
0116 OS << formatv(R"(
0117 #ifdef __GNUC__
0118 #pragma GCC diagnostic pop
0119 #endif
0120
0121 {0}static constexpr llvm::StringTable {1} =
0122 {0} {1}Storage;
0123 )",
0124 Indent, Name);
0125 }
0126
0127
0128 void EmitString(raw_ostream &O) const {
0129
0130 SmallString<256> EscapedStr;
0131 raw_svector_ostream(EscapedStr).write_escaped(AggregateString);
0132
0133 O << " \"";
0134 unsigned CharsPrinted = 0;
0135 for (unsigned i = 0, e = EscapedStr.size(); i != e; ++i) {
0136 if (CharsPrinted > 70) {
0137 O << "\"\n \"";
0138 CharsPrinted = 0;
0139 }
0140 O << EscapedStr[i];
0141 ++CharsPrinted;
0142
0143
0144 if (EscapedStr[i] != '\\')
0145 continue;
0146
0147 assert(i + 1 < EscapedStr.size() && "Incomplete escape sequence!");
0148 if (isDigit(EscapedStr[i + 1])) {
0149 assert(isDigit(EscapedStr[i + 2]) && isDigit(EscapedStr[i + 3]) &&
0150 "Expected 3 digit octal escape!");
0151 O << EscapedStr[++i];
0152 O << EscapedStr[++i];
0153 O << EscapedStr[++i];
0154 CharsPrinted += 3;
0155 } else {
0156 O << EscapedStr[++i];
0157 ++CharsPrinted;
0158 }
0159 }
0160 O << "\"";
0161 }
0162 };
0163
0164 }
0165
0166 #endif