[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / tools / obj2yaml / wasm2yaml.cpp
blobc450c02a05ec43b04892dea1d4be976fc11158b1
1 //===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "obj2yaml.h"
10 #include "llvm/Object/COFF.h"
11 #include "llvm/ObjectYAML/WasmYAML.h"
12 #include "llvm/Support/ErrorHandling.h"
13 #include "llvm/Support/LEB128.h"
14 #include "llvm/Support/YAMLTraits.h"
16 using namespace llvm;
17 using object::WasmSection;
19 namespace {
21 class WasmDumper {
22 const object::WasmObjectFile &Obj;
24 public:
25 WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
27 ErrorOr<WasmYAML::Object *> dump();
29 std::unique_ptr<WasmYAML::CustomSection>
30 dumpCustomSection(const WasmSection &WasmSec);
33 } // namespace
35 static WasmYAML::Limits makeLimits(const wasm::WasmLimits &Limits) {
36 WasmYAML::Limits L;
37 L.Flags = Limits.Flags;
38 L.Minimum = Limits.Minimum;
39 L.Maximum = Limits.Maximum;
40 return L;
43 static WasmYAML::Table makeTable(uint32_t Index,
44 const wasm::WasmTableType &Type) {
45 WasmYAML::Table T;
46 T.Index = Index;
47 T.ElemType = Type.ElemType;
48 T.TableLimits = makeLimits(Type.Limits);
49 return T;
52 std::unique_ptr<WasmYAML::CustomSection>
53 WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
54 std::unique_ptr<WasmYAML::CustomSection> CustomSec;
55 if (WasmSec.Name == "dylink" || WasmSec.Name == "dylink.0") {
56 std::unique_ptr<WasmYAML::DylinkSection> DylinkSec =
57 std::make_unique<WasmYAML::DylinkSection>();
58 const wasm::WasmDylinkInfo& Info = Obj.dylinkInfo();
59 DylinkSec->MemorySize = Info.MemorySize;
60 DylinkSec->MemoryAlignment = Info.MemoryAlignment;
61 DylinkSec->TableSize = Info.TableSize;
62 DylinkSec->TableAlignment = Info.TableAlignment;
63 DylinkSec->Needed = Info.Needed;
64 for (const auto &Imp : Info.ImportInfo)
65 DylinkSec->ImportInfo.push_back({Imp.Module, Imp.Field, Imp.Flags});
66 for (const auto &Exp : Info.ExportInfo)
67 DylinkSec->ExportInfo.push_back({Exp.Name, Exp.Flags});
68 CustomSec = std::move(DylinkSec);
69 } else if (WasmSec.Name == "name") {
70 std::unique_ptr<WasmYAML::NameSection> NameSec =
71 std::make_unique<WasmYAML::NameSection>();
72 for (const llvm::wasm::WasmDebugName &Name : Obj.debugNames()) {
73 WasmYAML::NameEntry NameEntry;
74 NameEntry.Name = Name.Name;
75 NameEntry.Index = Name.Index;
76 if (Name.Type == llvm::wasm::NameType::FUNCTION) {
77 NameSec->FunctionNames.push_back(NameEntry);
78 } else if (Name.Type == llvm::wasm::NameType::GLOBAL) {
79 NameSec->GlobalNames.push_back(NameEntry);
80 } else {
81 assert(Name.Type == llvm::wasm::NameType::DATA_SEGMENT);
82 NameSec->DataSegmentNames.push_back(NameEntry);
85 CustomSec = std::move(NameSec);
86 } else if (WasmSec.Name == "linking") {
87 std::unique_ptr<WasmYAML::LinkingSection> LinkingSec =
88 std::make_unique<WasmYAML::LinkingSection>();
89 LinkingSec->Version = Obj.linkingData().Version;
91 ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
92 for (StringRef ComdatName : Comdats)
93 LinkingSec->Comdats.emplace_back(WasmYAML::Comdat{ComdatName, {}});
94 for (auto &Func : Obj.functions()) {
95 if (Func.Comdat != UINT32_MAX) {
96 LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
97 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
101 uint32_t SegmentIndex = 0;
102 for (const object::WasmSegment &Segment : Obj.dataSegments()) {
103 if (!Segment.Data.Name.empty()) {
104 WasmYAML::SegmentInfo SegmentInfo;
105 SegmentInfo.Name = Segment.Data.Name;
106 SegmentInfo.Index = SegmentIndex;
107 SegmentInfo.Alignment = Segment.Data.Alignment;
108 SegmentInfo.Flags = Segment.Data.LinkingFlags;
109 LinkingSec->SegmentInfos.push_back(SegmentInfo);
111 if (Segment.Data.Comdat != UINT32_MAX) {
112 LinkingSec->Comdats[Segment.Data.Comdat].Entries.emplace_back(
113 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
115 SegmentIndex++;
117 uint32_t SectionIndex = 0;
118 for (const auto &Sec : Obj.sections()) {
119 const WasmSection &WasmSec = Obj.getWasmSection(Sec);
120 if (WasmSec.Comdat != UINT32_MAX)
121 LinkingSec->Comdats[WasmSec.Comdat].Entries.emplace_back(
122 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_SECTION, SectionIndex});
123 SectionIndex++;
126 uint32_t SymbolIndex = 0;
127 for (const wasm::WasmSymbolInfo &Symbol : Obj.linkingData().SymbolTable) {
128 WasmYAML::SymbolInfo Info;
129 Info.Index = SymbolIndex++;
130 Info.Kind = static_cast<uint32_t>(Symbol.Kind);
131 Info.Name = Symbol.Name;
132 Info.Flags = Symbol.Flags;
133 switch (Symbol.Kind) {
134 case wasm::WASM_SYMBOL_TYPE_DATA:
135 Info.DataRef = Symbol.DataRef;
136 break;
137 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
138 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
139 case wasm::WASM_SYMBOL_TYPE_TABLE:
140 case wasm::WASM_SYMBOL_TYPE_TAG:
141 Info.ElementIndex = Symbol.ElementIndex;
142 break;
143 case wasm::WASM_SYMBOL_TYPE_SECTION:
144 Info.ElementIndex = Symbol.ElementIndex;
145 break;
147 LinkingSec->SymbolTable.emplace_back(Info);
150 for (const wasm::WasmInitFunc &Func : Obj.linkingData().InitFunctions) {
151 WasmYAML::InitFunction F{Func.Priority, Func.Symbol};
152 LinkingSec->InitFunctions.emplace_back(F);
155 CustomSec = std::move(LinkingSec);
156 } else if (WasmSec.Name == "producers") {
157 std::unique_ptr<WasmYAML::ProducersSection> ProducersSec =
158 std::make_unique<WasmYAML::ProducersSection>();
159 const llvm::wasm::WasmProducerInfo &Info = Obj.getProducerInfo();
160 for (auto &E : Info.Languages) {
161 WasmYAML::ProducerEntry Producer;
162 Producer.Name = E.first;
163 Producer.Version = E.second;
164 ProducersSec->Languages.push_back(Producer);
166 for (auto &E : Info.Tools) {
167 WasmYAML::ProducerEntry Producer;
168 Producer.Name = E.first;
169 Producer.Version = E.second;
170 ProducersSec->Tools.push_back(Producer);
172 for (auto &E : Info.SDKs) {
173 WasmYAML::ProducerEntry Producer;
174 Producer.Name = E.first;
175 Producer.Version = E.second;
176 ProducersSec->SDKs.push_back(Producer);
178 CustomSec = std::move(ProducersSec);
179 } else if (WasmSec.Name == "target_features") {
180 std::unique_ptr<WasmYAML::TargetFeaturesSection> TargetFeaturesSec =
181 std::make_unique<WasmYAML::TargetFeaturesSection>();
182 for (auto &E : Obj.getTargetFeatures()) {
183 WasmYAML::FeatureEntry Feature;
184 Feature.Prefix = E.Prefix;
185 Feature.Name = E.Name;
186 TargetFeaturesSec->Features.push_back(Feature);
188 CustomSec = std::move(TargetFeaturesSec);
189 } else {
190 CustomSec = std::make_unique<WasmYAML::CustomSection>(WasmSec.Name);
192 CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
193 return CustomSec;
196 ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
197 auto Y = std::make_unique<WasmYAML::Object>();
199 // Dump header
200 Y->Header.Version = Obj.getHeader().Version;
202 // Dump sections
203 for (const auto &Sec : Obj.sections()) {
204 const WasmSection &WasmSec = Obj.getWasmSection(Sec);
205 std::unique_ptr<WasmYAML::Section> S;
206 switch (WasmSec.Type) {
207 case wasm::WASM_SEC_CUSTOM: {
208 if (WasmSec.Name.startswith("reloc.")) {
209 // Relocations are attached the sections they apply to rather than
210 // being represented as a custom section in the YAML output.
211 continue;
213 S = dumpCustomSection(WasmSec);
214 break;
216 case wasm::WASM_SEC_TYPE: {
217 auto TypeSec = std::make_unique<WasmYAML::TypeSection>();
218 uint32_t Index = 0;
219 for (const auto &FunctionSig : Obj.types()) {
220 WasmYAML::Signature Sig;
221 Sig.Index = Index++;
222 for (const auto &ParamType : FunctionSig.Params)
223 Sig.ParamTypes.emplace_back(static_cast<uint32_t>(ParamType));
224 for (const auto &ReturnType : FunctionSig.Returns)
225 Sig.ReturnTypes.emplace_back(static_cast<uint32_t>(ReturnType));
226 TypeSec->Signatures.push_back(Sig);
228 S = std::move(TypeSec);
229 break;
231 case wasm::WASM_SEC_IMPORT: {
232 auto ImportSec = std::make_unique<WasmYAML::ImportSection>();
233 for (auto &Import : Obj.imports()) {
234 WasmYAML::Import Im;
235 Im.Module = Import.Module;
236 Im.Field = Import.Field;
237 Im.Kind = Import.Kind;
238 switch (Im.Kind) {
239 case wasm::WASM_EXTERNAL_FUNCTION:
240 Im.SigIndex = Import.SigIndex;
241 break;
242 case wasm::WASM_EXTERNAL_GLOBAL:
243 Im.GlobalImport.Type = Import.Global.Type;
244 Im.GlobalImport.Mutable = Import.Global.Mutable;
245 break;
246 case wasm::WASM_EXTERNAL_TAG:
247 Im.SigIndex = Import.SigIndex;
248 break;
249 case wasm::WASM_EXTERNAL_TABLE:
250 // FIXME: Currently we always output an index of 0 for any imported
251 // table.
252 Im.TableImport = makeTable(0, Import.Table);
253 break;
254 case wasm::WASM_EXTERNAL_MEMORY:
255 Im.Memory = makeLimits(Import.Memory);
256 break;
258 ImportSec->Imports.push_back(Im);
260 S = std::move(ImportSec);
261 break;
263 case wasm::WASM_SEC_FUNCTION: {
264 auto FuncSec = std::make_unique<WasmYAML::FunctionSection>();
265 for (const auto &Func : Obj.functions()) {
266 FuncSec->FunctionTypes.push_back(Func.SigIndex);
268 S = std::move(FuncSec);
269 break;
271 case wasm::WASM_SEC_TABLE: {
272 auto TableSec = std::make_unique<WasmYAML::TableSection>();
273 for (const wasm::WasmTable &Table : Obj.tables()) {
274 TableSec->Tables.push_back(makeTable(Table.Index, Table.Type));
276 S = std::move(TableSec);
277 break;
279 case wasm::WASM_SEC_MEMORY: {
280 auto MemorySec = std::make_unique<WasmYAML::MemorySection>();
281 for (const wasm::WasmLimits &Memory : Obj.memories()) {
282 MemorySec->Memories.push_back(makeLimits(Memory));
284 S = std::move(MemorySec);
285 break;
287 case wasm::WASM_SEC_TAG: {
288 auto TagSec = std::make_unique<WasmYAML::TagSection>();
289 for (auto &Tag : Obj.tags()) {
290 TagSec->TagTypes.push_back(Tag.SigIndex);
292 S = std::move(TagSec);
293 break;
295 case wasm::WASM_SEC_GLOBAL: {
296 auto GlobalSec = std::make_unique<WasmYAML::GlobalSection>();
297 for (auto &Global : Obj.globals()) {
298 WasmYAML::Global G;
299 G.Index = Global.Index;
300 G.Type = Global.Type.Type;
301 G.Mutable = Global.Type.Mutable;
302 G.Init.Extended = Global.InitExpr.Extended;
303 if (Global.InitExpr.Extended) {
304 G.Init.Body = Global.InitExpr.Body;
305 } else {
306 G.Init.Inst = Global.InitExpr.Inst;
308 GlobalSec->Globals.push_back(G);
310 S = std::move(GlobalSec);
311 break;
313 case wasm::WASM_SEC_START: {
314 auto StartSec = std::make_unique<WasmYAML::StartSection>();
315 StartSec->StartFunction = Obj.startFunction();
316 S = std::move(StartSec);
317 break;
319 case wasm::WASM_SEC_EXPORT: {
320 auto ExportSec = std::make_unique<WasmYAML::ExportSection>();
321 for (auto &Export : Obj.exports()) {
322 WasmYAML::Export Ex;
323 Ex.Name = Export.Name;
324 Ex.Kind = Export.Kind;
325 Ex.Index = Export.Index;
326 ExportSec->Exports.push_back(Ex);
328 S = std::move(ExportSec);
329 break;
331 case wasm::WASM_SEC_ELEM: {
332 auto ElemSec = std::make_unique<WasmYAML::ElemSection>();
333 for (auto &Segment : Obj.elements()) {
334 WasmYAML::ElemSegment Seg;
335 Seg.Flags = Segment.Flags;
336 Seg.TableNumber = Segment.TableNumber;
337 Seg.ElemKind = Segment.ElemKind;
338 Seg.Offset.Extended = Segment.Offset.Extended;
339 if (Seg.Offset.Extended) {
340 Seg.Offset.Body = yaml::BinaryRef(Segment.Offset.Body);
341 } else {
342 Seg.Offset.Inst = Segment.Offset.Inst;
344 append_range(Seg.Functions, Segment.Functions);
345 ElemSec->Segments.push_back(Seg);
347 S = std::move(ElemSec);
348 break;
350 case wasm::WASM_SEC_CODE: {
351 auto CodeSec = std::make_unique<WasmYAML::CodeSection>();
352 for (auto &Func : Obj.functions()) {
353 WasmYAML::Function Function;
354 Function.Index = Func.Index;
355 for (auto &Local : Func.Locals) {
356 WasmYAML::LocalDecl LocalDecl;
357 LocalDecl.Type = Local.Type;
358 LocalDecl.Count = Local.Count;
359 Function.Locals.push_back(LocalDecl);
361 Function.Body = yaml::BinaryRef(Func.Body);
362 CodeSec->Functions.push_back(Function);
364 S = std::move(CodeSec);
365 break;
367 case wasm::WASM_SEC_DATA: {
368 auto DataSec = std::make_unique<WasmYAML::DataSection>();
369 for (const object::WasmSegment &Segment : Obj.dataSegments()) {
370 WasmYAML::DataSegment Seg;
371 Seg.SectionOffset = Segment.SectionOffset;
372 Seg.InitFlags = Segment.Data.InitFlags;
373 Seg.MemoryIndex = Segment.Data.MemoryIndex;
374 Seg.Offset.Extended = Segment.Data.Offset.Extended;
375 if (Seg.Offset.Extended) {
376 Seg.Offset.Body = yaml::BinaryRef(Segment.Data.Offset.Body);
377 } else {
378 Seg.Offset.Inst = Segment.Data.Offset.Inst;
380 Seg.Content = yaml::BinaryRef(Segment.Data.Content);
381 DataSec->Segments.push_back(Seg);
383 S = std::move(DataSec);
384 break;
386 case wasm::WASM_SEC_DATACOUNT: {
387 auto DataCountSec = std::make_unique<WasmYAML::DataCountSection>();
388 DataCountSec->Count = Obj.dataSegments().size();
389 S = std::move(DataCountSec);
390 break;
392 default:
393 llvm_unreachable("Unknown section type");
394 break;
397 // Only propagate the section size encoding length if it's not the minimal
398 // size or 5 (the default "padded" value). This is to avoid having every
399 // YAML output polluted with this value when we usually don't care about it
400 // (and avoid rewriting all the test expectations).
401 if (WasmSec.HeaderSecSizeEncodingLen &&
402 WasmSec.HeaderSecSizeEncodingLen !=
403 getULEB128Size(WasmSec.Content.size()) &&
404 WasmSec.HeaderSecSizeEncodingLen != 5)
405 S->HeaderSecSizeEncodingLen = WasmSec.HeaderSecSizeEncodingLen;
407 for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
408 WasmYAML::Relocation R;
409 R.Type = Reloc.Type;
410 R.Index = Reloc.Index;
411 R.Offset = Reloc.Offset;
412 R.Addend = Reloc.Addend;
413 S->Relocations.push_back(R);
415 Y->Sections.push_back(std::move(S));
418 return Y.release();
421 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
422 WasmDumper Dumper(Obj);
423 ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
424 if (std::error_code EC = YAMLOrErr.getError())
425 return EC;
427 std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
428 yaml::Output Yout(Out);
429 Yout << *YAML;
431 return std::error_code();