Index: llvm/docs/TableGen/BackGuide.rst =================================================================== --- llvm/docs/TableGen/BackGuide.rst +++ llvm/docs/TableGen/BackGuide.rst @@ -336,14 +336,11 @@ The ``CodeInit`` class is a subclass of ``TypedInit``. Its instances represent arbitrary-length strings produced from ``code`` literals in the TableGen files. It includes a data member that contains a ``StringRef`` of -the value. It also includes a data member specifying the source code -location of the code string. +the value. The class provides the usual ``get()`` and ``getValue()`` functions. The latter function returns the ``StringRef``. -The ``getLoc()`` function returns the source code location. - ``DagInit`` ~~~~~~~~~~~ Index: llvm/include/llvm/TableGen/Record.h =================================================================== --- llvm/include/llvm/TableGen/Record.h +++ llvm/include/llvm/TableGen/Record.h @@ -597,7 +597,13 @@ /// "foo" - Represent an initialization by a string value. class StringInit : public TypedInit { +//// enum StringFormat { +//// SF_String, // Format as "text" +//// SF_Code, // Format as [{text}] +//// }; + StringRef Value; +//// StringFormat Format; explicit StringInit(StringRef V) : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} @@ -630,11 +636,14 @@ class CodeInit : public TypedInit { StringRef Value; - SMLoc Loc; +//// SMLoc Loc; - explicit CodeInit(StringRef V, const SMLoc &Loc) + explicit CodeInit(StringRef V) : TypedInit(IK_CodeInit, static_cast(CodeRecTy::get())), - Value(V), Loc(Loc) {} + Value(V) {} +//// explicit CodeInit(StringRef V, const SMLoc &Loc) +//// : TypedInit(IK_CodeInit, static_cast(CodeRecTy::get())), +//// Value(V), Loc(Loc) {} public: CodeInit(const StringInit &) = delete; @@ -644,10 +653,11 @@ return I->getKind() == IK_CodeInit; } - static CodeInit *get(StringRef, const SMLoc &Loc); + static CodeInit *get(StringRef); +//// static CodeInit *get(StringRef, const SMLoc &Loc); StringRef getValue() const { return Value; } - const SMLoc &getLoc() const { return Loc; } +//// const SMLoc &getLoc() const { return Loc; } Init *convertInitializerTo(RecTy *Ty) const override; @@ -1649,6 +1659,9 @@ // High-level methods useful to tablegen back-ends // + ///Return the source location for the named field. + SMLoc getFieldLoc(StringRef FieldName) const; + /// Return the initializer for a value with the specified name, /// or throw an exception if the field does not exist. Init *getValueInit(StringRef FieldName) const; Index: llvm/lib/TableGen/Record.cpp =================================================================== --- llvm/lib/TableGen/Record.cpp +++ llvm/lib/TableGen/Record.cpp @@ -514,20 +514,13 @@ return BitsInit::get(NewBits); } -CodeInit *CodeInit::get(StringRef V, const SMLoc &Loc) { - static StringSet ThePool(Allocator); +CodeInit *CodeInit::get(StringRef V) { + static StringMap ThePool(Allocator); - CodeInitsConstructed++; - - // Unlike StringMap, StringSet doesn't accept empty keys. - if (V.empty()) - return new (Allocator) CodeInit("", Loc); - - // Location tracking prevents us from de-duping CodeInits as we're never - // called with the same string and same location twice. However, we can at - // least de-dupe the strings for a modest saving. - auto &Entry = *ThePool.insert(V).first; - return new(Allocator) CodeInit(Entry.getKey(), Loc); + auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first; + if (!Entry.second) + Entry.second = new(Allocator) CodeInit(Entry.getKey()); + return Entry.second; } StringInit *StringInit::get(StringRef V) { @@ -543,7 +536,7 @@ if (isa(Ty)) return const_cast(this); if (isa(Ty)) - return CodeInit::get(getValue(), SMLoc()); + return CodeInit::get(getValue()); return nullptr; } @@ -1046,8 +1039,6 @@ default: llvm_unreachable("unhandled comparison"); } return BitInit::get(Result); -//// bool Equal = LHSs->getValue() == RHSs->getValue(); -//// return BitInit::get(getOpcode() == EQ ? Equal : !Equal); } // Finally, !eq and !ne can be used with records. @@ -2170,7 +2161,7 @@ return false; } -// This version of setValue takes an source location and resets the +// This version of setValue takes a source location and resets the // location in the RecordVal. bool RecordVal::setValue(Init *V, SMLoc NewLoc) { Loc = NewLoc; @@ -2351,6 +2342,14 @@ return OS << "}\n"; } +SMLoc Record::getFieldLoc(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (!R) + PrintFatalError(getLoc(), "Record `" + getName() + + "' does not have a field named `" + FieldName + "'!\n"); + return R->getLoc(); +} + Init *Record::getValueInit(StringRef FieldName) const { const RecordVal *R = getValue(FieldName); if (!R || !R->getValue()) Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -1920,7 +1920,7 @@ break; } case tgtok::CodeFragment: - R = CodeInit::get(Lex.getCurStrVal(), Lex.getLoc()); + R = CodeInit::get(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: Index: llvm/unittests/TableGen/CodeExpanderTest.cpp =================================================================== --- llvm/unittests/TableGen/CodeExpanderTest.cpp +++ llvm/unittests/TableGen/CodeExpanderTest.cpp @@ -113,8 +113,8 @@ .emit(OS); EXPECT_EQ(OS.str(), " $foo"); DiagChecker.expect(SMDiagnostic( - SrcMgr, SMLoc::getFromPointer(In.data() + 1), "TestBuffer", 1, 1, - SourceMgr::DK_Warning, "Assuming missing escape character", " $foo", {})); + SrcMgr, SMLoc::getFromPointer(In.data()), "TestBuffer", 1, 0, + SourceMgr::DK_Warning, "Assuming missing escape character: \\$", " $foo", {})); } // \$foo is not an expansion but shouldn't warn as it's using the escape. @@ -162,27 +162,7 @@ EXPECT_EQ(OS.str(), "expansion"); DiagChecker.expect( SMDiagnostic(SrcMgr, SMLoc(), "", 0, -1, SourceMgr::DK_Error, - "Attempting to expand an undeclared variable foo", "", {})); -} - -// ${foo} is an undefined expansion and should error. When given a valid -// location for the start of the buffer it should correctly point at the -// expansion being performed. -TEST(CodeExpander, UndefinedExpansionWithLoc) { - std::string Result; - raw_string_ostream OS(Result); - CodeExpansions Expansions; - Expansions.declare("bar", "expansion"); - - RAIIDiagnosticChecker DiagChecker; - StringRef In = bufferize("Padding ${foo}${bar}"); - CodeExpander(In, Expansions, SMLoc::getFromPointer(In.data()), false) - .emit(OS); - EXPECT_EQ(OS.str(), "Padding expansion"); - DiagChecker.expect(SMDiagnostic( - SrcMgr, SMLoc::getFromPointer(In.data() + 8), "TestBuffer", 1, 8, - SourceMgr::DK_Error, "Attempting to expand an undeclared variable foo", - "Padding ${foo}${bar}", {})); + "Attempt to expand an undeclared variable 'foo'", "", {})); } // ${bar is an unterminated expansion. Warn and implicitly terminate it. @@ -197,7 +177,7 @@ CodeExpander(In, Expansions, SMLoc::getFromPointer(In.data()), false) .emit(OS); EXPECT_EQ(OS.str(), " expansion"); - DiagChecker.expect(SMDiagnostic(SrcMgr, SMLoc::getFromPointer(In.data() + 1), - "TestBuffer", 1, 1, SourceMgr::DK_Warning, - "Unterminated expansion", " ${bar", {})); + DiagChecker.expect(SMDiagnostic(SrcMgr, SMLoc::getFromPointer(In.data()), + "TestBuffer", 1, 0, SourceMgr::DK_Warning, + "Unterminated expansion '${bar'", " ${bar", {})); } Index: llvm/utils/TableGen/GICombinerEmitter.cpp =================================================================== --- llvm/utils/TableGen/GICombinerEmitter.cpp +++ llvm/utils/TableGen/GICombinerEmitter.cpp @@ -759,7 +759,7 @@ DagInit *Applyer = RuleDef.getValueAsDag("Apply"); if (Applyer->getOperatorAsDef(RuleDef.getLoc())->getName() != "apply") { - PrintError(RuleDef.getLoc(), "Expected apply operator"); + PrintError(RuleDef.getLoc(), "Expected 'apply' operator in Apply DAG"); return; } @@ -800,7 +800,7 @@ OS << Indent << " && [&]() {\n" << Indent << " " << CodeExpander(Rule->getMatchingFixupCode()->getValue(), Expansions, - Rule->getMatchingFixupCode()->getLoc(), ShowExpansions) + RuleDef.getLoc(), ShowExpansions) << "\n" << Indent << " return true;\n" << Indent << " }()"; @@ -809,7 +809,7 @@ if (const CodeInit *Code = dyn_cast(Applyer->getArg(0))) { OS << CodeExpander(Code->getAsUnquotedString(), Expansions, - Code->getLoc(), ShowExpansions) + RuleDef.getLoc(), ShowExpansions) << "\n" << Indent << " return true;\n" << Indent << " }\n"; Index: llvm/utils/TableGen/GlobalISel/CodeExpander.cpp =================================================================== --- llvm/utils/TableGen/GlobalISel/CodeExpander.cpp +++ llvm/utils/TableGen/GlobalISel/CodeExpander.cpp @@ -58,21 +58,15 @@ // Warn if we split because no terminator was found. StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); if (EndVar.empty()) { - size_t LocOffset = StartVar.data() - Code.data(); - PrintWarning( - Loc.size() > 0 && Loc[0].isValid() - ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) - : SMLoc(), - "Unterminated expansion"); + PrintWarning(Loc, "Unterminated expansion '${" + Var + "'"); + PrintNote("Code: [{" + Code + "}]"); } auto ValueI = Expansions.find(Var); if (ValueI == Expansions.end()) { - size_t LocOffset = StartVar.data() - Code.data(); - PrintError(Loc.size() > 0 && Loc[0].isValid() - ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) - : SMLoc(), - "Attempting to expand an undeclared variable " + Var); + PrintError(Loc, + "Attempt to expand an undeclared variable '" + Var + "'"); + PrintNote("Code: [{" + Code + "}]"); } if (ShowExpansions) OS << "/*$" << Var << "{*/"; @@ -82,11 +76,8 @@ continue; } - size_t LocOffset = Current.data() - Code.data(); - PrintWarning(Loc.size() > 0 && Loc[0].isValid() - ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) - : SMLoc(), - "Assuming missing escape character"); + PrintWarning(Loc, "Assuming missing escape character: \\$"); + PrintNote("Code: [{" + Code + "}]"); OS << "$"; Current = Current.drop_front(1); }