xref: /llvm-project/llvm/utils/TableGen/Common/GlobalISel/CodeExpander.cpp (revision fa3d789df15bd1f58fb8ba4ea3be909218cf7f03)
1*fa3d789dSPierre van Houtryve //===- CodeExpander.cpp - Expand variables in a string --------------------===//
2*fa3d789dSPierre van Houtryve //
3*fa3d789dSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fa3d789dSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information.
5*fa3d789dSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fa3d789dSPierre van Houtryve //
7*fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
8*fa3d789dSPierre van Houtryve //
9*fa3d789dSPierre van Houtryve /// \file Expand the variables in a string.
10*fa3d789dSPierre van Houtryve //
11*fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
12*fa3d789dSPierre van Houtryve 
13*fa3d789dSPierre van Houtryve #include "CodeExpander.h"
14*fa3d789dSPierre van Houtryve #include "CodeExpansions.h"
15*fa3d789dSPierre van Houtryve #include "llvm/Support/raw_ostream.h"
16*fa3d789dSPierre van Houtryve #include "llvm/TableGen/Error.h"
17*fa3d789dSPierre van Houtryve 
18*fa3d789dSPierre van Houtryve using namespace llvm;
19*fa3d789dSPierre van Houtryve 
emit(raw_ostream & OS) const20*fa3d789dSPierre van Houtryve void CodeExpander::emit(raw_ostream &OS) const {
21*fa3d789dSPierre van Houtryve   StringRef Current = Code;
22*fa3d789dSPierre van Houtryve 
23*fa3d789dSPierre van Houtryve   while (!Current.empty()) {
24*fa3d789dSPierre van Houtryve     size_t Pos = Current.find_first_of("$\n\\");
25*fa3d789dSPierre van Houtryve     if (Pos == StringRef::npos) {
26*fa3d789dSPierre van Houtryve       OS << Current;
27*fa3d789dSPierre van Houtryve       Current = "";
28*fa3d789dSPierre van Houtryve       continue;
29*fa3d789dSPierre van Houtryve     }
30*fa3d789dSPierre van Houtryve 
31*fa3d789dSPierre van Houtryve     OS << Current.substr(0, Pos);
32*fa3d789dSPierre van Houtryve     Current = Current.substr(Pos);
33*fa3d789dSPierre van Houtryve 
34*fa3d789dSPierre van Houtryve     if (Current.consume_front("\n")) {
35*fa3d789dSPierre van Houtryve       OS << "\n" << Indent;
36*fa3d789dSPierre van Houtryve       continue;
37*fa3d789dSPierre van Houtryve     }
38*fa3d789dSPierre van Houtryve 
39*fa3d789dSPierre van Houtryve     if (Current.starts_with("\\$") || Current.starts_with("\\\\")) {
40*fa3d789dSPierre van Houtryve       OS << Current[1];
41*fa3d789dSPierre van Houtryve       Current = Current.drop_front(2);
42*fa3d789dSPierre van Houtryve       continue;
43*fa3d789dSPierre van Houtryve     }
44*fa3d789dSPierre van Houtryve 
45*fa3d789dSPierre van Houtryve     if (Current.consume_front("\\"))
46*fa3d789dSPierre van Houtryve       continue;
47*fa3d789dSPierre van Houtryve 
48*fa3d789dSPierre van Houtryve     if (Current.starts_with("${")) {
49*fa3d789dSPierre van Houtryve       StringRef StartVar = Current;
50*fa3d789dSPierre van Houtryve       Current = Current.drop_front(2);
51*fa3d789dSPierre van Houtryve       StringRef Var;
52*fa3d789dSPierre van Houtryve       std::tie(Var, Current) = Current.split("}");
53*fa3d789dSPierre van Houtryve 
54*fa3d789dSPierre van Houtryve       // Warn if we split because no terminator was found.
55*fa3d789dSPierre van Houtryve       StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size());
56*fa3d789dSPierre van Houtryve       if (EndVar.empty()) {
57*fa3d789dSPierre van Houtryve         PrintWarning(Loc, "Unterminated expansion '${" + Var + "'");
58*fa3d789dSPierre van Houtryve         PrintNote("Code: [{" + Code + "}]");
59*fa3d789dSPierre van Houtryve       }
60*fa3d789dSPierre van Houtryve 
61*fa3d789dSPierre van Houtryve       auto ValueI = Expansions.find(Var);
62*fa3d789dSPierre van Houtryve       if (ValueI == Expansions.end()) {
63*fa3d789dSPierre van Houtryve         PrintError(Loc,
64*fa3d789dSPierre van Houtryve                    "Attempt to expand an undeclared variable '" + Var + "'");
65*fa3d789dSPierre van Houtryve         PrintNote("Code: [{" + Code + "}]");
66*fa3d789dSPierre van Houtryve       }
67*fa3d789dSPierre van Houtryve       if (ShowExpansions)
68*fa3d789dSPierre van Houtryve         OS << "/*$" << Var << "{*/";
69*fa3d789dSPierre van Houtryve       OS << Expansions.lookup(Var);
70*fa3d789dSPierre van Houtryve       if (ShowExpansions)
71*fa3d789dSPierre van Houtryve         OS << "/*}*/";
72*fa3d789dSPierre van Houtryve       continue;
73*fa3d789dSPierre van Houtryve     }
74*fa3d789dSPierre van Houtryve 
75*fa3d789dSPierre van Houtryve     PrintWarning(Loc, "Assuming missing escape character: \\$");
76*fa3d789dSPierre van Houtryve     PrintNote("Code: [{" + Code + "}]");
77*fa3d789dSPierre van Houtryve     OS << "$";
78*fa3d789dSPierre van Houtryve     Current = Current.drop_front(1);
79*fa3d789dSPierre van Houtryve   }
80*fa3d789dSPierre van Houtryve }
81