llvm.org GIT mirror llvm / 19ea665
[WebAssembly] Parse llvm.ident into producers section Summary: Everything before the word "version" is the tool, and everything after the word "version" is the version. Reviewers: aheejin, dschuff Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D56742 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351399 91177308-0d34-0410-b5e6-96231b3b80d8 Thomas Lively 7 months ago
14 changed file(s) with 280 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
4040 uint32_t TableSize; // Table size in elements
4141 uint32_t TableAlignment; // P2 alignment of table
4242 std::vector Needed; // Shared library depenedencies
43 };
44
45 struct WasmProducerInfo {
46 std::vector> Languages;
47 std::vector> Tools;
48 std::vector> SDKs;
4349 };
4450
4551 struct WasmExport {
129129 static bool classof(const Binary *v) { return v->isWasm(); }
130130
131131 const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
132 const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
132133 ArrayRef types() const { return Signatures; }
133134 ArrayRef functionTypes() const { return FunctionTypes; }
134135 ArrayRef imports() const { return Imports; }
148149 uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
149150 uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
150151 uint32_t getNumImportedEvents() const { return NumImportedEvents; }
151
152152 void moveSymbolNext(DataRefImpl &Symb) const override;
153153
154154 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
251251 Error parseLinkingSection(ReadContext &Ctx);
252252 Error parseLinkingSectionSymtab(ReadContext &Ctx);
253253 Error parseLinkingSectionComdat(ReadContext &Ctx);
254 Error parseProducersSection(ReadContext &Ctx);
254255 Error parseRelocSection(StringRef Name, ReadContext &Ctx);
255256
256257 wasm::WasmObjectHeader Header;
257258 std::vector Sections;
258259 wasm::WasmDylinkInfo DylinkInfo;
260 wasm::WasmProducerInfo ProducerInfo;
259261 std::vector Signatures;
260262 std::vector FunctionTypes;
261263 std::vector Tables;
122122 StringRef Name;
123123 };
124124
125 struct ProducerEntry {
126 std::string Name;
127 std::string Version;
128 };
129
125130 struct SegmentInfo {
126131 uint32_t Index;
127132 StringRef Name;
221226 std::vector SegmentInfos;
222227 std::vector InitFunctions;
223228 std::vector Comdats;
229 };
230
231 struct ProducersSection : CustomSection {
232 ProducersSection() : CustomSection("producers") {}
233
234 static bool classof(const Section *S) {
235 auto C = dyn_cast(S);
236 return C && C->Name == "producers";
237 }
238
239 std::vector Languages;
240 std::vector Tools;
241 std::vector SDKs;
224242 };
225243
226244 struct TypeSection : Section {
365383 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
366384 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
367385 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
386 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ProducerEntry)
368387 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
369388 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
370389 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
443462 static void mapping(IO &IO, WasmYAML::NameEntry &NameEntry);
444463 };
445464
465 template <> struct MappingTraits {
466 static void mapping(IO &IO, WasmYAML::ProducerEntry &ProducerEntry);
467 };
468
446469 template <> struct MappingTraits {
447470 static void mapping(IO &IO, WasmYAML::SegmentInfo &SegmentInfo);
448471 };
223223 // Stores output data (index, relocations, content offset) for custom
224224 // section.
225225 std::vector CustomSections;
226 std::unique_ptr ProducersSection;
226227 // Relocations for fixing up references in the custom sections.
227228 DenseMap>
228229 CustomSectionsRelocations;
264265 WasmIndices.clear();
265266 TableIndices.clear();
266267 DataLocations.clear();
268 CustomSections.clear();
269 ProducersSection.reset();
267270 CustomSectionsRelocations.clear();
268271 SignatureIndices.clear();
269272 Signatures.clear();
310313 ArrayRef SymbolInfos,
311314 ArrayRef> InitFuncs,
312315 const std::map> &Comdats);
313 void writeCustomSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
316 void writeCustomSection(WasmCustomSection &CustomSection,
317 const MCAssembler &Asm, const MCAsmLayout &Layout);
314318 void writeCustomRelocSections();
315319 void
316320 updateCustomSectionRelocations(const SmallVector &Functions,
10441048 endSection(Section);
10451049 }
10461050
1047 void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
1048 const MCAsmLayout &Layout) {
1049 for (auto &CustomSection : CustomSections) {
1050 SectionBookkeeping Section;
1051 auto *Sec = CustomSection.Section;
1052 startCustomSection(Section, CustomSection.Name);
1053
1054 Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
1055 Asm.writeSectionData(W.OS, Sec, Layout);
1056
1057 CustomSection.OutputContentsOffset = Section.ContentsOffset;
1058 CustomSection.OutputIndex = Section.Index;
1059
1060 endSection(Section);
1061
1062 // Apply fixups.
1063 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1064 applyRelocations(Relocations, CustomSection.OutputContentsOffset);
1065 }
1051 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1052 const MCAssembler &Asm,
1053 const MCAsmLayout &Layout) {
1054 SectionBookkeeping Section;
1055 auto *Sec = CustomSection.Section;
1056 startCustomSection(Section, CustomSection.Name);
1057
1058 Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
1059 Asm.writeSectionData(W.OS, Sec, Layout);
1060
1061 CustomSection.OutputContentsOffset = Section.ContentsOffset;
1062 CustomSection.OutputIndex = Section.Index;
1063
1064 endSection(Section);
1065
1066 // Apply fixups.
1067 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1068 applyRelocations(Relocations, CustomSection.OutputContentsOffset);
10661069 }
10671070
10681071 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
12811284 report_fatal_error("section name and begin symbol should match: " +
12821285 Twine(SectionName));
12831286 }
1287
1288 // Separate out the producers section
1289 if (Name == "producers") {
1290 ProducersSection = llvm::make_unique(Name, &Section);
1291 continue;
1292 }
1293
12841294 CustomSections.emplace_back(Name, &Section);
12851295 }
12861296 }
15691579 writeElemSection(TableElems);
15701580 writeCodeSection(Asm, Layout, Functions);
15711581 writeDataSection();
1572 writeCustomSections(Asm, Layout);
1582 for (auto &CustomSection : CustomSections)
1583 writeCustomSection(CustomSection, Asm, Layout);
15731584 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
15741585 writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
15751586 writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
15761587 writeCustomRelocSections();
1588 if (ProducersSection)
1589 writeCustomSection(*ProducersSection, Asm, Layout);
15771590
15781591 // TODO: Translate the .comment section to the output.
15791592 return W.OS.tell() - StartOffset;
99 #include "llvm/ADT/ArrayRef.h"
1010 #include "llvm/ADT/DenseSet.h"
1111 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallSet.h"
1213 #include "llvm/ADT/StringRef.h"
1314 #include "llvm/ADT/StringSet.h"
1415 #include "llvm/ADT/Triple.h"
658659 return Error::success();
659660 }
660661
662 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
663 llvm::SmallSet FieldsSeen;
664 uint32_t Fields = readVaruint32(Ctx);
665 for (size_t i = 0; i < Fields; ++i) {
666 StringRef FieldName = readString(Ctx);
667 if (!FieldsSeen.insert(FieldName).second)
668 return make_error(
669 "Producers section does not have unique fields",
670 object_error::parse_failed);
671 std::vector> *ProducerVec = nullptr;
672 if (FieldName == "language") {
673 ProducerVec = &ProducerInfo.Languages;
674 } else if (FieldName == "processed-by") {
675 ProducerVec = &ProducerInfo.Tools;
676 } else if (FieldName == "sdk") {
677 ProducerVec = &ProducerInfo.SDKs;
678 } else {
679 return make_error(
680 "Producers section field is not named one of language, processed-by, "
681 "or sdk",
682 object_error::parse_failed);
683 }
684 uint32_t ValueCount = readVaruint32(Ctx);
685 llvm::SmallSet ProducersSeen;
686 for (size_t j = 0; j < ValueCount; ++j) {
687 StringRef Name = readString(Ctx);
688 StringRef Version = readString(Ctx);
689 if (!ProducersSeen.insert(Name).second) {
690 return make_error(
691 "Producers section contains repeated producer",
692 object_error::parse_failed);
693 }
694 ProducerVec->emplace_back(Name, Version);
695 }
696 }
697 if (Ctx.Ptr != Ctx.End)
698 return make_error("Producers section ended prematurely",
699 object_error::parse_failed);
700 return Error::success();
701 }
702
661703 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
662704 uint32_t SectionIndex = readVaruint32(Ctx);
663705 if (SectionIndex >= Sections.size())
755797 return Err;
756798 } else if (Sec.Name == "linking") {
757799 if (Error Err = parseLinkingSection(Ctx))
800 return Err;
801 } else if (Sec.Name == "producers") {
802 if (Error Err = parseProducersSection(Ctx))
758803 return Err;
759804 } else if (Sec.Name.startswith("reloc.")) {
760805 if (Error Err = parseRelocSection(Sec.Name, Ctx))
7171 IO.mapOptional("SegmentInfo", Section.SegmentInfos);
7272 IO.mapOptional("InitFunctions", Section.InitFunctions);
7373 IO.mapOptional("Comdats", Section.Comdats);
74 }
75
76 static void sectionMapping(IO &IO, WasmYAML::ProducersSection &Section) {
77 commonSectionMapping(IO, Section);
78 IO.mapRequired("Name", Section.Name);
79 IO.mapOptional("Languages", Section.Languages);
80 IO.mapOptional("Tools", Section.Tools);
81 IO.mapOptional("SDKs", Section.SDKs);
7482 }
7583
7684 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
168176 if (!IO.outputting())
169177 Section.reset(new WasmYAML::NameSection());
170178 sectionMapping(IO, *cast(Section.get()));
179 } else if (SectionName == "producers") {
180 if (!IO.outputting())
181 Section.reset(new WasmYAML::ProducersSection());
182 sectionMapping(IO, *cast(Section.get()));
171183 } else {
172184 if (!IO.outputting())
173185 Section.reset(new WasmYAML::CustomSection(SectionName));
290302 IO &IO, WasmYAML::NameEntry &NameEntry) {
291303 IO.mapRequired("Index", NameEntry.Index);
292304 IO.mapRequired("Name", NameEntry.Name);
305 }
306
307 void MappingTraits::mapping(
308 IO &IO, WasmYAML::ProducerEntry &ProducerEntry) {
309 IO.mapRequired("Name", ProducerEntry.Name);
310 IO.mapRequired("Version", ProducerEntry.Version);
293311 }
294312
295313 void MappingTraits::mapping(
2121 #include "WebAssemblyMCInstLower.h"
2222 #include "WebAssemblyMachineFunctionInfo.h"
2323 #include "WebAssemblyRegisterInfo.h"
24 #include "llvm/ADT/SmallSet.h"
2425 #include "llvm/ADT/StringExtras.h"
2526 #include "llvm/CodeGen/Analysis.h"
2627 #include "llvm/CodeGen/AsmPrinter.h"
144145 OutStreamer->EmitBytes(Contents->getString());
145146 OutStreamer->PopSection();
146147 }
148 }
149
150 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
151 llvm::SmallSet SeenTools;
152 llvm::SmallVector, 4> Tools;
153 for (size_t i = 0, e = Ident->getNumOperands(); i < e; ++i) {
154 const auto *S = cast(Ident->getOperand(i)->getOperand(0));
155 std::pair Field = S->getString().split("version");
156 StringRef Name = Field.first.trim();
157 StringRef Version = Field.second.trim();
158 if (!SeenTools.insert(Name).second)
159 continue;
160 Tools.emplace_back(Name, Version);
161 }
162 MCSectionWasm *Producers = OutContext.getWasmSection(
163 ".custom_section.producers", SectionKind::getMetadata());
164 OutStreamer->PushSection();
165 OutStreamer->SwitchSection(Producers);
166 OutStreamer->EmitULEB128IntValue(1);
167 OutStreamer->EmitULEB128IntValue(strlen("processed-by"));
168 OutStreamer->EmitBytes("processed-by");
169 OutStreamer->EmitULEB128IntValue(Tools.size());
170 for (auto &Tool : Tools) {
171 OutStreamer->EmitULEB128IntValue(Tool.first.size());
172 OutStreamer->EmitBytes(Tool.first);
173 OutStreamer->EmitULEB128IntValue(Tool.second.size());
174 OutStreamer->EmitBytes(Tool.second);
175 }
176 OutStreamer->PopSection();
147177 }
148178 }
149179
99 !2 = !{ !"green", !"qux" }
1010 !wasm.custom_sections = !{ !0, !1, !2 }
1111
12 !llvm.ident = !{!3}
13 !3 = !{!"clang version 123"}
14
1215 ; CHECK: .section .custom_section.red,"",@
1316 ; CHECK-NEXT: .ascii "foo"
1417
1720
1821 ; CHECK: .section .custom_section.green,"",@
1922 ; CHECK-NEXT: .ascii "qux"
23
24 ; CHECK: .section .custom_section.producers,"",@
25 ; CHECK-NEXT: .int8 1
26 ; CHECK-NEXT: .int8 12
27 ; CHECK-NEXT: .ascii "processed-by"
28 ; CHECK-NEXT: .int8 1
29 ; CHECK-NEXT: .int8 5
30 ; CHECK-NEXT: .ascii "clang"
31 ; CHECK-NEXT: .int8 3
32 ; CHECK-NEXT: .ascii "123"
77 !1 = !{ !"green", !"bar" }
88 !2 = !{ !"green", !"qux" }
99 !wasm.custom_sections = !{ !0, !1, !2 }
10
11 !3 = !{ !"clang version 123"}
12 !llvm.ident = !{!3}
1013
1114 ; CHECK: Section {
1215 ; CHECK: Type: CUSTOM (0x0)
2023 ; CHECK: Offset: 85
2124 ; CHECK: Name: green
2225 ; CHECK: }
26 ; CHECK: Section {
27 ; CHECK: Type: CUSTOM (0x0)
28 ; CHECK: Size: 25
29 ; CHECK: Offset: 118
30 ; CHECK: Name: producers
31 ; CHECK: }
122122 ; CHECK-NEXT: Size: 6
123123 ; CHECK-NEXT: Offset: 991
124124 ; CHECK-NEXT: Name: reloc..debug_line
125 ; CHECK-NEXT: }
126 ; CHECK-NEXT: Section {
127 ; CHECK-NEXT: Type: CUSTOM (0x0)
128 ; CHECK-NEXT: Size: 62
129 ; CHECK-NEXT: Offset: 1021
130 ; CHECK-NEXT: Name: producers
125131 ; CHECK-NEXT: }
126132 ; CHECK-NEXT:]
127133 ; CHECK-NEXT:Relocations [
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: CUSTOM
6 Name: producers
7 Languages:
8 - Name: C++
9 Version: C++11
10 Tools:
11 - Name: clang
12 Version: 123
13 SDKs:
14 - Name: emscripten
15 Version: 9001
16 ...
17 # CHECK: Sections:
18 # CHECK: - Type: CUSTOM
19 # CHECK: Name: producers
20 # CHECK: Languages:
21 # CHECK: - Name: 'C++'
22 # CHECK: Version: 'C++11'
23 # CHECK: Tools:
24 # CHECK: - Name: clang
25 # CHECK: Version: '123'
26 # CHECK: SDKs:
27 # CHECK: - Name: emscripten
28 # CHECK: Version: '9001'
0 # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: CUSTOM
6 Name: producers
7 Languages:
8 - Name: C++
9 Version: C++11
10 - Name: C++
11 Version: C++17
12 ...
13 # CHECK: Producers section contains repeated producer
132132 }
133133
134134 CustomSec = std::move(LinkingSec);
135 } else if (WasmSec.Name == "producers") {
136 std::unique_ptr ProducersSec =
137 make_unique();
138 const llvm::wasm::WasmProducerInfo &Info = Obj.getProducerInfo();
139 for (auto &E : Info.Languages) {
140 WasmYAML::ProducerEntry Producer;
141 Producer.Name = E.first;
142 Producer.Version = E.second;
143 ProducersSec->Languages.push_back(Producer);
144 }
145 for (auto &E : Info.Tools) {
146 WasmYAML::ProducerEntry Producer;
147 Producer.Name = E.first;
148 Producer.Version = E.second;
149 ProducersSec->Tools.push_back(Producer);
150 }
151 for (auto &E : Info.SDKs) {
152 WasmYAML::ProducerEntry Producer;
153 Producer.Name = E.first;
154 Producer.Version = E.second;
155 ProducersSec->SDKs.push_back(Producer);
156 }
157 CustomSec = std::move(ProducersSec);
135158 } else {
136159 CustomSec = make_unique(WasmSec.Name);
137160 }
4848 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
4949 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
5050 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
51 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
5152 WasmYAML::Object &Obj;
5253 uint32_t NumImportedFunctions = 0;
5354 uint32_t NumImportedGlobals = 0;
255256 }
256257
257258 int WasmWriter::writeSectionContent(raw_ostream &OS,
259 WasmYAML::ProducersSection &Section) {
260 writeStringRef(Section.Name, OS);
261 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
262 int(!Section.SDKs.empty());
263 if (Fields == 0)
264 return 0;
265 encodeULEB128(Fields, OS);
266 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
267 std::make_pair(StringRef("processed-by"), &Section.Tools),
268 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
269 if (Field.second->empty())
270 continue;
271 writeStringRef(Field.first, OS);
272 encodeULEB128(Field.second->size(), OS);
273 for (auto &Entry : *Field.second) {
274 writeStringRef(Entry.Name, OS);
275 writeStringRef(Entry.Version, OS);
276 }
277 }
278 return 0;
279 }
280
281 int WasmWriter::writeSectionContent(raw_ostream &OS,
258282 WasmYAML::CustomSection &Section) {
259283 if (auto S = dyn_cast(&Section)) {
260284 if (auto Err = writeSectionContent(OS, *S))
263287 if (auto Err = writeSectionContent(OS, *S))
264288 return Err;
265289 } else if (auto S = dyn_cast(&Section)) {
290 if (auto Err = writeSectionContent(OS, *S))
291 return Err;
292 } else if (auto S = dyn_cast(&Section)) {
266293 if (auto Err = writeSectionContent(OS, *S))
267294 return Err;
268295 } else {