[llvm] e395124 - [yaml2obj] Add -D k=v to preprocess the input YAML
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 7 09:40:02 PST 2020
Author: Fangrui Song
Date: 2020-02-07T09:35:00-08:00
New Revision: e3951248b14f5523cb93b380f0995d611a56192f
URL: https://github.com/llvm/llvm-project/commit/e3951248b14f5523cb93b380f0995d611a56192f
DIFF: https://github.com/llvm/llvm-project/commit/e3951248b14f5523cb93b380f0995d611a56192f.diff
LOG: [yaml2obj] Add -D k=v to preprocess the input YAML
Examples:
```
yaml2obj -D MACHINE=EM_386 a.yaml -o a.o
yaml2obj -D MACHINE=0x1234 a.yaml -o a.o
```
where a.yaml contains:
```
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2MSB
Type: ET_REL
Machine: [[MACHINE]]
```
Reviewed By: grimar, jhenderson
Differential Revision: https://reviews.llvm.org/D73821
Added:
llvm/test/tools/yaml2obj/macro.yaml
Modified:
llvm/tools/yaml2obj/yaml2obj.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/yaml2obj/macro.yaml b/llvm/test/tools/yaml2obj/macro.yaml
new file mode 100644
index 000000000000..d7834fa6d97a
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/macro.yaml
@@ -0,0 +1,60 @@
+# RUN: yaml2obj -D NAME= %s | llvm-nm - | FileCheck --check-prefix=FBAR %s
+# FBAR: U fbar
+
+# RUN: yaml2obj -D NAME=o %s | llvm-nm - | FileCheck --check-prefix=FOOBAR %s
+# RUN: yaml2obj -DNAME=o %s | llvm-nm - | FileCheck --check-prefix=FOOBAR %s
+# FOOBAR: U foobar
+
+# RUN: not yaml2obj -D NAME %s 2>&1 | FileCheck --check-prefix=ERR1 %s
+# ERR1: error: invalid syntax for -D: NAME
+
+# RUN: not yaml2obj -D =value %s 2>&1 | FileCheck --check-prefix=ERR2 %s
+# ERR2: error: invalid syntax for -D: =value
+
+# RUN: not yaml2obj -D NAME=a -D NAME=b %s 2>&1 | FileCheck --check-prefix=ERR3 %s
+# ERR3: error: 'NAME' redefined
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Symbols:
+ - Name: f[[NAME]][[NAME]]bar
+
+## Digits can appear in macro names. Test that we don't expand macros recursively.
+# RUN: yaml2obj --docnum=2 -D a0='[[a1]]' -D a1='[[a0]]' %s | llvm-nm --just-symbol-name --no-sort - > %t.recur
+# RUN: echo -e '[[a1]]\n[[a0]]' > %t0.recur
+# RUN:
diff -u %t0.recur %t.recur
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Symbols:
+ - Name: "[[a0]]"
+ - Name: "[[a1]]"
+
+## Test unterminated [[.
+# RUN: yaml2obj --docnum=3 %s | llvm-nm --just-symbol-name --no-sort - > %t.nosubst
+# RUN: echo -e 'a[[\n[[a]\n[[a[[a]]\n[[a][[a]][[b]]' > %t0.nosubst
+# RUN:
diff -u %t0.nosubst %t.nosubst
+
+# RUN: yaml2obj --docnum=3 -D a=b -D b=c %s | llvm-nm --just-symbol-name --no-sort - > %t.subst
+# RUN: echo -e 'a[[\n[[a]\n[[ab\n[[a]bc' > %t0.subst
+# RUN:
diff -u %t0.subst %t.subst
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Symbols:
+ - Name: "a[["
+ - Name: "[[a]"
+ - Name: "[[a[[a]]"
+ - Name: "[[a][[a]][[b]]"
diff --git a/llvm/tools/yaml2obj/yaml2obj.cpp b/llvm/tools/yaml2obj/yaml2obj.cpp
index dd92e01f479a..8a23b2281ca6 100644
--- a/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -34,6 +34,11 @@ cl::OptionCategory Cat("yaml2obj Options");
cl::opt<std::string> Input(cl::Positional, cl::desc("<input file>"),
cl::init("-"), cl::cat(Cat));
+cl::list<std::string>
+ D("D", cl::Prefix,
+ cl::desc("Defined the specified macros to their specified "
+ "definition. The syntax is <macro>=<definition>"));
+
cl::opt<unsigned>
DocNum("docnum", cl::init(1),
cl::desc("Read specified document from input (default = 1)"),
@@ -44,6 +49,44 @@ cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
cl::Prefix, cl::cat(Cat));
} // namespace
+static Optional<std::string> preprocess(StringRef Buf,
+ yaml::ErrorHandler ErrHandler) {
+ DenseMap<StringRef, StringRef> Defines;
+ for (StringRef Define : D) {
+ StringRef Macro, Definition;
+ std::tie(Macro, Definition) = Define.split('=');
+ if (!Define.count('=') || Macro.empty()) {
+ ErrHandler("invalid syntax for -D: " + Define);
+ return {};
+ }
+ if (!Defines.try_emplace(Macro, Definition).second) {
+ ErrHandler("'" + Macro + "'" + " redefined");
+ return {};
+ }
+ }
+
+ std::string Preprocessed;
+ while (!Buf.empty()) {
+ if (Buf.startswith("[[")) {
+ size_t I = Buf.find_first_of("[]", 2);
+ if (Buf.substr(I).startswith("]]")) {
+ StringRef Macro = Buf.substr(2, I - 2);
+ auto It = Defines.find(Macro);
+ if (It != Defines.end()) {
+ Preprocessed += It->second;
+ Buf = Buf.substr(I + 2);
+ continue;
+ }
+ }
+ }
+
+ Preprocessed += Buf[0];
+ Buf = Buf.substr(1);
+ }
+
+ return Preprocessed;
+}
+
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
cl::HideUnrelatedOptions(Cat);
@@ -68,7 +111,10 @@ int main(int argc, char **argv) {
if (!Buf)
return 1;
- yaml::Input YIn(Buf.get()->getBuffer());
+ Optional<std::string> Buffer = preprocess(Buf.get()->getBuffer(), ErrHandler);
+ if (!Buffer)
+ return 1;
+ yaml::Input YIn(*Buffer);
if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum))
return 1;
More information about the llvm-commits
mailing list