LLVM  14.0.0git
WasmObjectFile.cpp
Go to the documentation of this file.
1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/ArrayRef.h"
10 #include "llvm/ADT/DenseSet.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallSet.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/StringSet.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/ADT/Triple.h"
17 #include "llvm/BinaryFormat/Wasm.h"
19 #include "llvm/Object/Binary.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Object/Wasm.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/Error.h"
27 #include "llvm/Support/LEB128.h"
29 #include <algorithm>
30 #include <cassert>
31 #include <cstdint>
32 #include <cstring>
33 #include <system_error>
34 
35 #define DEBUG_TYPE "wasm-object"
36 
37 using namespace llvm;
38 using namespace object;
39 
40 void WasmSymbol::print(raw_ostream &Out) const {
41  Out << "Name=" << Info.Name
42  << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
44  if (!isTypeData()) {
45  Out << ", ElemIndex=" << Info.ElementIndex;
46  } else if (isDefined()) {
47  Out << ", Segment=" << Info.DataRef.Segment;
48  Out << ", Offset=" << Info.DataRef.Offset;
49  Out << ", Size=" << Info.DataRef.Size;
50  }
51 }
52 
53 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
55 #endif
56 
59  Error Err = Error::success();
60  auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
61  if (Err)
62  return std::move(Err);
63 
64  return std::move(ObjectFile);
65 }
66 
67 #define VARINT7_MAX ((1 << 7) - 1)
68 #define VARINT7_MIN (-(1 << 7))
69 #define VARUINT7_MAX (1 << 7)
70 #define VARUINT1_MAX (1)
71 
72 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
73  if (Ctx.Ptr == Ctx.End)
74  report_fatal_error("EOF while reading uint8");
75  return *Ctx.Ptr++;
76 }
77 
78 static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
79  if (Ctx.Ptr + 4 > Ctx.End)
80  report_fatal_error("EOF while reading uint32");
81  uint32_t Result = support::endian::read32le(Ctx.Ptr);
82  Ctx.Ptr += 4;
83  return Result;
84 }
85 
86 static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
87  if (Ctx.Ptr + 4 > Ctx.End)
88  report_fatal_error("EOF while reading float64");
89  int32_t Result = 0;
90  memcpy(&Result, Ctx.Ptr, sizeof(Result));
91  Ctx.Ptr += sizeof(Result);
92  return Result;
93 }
94 
95 static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
96  if (Ctx.Ptr + 8 > Ctx.End)
97  report_fatal_error("EOF while reading float64");
98  int64_t Result = 0;
99  memcpy(&Result, Ctx.Ptr, sizeof(Result));
100  Ctx.Ptr += sizeof(Result);
101  return Result;
102 }
103 
104 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
105  unsigned Count;
106  const char *Error = nullptr;
107  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
108  if (Error)
110  Ctx.Ptr += Count;
111  return Result;
112 }
113 
114 static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
115  uint32_t StringLen = readULEB128(Ctx);
116  if (Ctx.Ptr + StringLen > Ctx.End)
117  report_fatal_error("EOF while reading string");
118  StringRef Return =
119  StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
120  Ctx.Ptr += StringLen;
121  return Return;
122 }
123 
124 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
125  unsigned Count;
126  const char *Error = nullptr;
127  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
128  if (Error)
130  Ctx.Ptr += Count;
131  return Result;
132 }
133 
134 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
135  int64_t Result = readLEB128(Ctx);
136  if (Result > VARUINT1_MAX || Result < 0)
137  report_fatal_error("LEB is outside Varuint1 range");
138  return Result;
139 }
140 
141 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
142  int64_t Result = readLEB128(Ctx);
143  if (Result > INT32_MAX || Result < INT32_MIN)
144  report_fatal_error("LEB is outside Varint32 range");
145  return Result;
146 }
147 
148 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
149  uint64_t Result = readULEB128(Ctx);
150  if (Result > UINT32_MAX)
151  report_fatal_error("LEB is outside Varuint32 range");
152  return Result;
153 }
154 
155 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
156  return readLEB128(Ctx);
157 }
158 
159 static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
160  return readULEB128(Ctx);
161 }
162 
163 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
164  return readUint8(Ctx);
165 }
166 
168  WasmObjectFile::ReadContext &Ctx) {
169  Expr.Opcode = readOpcode(Ctx);
170 
171  switch (Expr.Opcode) {
173  Expr.Value.Int32 = readVarint32(Ctx);
174  break;
176  Expr.Value.Int64 = readVarint64(Ctx);
177  break;
179  Expr.Value.Float32 = readFloat32(Ctx);
180  break;
182  Expr.Value.Float64 = readFloat64(Ctx);
183  break;
185  Expr.Value.Global = readULEB128(Ctx);
186  break;
188  wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
189  if (Ty != wasm::ValType::EXTERNREF) {
190  return make_error<GenericBinaryError>("invalid type for ref.null",
192  }
193  break;
194  }
195  default:
196  return make_error<GenericBinaryError>("invalid opcode in init_expr",
198  }
199 
200  uint8_t EndOpcode = readOpcode(Ctx);
201  if (EndOpcode != wasm::WASM_OPCODE_END) {
202  return make_error<GenericBinaryError>("invalid init_expr",
204  }
205  return Error::success();
206 }
207 
208 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
209  wasm::WasmLimits Result;
210  Result.Flags = readVaruint32(Ctx);
211  Result.Minimum = readVaruint64(Ctx);
212  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
213  Result.Maximum = readVaruint64(Ctx);
214  return Result;
215 }
216 
217 static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
218  wasm::WasmTableType TableType;
219  TableType.ElemType = readUint8(Ctx);
220  TableType.Limits = readLimits(Ctx);
221  return TableType;
222 }
223 
224 static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
225  WasmSectionOrderChecker &Checker) {
226  Section.Offset = Ctx.Ptr - Ctx.Start;
227  Section.Type = readUint8(Ctx);
228  LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
229  uint32_t Size = readVaruint32(Ctx);
230  if (Size == 0)
231  return make_error<StringError>("zero length section",
233  if (Ctx.Ptr + Size > Ctx.End)
234  return make_error<StringError>("section too large",
236  if (Section.Type == wasm::WASM_SEC_CUSTOM) {
237  WasmObjectFile::ReadContext SectionCtx;
238  SectionCtx.Start = Ctx.Ptr;
239  SectionCtx.Ptr = Ctx.Ptr;
240  SectionCtx.End = Ctx.Ptr + Size;
241 
242  Section.Name = readString(SectionCtx);
243 
244  uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
245  Ctx.Ptr += SectionNameSize;
246  Size -= SectionNameSize;
247  }
248 
249  if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
250  return make_error<StringError>("out of order section type: " +
251  llvm::to_string(Section.Type),
253  }
254 
255  Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
256  Ctx.Ptr += Size;
257  return Error::success();
258 }
259 
261  : ObjectFile(Binary::ID_Wasm, Buffer) {
262  ErrorAsOutParameter ErrAsOutParam(&Err);
263  Header.Magic = getData().substr(0, 4);
264  if (Header.Magic != StringRef("\0asm", 4)) {
265  Err = make_error<StringError>("invalid magic number",
267  return;
268  }
269 
270  ReadContext Ctx;
271  Ctx.Start = getData().bytes_begin();
272  Ctx.Ptr = Ctx.Start + 4;
273  Ctx.End = Ctx.Start + getData().size();
274 
275  if (Ctx.Ptr + 4 > Ctx.End) {
276  Err = make_error<StringError>("missing version number",
278  return;
279  }
280 
281  Header.Version = readUint32(Ctx);
282  if (Header.Version != wasm::WasmVersion) {
283  Err = make_error<StringError>("invalid version number: " +
284  Twine(Header.Version),
286  return;
287  }
288 
289  WasmSection Sec;
290  WasmSectionOrderChecker Checker;
291  while (Ctx.Ptr < Ctx.End) {
292  if ((Err = readSection(Sec, Ctx, Checker)))
293  return;
294  if ((Err = parseSection(Sec)))
295  return;
296 
297  Sections.push_back(Sec);
298  }
299 }
300 
301 Error WasmObjectFile::parseSection(WasmSection &Sec) {
302  ReadContext Ctx;
303  Ctx.Start = Sec.Content.data();
304  Ctx.End = Ctx.Start + Sec.Content.size();
305  Ctx.Ptr = Ctx.Start;
306  switch (Sec.Type) {
308  return parseCustomSection(Sec, Ctx);
309  case wasm::WASM_SEC_TYPE:
310  return parseTypeSection(Ctx);
312  return parseImportSection(Ctx);
314  return parseFunctionSection(Ctx);
316  return parseTableSection(Ctx);
318  return parseMemorySection(Ctx);
319  case wasm::WASM_SEC_TAG:
320  return parseTagSection(Ctx);
322  return parseGlobalSection(Ctx);
324  return parseExportSection(Ctx);
326  return parseStartSection(Ctx);
327  case wasm::WASM_SEC_ELEM:
328  return parseElemSection(Ctx);
329  case wasm::WASM_SEC_CODE:
330  return parseCodeSection(Ctx);
331  case wasm::WASM_SEC_DATA:
332  return parseDataSection(Ctx);
334  return parseDataCountSection(Ctx);
335  default:
336  return make_error<GenericBinaryError>(
337  "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
338  }
339 }
340 
341 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
342  // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
343  HasDylinkSection = true;
344  DylinkInfo.MemorySize = readVaruint32(Ctx);
345  DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
346  DylinkInfo.TableSize = readVaruint32(Ctx);
347  DylinkInfo.TableAlignment = readVaruint32(Ctx);
348  uint32_t Count = readVaruint32(Ctx);
349  while (Count--) {
350  DylinkInfo.Needed.push_back(readString(Ctx));
351  }
352  if (Ctx.Ptr != Ctx.End)
353  return make_error<GenericBinaryError>("dylink section ended prematurely",
355  return Error::success();
356 }
357 
358 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
359  llvm::DenseSet<uint64_t> SeenFunctions;
360  llvm::DenseSet<uint64_t> SeenGlobals;
361  llvm::DenseSet<uint64_t> SeenSegments;
362  if (FunctionTypes.size() && !SeenCodeSection) {
363  return make_error<GenericBinaryError>("names must come after code section",
365  }
366 
367  while (Ctx.Ptr < Ctx.End) {
368  uint8_t Type = readUint8(Ctx);
369  uint32_t Size = readVaruint32(Ctx);
370  const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
371  switch (Type) {
375  uint32_t Count = readVaruint32(Ctx);
376  while (Count--) {
378  StringRef Name = readString(Ctx);
381  if (!SeenFunctions.insert(Index).second)
382  return make_error<GenericBinaryError>(
383  "function named more than once", object_error::parse_failed);
384  if (!isValidFunctionIndex(Index) || Name.empty())
385  return make_error<GenericBinaryError>("invalid name entry",
387 
388  if (isDefinedFunctionIndex(Index))
389  getDefinedFunction(Index).DebugName = Name;
390  } else if (Type == wasm::WASM_NAMES_GLOBAL) {
391  nameType = wasm::NameType::GLOBAL;
392  if (!SeenGlobals.insert(Index).second)
393  return make_error<GenericBinaryError>("global named more than once",
395  if (!isValidGlobalIndex(Index) || Name.empty())
396  return make_error<GenericBinaryError>("invalid name entry",
398  } else {
399  nameType = wasm::NameType::DATA_SEGMENT;
400  if (!SeenSegments.insert(Index).second)
401  return make_error<GenericBinaryError>(
402  "segment named more than once", object_error::parse_failed);
403  if (Index > DataSegments.size())
404  return make_error<GenericBinaryError>("invalid named data segment",
406  }
407  DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
408  }
409  break;
410  }
411  // Ignore local names for now
413  default:
414  Ctx.Ptr += Size;
415  break;
416  }
417  if (Ctx.Ptr != SubSectionEnd)
418  return make_error<GenericBinaryError>(
419  "name sub-section ended prematurely", object_error::parse_failed);
420  }
421 
422  if (Ctx.Ptr != Ctx.End)
423  return make_error<GenericBinaryError>("name section ended prematurely",
425  return Error::success();
426 }
427 
428 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
429  HasLinkingSection = true;
430  if (FunctionTypes.size() && !SeenCodeSection) {
431  return make_error<GenericBinaryError>(
432  "linking data must come after code section",
434  }
435 
436  LinkingData.Version = readVaruint32(Ctx);
437  if (LinkingData.Version != wasm::WasmMetadataVersion) {
438  return make_error<GenericBinaryError>(
439  "unexpected metadata version: " + Twine(LinkingData.Version) +
440  " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
442  }
443 
444  const uint8_t *OrigEnd = Ctx.End;
445  while (Ctx.Ptr < OrigEnd) {
446  Ctx.End = OrigEnd;
447  uint8_t Type = readUint8(Ctx);
448  uint32_t Size = readVaruint32(Ctx);
449  LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
450  << "\n");
451  Ctx.End = Ctx.Ptr + Size;
452  switch (Type) {
454  if (Error Err = parseLinkingSectionSymtab(Ctx))
455  return Err;
456  break;
458  uint32_t Count = readVaruint32(Ctx);
459  if (Count > DataSegments.size())
460  return make_error<GenericBinaryError>("too many segment names",
462  for (uint32_t I = 0; I < Count; I++) {
463  DataSegments[I].Data.Name = readString(Ctx);
464  DataSegments[I].Data.Alignment = readVaruint32(Ctx);
465  DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
466  }
467  break;
468  }
469  case wasm::WASM_INIT_FUNCS: {
470  uint32_t Count = readVaruint32(Ctx);
471  LinkingData.InitFunctions.reserve(Count);
472  for (uint32_t I = 0; I < Count; I++) {
474  Init.Priority = readVaruint32(Ctx);
475  Init.Symbol = readVaruint32(Ctx);
476  if (!isValidFunctionSymbol(Init.Symbol))
477  return make_error<GenericBinaryError>("invalid function symbol: " +
478  Twine(Init.Symbol),
480  LinkingData.InitFunctions.emplace_back(Init);
481  }
482  break;
483  }
485  if (Error Err = parseLinkingSectionComdat(Ctx))
486  return Err;
487  break;
488  default:
489  Ctx.Ptr += Size;
490  break;
491  }
492  if (Ctx.Ptr != Ctx.End)
493  return make_error<GenericBinaryError>(
494  "linking sub-section ended prematurely", object_error::parse_failed);
495  }
496  if (Ctx.Ptr != OrigEnd)
497  return make_error<GenericBinaryError>("linking section ended prematurely",
499  return Error::success();
500 }
501 
502 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
503  uint32_t Count = readVaruint32(Ctx);
504  LinkingData.SymbolTable.reserve(Count);
505  Symbols.reserve(Count);
506  StringSet<> SymbolNames;
507 
508  std::vector<wasm::WasmImport *> ImportedGlobals;
509  std::vector<wasm::WasmImport *> ImportedFunctions;
510  std::vector<wasm::WasmImport *> ImportedTags;
511  std::vector<wasm::WasmImport *> ImportedTables;
512  ImportedGlobals.reserve(Imports.size());
513  ImportedFunctions.reserve(Imports.size());
514  ImportedTags.reserve(Imports.size());
515  ImportedTables.reserve(Imports.size());
516  for (auto &I : Imports) {
517  if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
518  ImportedFunctions.emplace_back(&I);
519  else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
520  ImportedGlobals.emplace_back(&I);
521  else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
522  ImportedTags.emplace_back(&I);
523  else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
524  ImportedTables.emplace_back(&I);
525  }
526 
527  while (Count--) {
529  const wasm::WasmSignature *Signature = nullptr;
530  const wasm::WasmGlobalType *GlobalType = nullptr;
531  const wasm::WasmTableType *TableType = nullptr;
532  const wasm::WasmTagType *TagType = nullptr;
533 
534  Info.Kind = readUint8(Ctx);
535  Info.Flags = readVaruint32(Ctx);
536  bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
537 
538  switch (Info.Kind) {
540  Info.ElementIndex = readVaruint32(Ctx);
541  if (!isValidFunctionIndex(Info.ElementIndex) ||
542  IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
543  return make_error<GenericBinaryError>("invalid function symbol index",
545  if (IsDefined) {
546  Info.Name = readString(Ctx);
547  unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
548  Signature = &Signatures[FunctionTypes[FuncIndex]];
549  wasm::WasmFunction &Function = Functions[FuncIndex];
550  if (Function.SymbolName.empty())
551  Function.SymbolName = Info.Name;
552  } else {
553  wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
554  if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
555  Info.Name = readString(Ctx);
556  Info.ImportName = Import.Field;
557  } else {
558  Info.Name = Import.Field;
559  }
560  Signature = &Signatures[Import.SigIndex];
561  if (!Import.Module.empty()) {
562  Info.ImportModule = Import.Module;
563  }
564  }
565  break;
566 
568  Info.ElementIndex = readVaruint32(Ctx);
569  if (!isValidGlobalIndex(Info.ElementIndex) ||
570  IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
571  return make_error<GenericBinaryError>("invalid global symbol index",
573  if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
575  return make_error<GenericBinaryError>("undefined weak global symbol",
577  if (IsDefined) {
578  Info.Name = readString(Ctx);
579  unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
580  wasm::WasmGlobal &Global = Globals[GlobalIndex];
581  GlobalType = &Global.Type;
582  if (Global.SymbolName.empty())
583  Global.SymbolName = Info.Name;
584  } else {
585  wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
586  if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
587  Info.Name = readString(Ctx);
588  Info.ImportName = Import.Field;
589  } else {
590  Info.Name = Import.Field;
591  }
592  GlobalType = &Import.Global;
593  if (!Import.Module.empty()) {
594  Info.ImportModule = Import.Module;
595  }
596  }
597  break;
598 
600  Info.ElementIndex = readVaruint32(Ctx);
601  if (!isValidTableNumber(Info.ElementIndex) ||
602  IsDefined != isDefinedTableNumber(Info.ElementIndex))
603  return make_error<GenericBinaryError>("invalid table symbol index",
605  if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
607  return make_error<GenericBinaryError>("undefined weak table symbol",
609  if (IsDefined) {
610  Info.Name = readString(Ctx);
611  unsigned TableNumber = Info.ElementIndex - NumImportedTables;
612  wasm::WasmTable &Table = Tables[TableNumber];
613  TableType = &Table.Type;
614  if (Table.SymbolName.empty())
615  Table.SymbolName = Info.Name;
616  } else {
617  wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
618  if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
619  Info.Name = readString(Ctx);
620  Info.ImportName = Import.Field;
621  } else {
622  Info.Name = Import.Field;
623  }
624  TableType = &Import.Table;
625  if (!Import.Module.empty()) {
626  Info.ImportModule = Import.Module;
627  }
628  }
629  break;
630 
632  Info.Name = readString(Ctx);
633  if (IsDefined) {
634  auto Index = readVaruint32(Ctx);
635  if (Index >= DataSegments.size())
636  return make_error<GenericBinaryError>("invalid data symbol index",
638  auto Offset = readVaruint64(Ctx);
639  auto Size = readVaruint64(Ctx);
640  size_t SegmentSize = DataSegments[Index].Data.Content.size();
641  if (Offset > SegmentSize)
642  return make_error<GenericBinaryError>(
643  "invalid data symbol offset: `" + Info.Name + "` (offset: " +
644  Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
647  }
648  break;
649 
651  if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
653  return make_error<GenericBinaryError>(
654  "section symbols must have local binding",
656  Info.ElementIndex = readVaruint32(Ctx);
657  // Use somewhat unique section name as symbol name.
658  StringRef SectionName = Sections[Info.ElementIndex].Name;
659  Info.Name = SectionName;
660  break;
661  }
662 
664  Info.ElementIndex = readVaruint32(Ctx);
665  if (!isValidTagIndex(Info.ElementIndex) ||
666  IsDefined != isDefinedTagIndex(Info.ElementIndex))
667  return make_error<GenericBinaryError>("invalid tag symbol index",
669  if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
671  return make_error<GenericBinaryError>("undefined weak global symbol",
673  if (IsDefined) {
674  Info.Name = readString(Ctx);
675  unsigned TagIndex = Info.ElementIndex - NumImportedTags;
676  wasm::WasmTag &Tag = Tags[TagIndex];
677  Signature = &Signatures[Tag.Type.SigIndex];
678  TagType = &Tag.Type;
679  if (Tag.SymbolName.empty())
680  Tag.SymbolName = Info.Name;
681 
682  } else {
683  wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
684  if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
685  Info.Name = readString(Ctx);
686  Info.ImportName = Import.Field;
687  } else {
688  Info.Name = Import.Field;
689  }
690  TagType = &Import.Tag;
691  Signature = &Signatures[TagType->SigIndex];
692  if (!Import.Module.empty()) {
693  Info.ImportModule = Import.Module;
694  }
695  }
696  break;
697  }
698 
699  default:
700  return make_error<GenericBinaryError>("invalid symbol type: " +
701  Twine(unsigned(Info.Kind)),
703  }
704 
705  if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
707  !SymbolNames.insert(Info.Name).second)
708  return make_error<GenericBinaryError>("duplicate symbol name " +
709  Twine(Info.Name),
711  LinkingData.SymbolTable.emplace_back(Info);
712  Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
713  TagType, Signature);
714  LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
715  }
716 
717  return Error::success();
718 }
719 
720 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
721  uint32_t ComdatCount = readVaruint32(Ctx);
722  StringSet<> ComdatSet;
723  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
724  StringRef Name = readString(Ctx);
725  if (Name.empty() || !ComdatSet.insert(Name).second)
726  return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
727  Twine(Name),
729  LinkingData.Comdats.emplace_back(Name);
730  uint32_t Flags = readVaruint32(Ctx);
731  if (Flags != 0)
732  return make_error<GenericBinaryError>("unsupported COMDAT flags",
734 
735  uint32_t EntryCount = readVaruint32(Ctx);
736  while (EntryCount--) {
737  unsigned Kind = readVaruint32(Ctx);
738  unsigned Index = readVaruint32(Ctx);
739  switch (Kind) {
740  default:
741  return make_error<GenericBinaryError>("invalid COMDAT entry type",
744  if (Index >= DataSegments.size())
745  return make_error<GenericBinaryError>(
746  "COMDAT data index out of range", object_error::parse_failed);
747  if (DataSegments[Index].Data.Comdat != UINT32_MAX)
748  return make_error<GenericBinaryError>("data segment in two COMDATs",
750  DataSegments[Index].Data.Comdat = ComdatIndex;
751  break;
753  if (!isDefinedFunctionIndex(Index))
754  return make_error<GenericBinaryError>(
755  "COMDAT function index out of range", object_error::parse_failed);
756  if (getDefinedFunction(Index).Comdat != UINT32_MAX)
757  return make_error<GenericBinaryError>("function in two COMDATs",
759  getDefinedFunction(Index).Comdat = ComdatIndex;
760  break;
762  if (Index >= Sections.size())
763  return make_error<GenericBinaryError>(
764  "COMDAT section index out of range", object_error::parse_failed);
765  if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
766  return make_error<GenericBinaryError>(
767  "non-custom section in a COMDAT", object_error::parse_failed);
768  Sections[Index].Comdat = ComdatIndex;
769  break;
770  }
771  }
772  }
773  return Error::success();
774 }
775 
776 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
777  llvm::SmallSet<StringRef, 3> FieldsSeen;
778  uint32_t Fields = readVaruint32(Ctx);
779  for (size_t I = 0; I < Fields; ++I) {
780  StringRef FieldName = readString(Ctx);
781  if (!FieldsSeen.insert(FieldName).second)
782  return make_error<GenericBinaryError>(
783  "producers section does not have unique fields",
785  std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
786  if (FieldName == "language") {
787  ProducerVec = &ProducerInfo.Languages;
788  } else if (FieldName == "processed-by") {
789  ProducerVec = &ProducerInfo.Tools;
790  } else if (FieldName == "sdk") {
791  ProducerVec = &ProducerInfo.SDKs;
792  } else {
793  return make_error<GenericBinaryError>(
794  "producers section field is not named one of language, processed-by, "
795  "or sdk",
797  }
798  uint32_t ValueCount = readVaruint32(Ctx);
799  llvm::SmallSet<StringRef, 8> ProducersSeen;
800  for (size_t J = 0; J < ValueCount; ++J) {
801  StringRef Name = readString(Ctx);
803  if (!ProducersSeen.insert(Name).second) {
804  return make_error<GenericBinaryError>(
805  "producers section contains repeated producer",
807  }
808  ProducerVec->emplace_back(std::string(Name), std::string(Version));
809  }
810  }
811  if (Ctx.Ptr != Ctx.End)
812  return make_error<GenericBinaryError>("producers section ended prematurely",
814  return Error::success();
815 }
816 
817 Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
818  llvm::SmallSet<std::string, 8> FeaturesSeen;
819  uint32_t FeatureCount = readVaruint32(Ctx);
820  for (size_t I = 0; I < FeatureCount; ++I) {
821  wasm::WasmFeatureEntry Feature;
822  Feature.Prefix = readUint8(Ctx);
823  switch (Feature.Prefix) {
827  break;
828  default:
829  return make_error<GenericBinaryError>("unknown feature policy prefix",
831  }
832  Feature.Name = std::string(readString(Ctx));
833  if (!FeaturesSeen.insert(Feature.Name).second)
834  return make_error<GenericBinaryError>(
835  "target features section contains repeated feature \"" +
836  Feature.Name + "\"",
838  TargetFeatures.push_back(Feature);
839  }
840  if (Ctx.Ptr != Ctx.End)
841  return make_error<GenericBinaryError>(
842  "target features section ended prematurely",
844  return Error::success();
845 }
846 
847 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
848  uint32_t SectionIndex = readVaruint32(Ctx);
849  if (SectionIndex >= Sections.size())
850  return make_error<GenericBinaryError>("invalid section index",
852  WasmSection &Section = Sections[SectionIndex];
853  uint32_t RelocCount = readVaruint32(Ctx);
854  uint32_t EndOffset = Section.Content.size();
855  uint32_t PreviousOffset = 0;
856  while (RelocCount--) {
857  wasm::WasmRelocation Reloc = {};
858  uint32_t type = readVaruint32(Ctx);
859  Reloc.Type = type;
860  Reloc.Offset = readVaruint32(Ctx);
861  if (Reloc.Offset < PreviousOffset)
862  return make_error<GenericBinaryError>("relocations not in offset order",
864  PreviousOffset = Reloc.Offset;
865  Reloc.Index = readVaruint32(Ctx);
866  switch (type) {
867  case wasm::R_WASM_FUNCTION_INDEX_LEB:
868  case wasm::R_WASM_TABLE_INDEX_SLEB:
869  case wasm::R_WASM_TABLE_INDEX_SLEB64:
870  case wasm::R_WASM_TABLE_INDEX_I32:
871  case wasm::R_WASM_TABLE_INDEX_I64:
872  case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
873  case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
874  if (!isValidFunctionSymbol(Reloc.Index))
875  return make_error<GenericBinaryError>(
876  "invalid relocation function index", object_error::parse_failed);
877  break;
878  case wasm::R_WASM_TABLE_NUMBER_LEB:
879  if (!isValidTableSymbol(Reloc.Index))
880  return make_error<GenericBinaryError>("invalid relocation table index",
882  break;
883  case wasm::R_WASM_TYPE_INDEX_LEB:
884  if (Reloc.Index >= Signatures.size())
885  return make_error<GenericBinaryError>("invalid relocation type index",
887  break;
888  case wasm::R_WASM_GLOBAL_INDEX_LEB:
889  // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
890  // symbols to refer to their GOT entries.
891  if (!isValidGlobalSymbol(Reloc.Index) &&
892  !isValidDataSymbol(Reloc.Index) &&
893  !isValidFunctionSymbol(Reloc.Index))
894  return make_error<GenericBinaryError>("invalid relocation global index",
896  break;
897  case wasm::R_WASM_GLOBAL_INDEX_I32:
898  if (!isValidGlobalSymbol(Reloc.Index))
899  return make_error<GenericBinaryError>("invalid relocation global index",
901  break;
902  case wasm::R_WASM_TAG_INDEX_LEB:
903  if (!isValidTagSymbol(Reloc.Index))
904  return make_error<GenericBinaryError>("invalid relocation tag index",
906  break;
907  case wasm::R_WASM_MEMORY_ADDR_LEB:
908  case wasm::R_WASM_MEMORY_ADDR_SLEB:
909  case wasm::R_WASM_MEMORY_ADDR_I32:
910  case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
911  case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
912  case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
913  if (!isValidDataSymbol(Reloc.Index))
914  return make_error<GenericBinaryError>("invalid relocation data index",
916  Reloc.Addend = readVarint32(Ctx);
917  break;
918  case wasm::R_WASM_MEMORY_ADDR_LEB64:
919  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
920  case wasm::R_WASM_MEMORY_ADDR_I64:
921  case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
922  case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
923  if (!isValidDataSymbol(Reloc.Index))
924  return make_error<GenericBinaryError>("invalid relocation data index",
926  Reloc.Addend = readVarint64(Ctx);
927  break;
928  case wasm::R_WASM_FUNCTION_OFFSET_I32:
929  if (!isValidFunctionSymbol(Reloc.Index))
930  return make_error<GenericBinaryError>(
931  "invalid relocation function index", object_error::parse_failed);
932  Reloc.Addend = readVarint32(Ctx);
933  break;
934  case wasm::R_WASM_FUNCTION_OFFSET_I64:
935  if (!isValidFunctionSymbol(Reloc.Index))
936  return make_error<GenericBinaryError>(
937  "invalid relocation function index", object_error::parse_failed);
938  Reloc.Addend = readVarint64(Ctx);
939  break;
940  case wasm::R_WASM_SECTION_OFFSET_I32:
941  if (!isValidSectionSymbol(Reloc.Index))
942  return make_error<GenericBinaryError>(
943  "invalid relocation section index", object_error::parse_failed);
944  Reloc.Addend = readVarint32(Ctx);
945  break;
946  default:
947  return make_error<GenericBinaryError>("invalid relocation type: " +
948  Twine(type),
950  }
951 
952  // Relocations must fit inside the section, and must appear in order. They
953  // also shouldn't overlap a function/element boundary, but we don't bother
954  // to check that.
955  uint64_t Size = 5;
956  if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
957  Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
958  Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
959  Size = 10;
960  if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
961  Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
962  Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
963  Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
964  Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
965  Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
966  Size = 4;
967  if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
968  Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
969  Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
970  Size = 8;
971  if (Reloc.Offset + Size > EndOffset)
972  return make_error<GenericBinaryError>("invalid relocation offset",
974 
975  Section.Relocations.push_back(Reloc);
976  }
977  if (Ctx.Ptr != Ctx.End)
978  return make_error<GenericBinaryError>("reloc section ended prematurely",
980  return Error::success();
981 }
982 
983 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
984  if (Sec.Name == "dylink") {
985  if (Error Err = parseDylinkSection(Ctx))
986  return Err;
987  } else if (Sec.Name == "name") {
988  if (Error Err = parseNameSection(Ctx))
989  return Err;
990  } else if (Sec.Name == "linking") {
991  if (Error Err = parseLinkingSection(Ctx))
992  return Err;
993  } else if (Sec.Name == "producers") {
994  if (Error Err = parseProducersSection(Ctx))
995  return Err;
996  } else if (Sec.Name == "target_features") {
997  if (Error Err = parseTargetFeaturesSection(Ctx))
998  return Err;
999  } else if (Sec.Name.startswith("reloc.")) {
1000  if (Error Err = parseRelocSection(Sec.Name, Ctx))
1001  return Err;
1002  }
1003  return Error::success();
1004 }
1005 
1006 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1007  uint32_t Count = readVaruint32(Ctx);
1008  Signatures.reserve(Count);
1009  while (Count--) {
1010  wasm::WasmSignature Sig;
1011  uint8_t Form = readUint8(Ctx);
1012  if (Form != wasm::WASM_TYPE_FUNC) {
1013  return make_error<GenericBinaryError>("invalid signature type",
1015  }
1016  uint32_t ParamCount = readVaruint32(Ctx);
1017  Sig.Params.reserve(ParamCount);
1018  while (ParamCount--) {
1019  uint32_t ParamType = readUint8(Ctx);
1020  Sig.Params.push_back(wasm::ValType(ParamType));
1021  }
1022  uint32_t ReturnCount = readVaruint32(Ctx);
1023  while (ReturnCount--) {
1024  uint32_t ReturnType = readUint8(Ctx);
1025  Sig.Returns.push_back(wasm::ValType(ReturnType));
1026  }
1027  Signatures.push_back(std::move(Sig));
1028  }
1029  if (Ctx.Ptr != Ctx.End)
1030  return make_error<GenericBinaryError>("type section ended prematurely",
1032  return Error::success();
1033 }
1034 
1035 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1036  uint32_t Count = readVaruint32(Ctx);
1037  Imports.reserve(Count);
1038  for (uint32_t I = 0; I < Count; I++) {
1039  wasm::WasmImport Im;
1040  Im.Module = readString(Ctx);
1041  Im.Field = readString(Ctx);
1042  Im.Kind = readUint8(Ctx);
1043  switch (Im.Kind) {
1045  NumImportedFunctions++;
1046  Im.SigIndex = readVaruint32(Ctx);
1047  break;
1049  NumImportedGlobals++;
1050  Im.Global.Type = readUint8(Ctx);
1051  Im.Global.Mutable = readVaruint1(Ctx);
1052  break;
1054  Im.Memory = readLimits(Ctx);
1056  HasMemory64 = true;
1057  break;
1059  Im.Table = readTableType(Ctx);
1060  NumImportedTables++;
1061  auto ElemType = Im.Table.ElemType;
1062  if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1063  ElemType != wasm::WASM_TYPE_EXTERNREF)
1064  return make_error<GenericBinaryError>("invalid table element type",
1066  break;
1067  }
1069  NumImportedTags++;
1070  Im.Tag.Attribute = readUint8(Ctx);
1071  Im.Tag.SigIndex = readVarint32(Ctx);
1072  break;
1073  default:
1074  return make_error<GenericBinaryError>("unexpected import kind",
1076  }
1077  Imports.push_back(Im);
1078  }
1079  if (Ctx.Ptr != Ctx.End)
1080  return make_error<GenericBinaryError>("import section ended prematurely",
1082  return Error::success();
1083 }
1084 
1085 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1086  uint32_t Count = readVaruint32(Ctx);
1087  FunctionTypes.reserve(Count);
1088  Functions.resize(Count);
1089  uint32_t NumTypes = Signatures.size();
1090  while (Count--) {
1091  uint32_t Type = readVaruint32(Ctx);
1092  if (Type >= NumTypes)
1093  return make_error<GenericBinaryError>("invalid function type",
1095  FunctionTypes.push_back(Type);
1096  }
1097  if (Ctx.Ptr != Ctx.End)
1098  return make_error<GenericBinaryError>("function section ended prematurely",
1100  return Error::success();
1101 }
1102 
1103 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1104  TableSection = Sections.size();
1105  uint32_t Count = readVaruint32(Ctx);
1106  Tables.reserve(Count);
1107  while (Count--) {
1109  T.Type = readTableType(Ctx);
1110  T.Index = NumImportedTables + Tables.size();
1111  Tables.push_back(T);
1112  auto ElemType = Tables.back().Type.ElemType;
1113  if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1114  ElemType != wasm::WASM_TYPE_EXTERNREF) {
1115  return make_error<GenericBinaryError>("invalid table element type",
1117  }
1118  }
1119  if (Ctx.Ptr != Ctx.End)
1120  return make_error<GenericBinaryError>("table section ended prematurely",
1122  return Error::success();
1123 }
1124 
1125 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1126  uint32_t Count = readVaruint32(Ctx);
1127  Memories.reserve(Count);
1128  while (Count--) {
1129  auto Limits = readLimits(Ctx);
1130  if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1131  HasMemory64 = true;
1132  Memories.push_back(Limits);
1133  }
1134  if (Ctx.Ptr != Ctx.End)
1135  return make_error<GenericBinaryError>("memory section ended prematurely",
1137  return Error::success();
1138 }
1139 
1140 Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1141  TagSection = Sections.size();
1142  uint32_t Count = readVaruint32(Ctx);
1143  Tags.reserve(Count);
1144  while (Count--) {
1146  Tag.Index = NumImportedTags + Tags.size();
1147  Tag.Type.Attribute = readUint8(Ctx);
1148  Tag.Type.SigIndex = readVaruint32(Ctx);
1149  Tags.push_back(Tag);
1150  }
1151 
1152  if (Ctx.Ptr != Ctx.End)
1153  return make_error<GenericBinaryError>("tag section ended prematurely",
1155  return Error::success();
1156 }
1157 
1158 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1159  GlobalSection = Sections.size();
1160  uint32_t Count = readVaruint32(Ctx);
1161  Globals.reserve(Count);
1162  while (Count--) {
1164  Global.Index = NumImportedGlobals + Globals.size();
1165  Global.Type.Type = readUint8(Ctx);
1166  Global.Type.Mutable = readVaruint1(Ctx);
1167  if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1168  return Err;
1169  Globals.push_back(Global);
1170  }
1171  if (Ctx.Ptr != Ctx.End)
1172  return make_error<GenericBinaryError>("global section ended prematurely",
1174  return Error::success();
1175 }
1176 
1177 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1178  uint32_t Count = readVaruint32(Ctx);
1179  Exports.reserve(Count);
1180  for (uint32_t I = 0; I < Count; I++) {
1181  wasm::WasmExport Ex;
1182  Ex.Name = readString(Ctx);
1183  Ex.Kind = readUint8(Ctx);
1184  Ex.Index = readVaruint32(Ctx);
1185  switch (Ex.Kind) {
1187 
1188  if (!isDefinedFunctionIndex(Ex.Index))
1189  return make_error<GenericBinaryError>("invalid function export",
1191  getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1192  break;
1194  if (!isValidGlobalIndex(Ex.Index))
1195  return make_error<GenericBinaryError>("invalid global export",
1197  break;
1199  if (!isValidTagIndex(Ex.Index))
1200  return make_error<GenericBinaryError>("invalid tag export",
1202  break;
1205  break;
1206  default:
1207  return make_error<GenericBinaryError>("unexpected export kind",
1209  }
1210  Exports.push_back(Ex);
1211  }
1212  if (Ctx.Ptr != Ctx.End)
1213  return make_error<GenericBinaryError>("export section ended prematurely",
1215  return Error::success();
1216 }
1217 
1218 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1219  return Index < NumImportedFunctions + FunctionTypes.size();
1220 }
1221 
1222 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1223  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1224 }
1225 
1226 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1227  return Index < NumImportedGlobals + Globals.size();
1228 }
1229 
1230 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1231  return Index < NumImportedTables + Tables.size();
1232 }
1233 
1234 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1235  return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1236 }
1237 
1238 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1239  return Index >= NumImportedTables && isValidTableNumber(Index);
1240 }
1241 
1242 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1243  return Index < NumImportedTags + Tags.size();
1244 }
1245 
1246 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1247  return Index >= NumImportedTags && isValidTagIndex(Index);
1248 }
1249 
1250 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1251  return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1252 }
1253 
1254 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1255  return Index < Symbols.size() && Symbols[Index].isTypeTable();
1256 }
1257 
1258 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1259  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1260 }
1261 
1262 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1263  return Index < Symbols.size() && Symbols[Index].isTypeTag();
1264 }
1265 
1266 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1267  return Index < Symbols.size() && Symbols[Index].isTypeData();
1268 }
1269 
1270 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1271  return Index < Symbols.size() && Symbols[Index].isTypeSection();
1272 }
1273 
1274 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1275  assert(isDefinedFunctionIndex(Index));
1276  return Functions[Index - NumImportedFunctions];
1277 }
1278 
1279 const wasm::WasmFunction &
1280 WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1281  assert(isDefinedFunctionIndex(Index));
1282  return Functions[Index - NumImportedFunctions];
1283 }
1284 
1285 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1286  assert(isDefinedGlobalIndex(Index));
1287  return Globals[Index - NumImportedGlobals];
1288 }
1289 
1290 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1291  assert(isDefinedTagIndex(Index));
1292  return Tags[Index - NumImportedTags];
1293 }
1294 
1295 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1296  StartFunction = readVaruint32(Ctx);
1297  if (!isValidFunctionIndex(StartFunction))
1298  return make_error<GenericBinaryError>("invalid start function",
1300  return Error::success();
1301 }
1302 
1303 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1304  SeenCodeSection = true;
1305  CodeSection = Sections.size();
1306  uint32_t FunctionCount = readVaruint32(Ctx);
1307  if (FunctionCount != FunctionTypes.size()) {
1308  return make_error<GenericBinaryError>("invalid function count",
1310  }
1311 
1312  for (uint32_t i = 0; i < FunctionCount; i++) {
1313  wasm::WasmFunction& Function = Functions[i];
1314  const uint8_t *FunctionStart = Ctx.Ptr;
1315  uint32_t Size = readVaruint32(Ctx);
1316  const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1317 
1318  Function.CodeOffset = Ctx.Ptr - FunctionStart;
1319  Function.Index = NumImportedFunctions + i;
1320  Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1321  Function.Size = FunctionEnd - FunctionStart;
1322 
1323  uint32_t NumLocalDecls = readVaruint32(Ctx);
1324  Function.Locals.reserve(NumLocalDecls);
1325  while (NumLocalDecls--) {
1326  wasm::WasmLocalDecl Decl;
1327  Decl.Count = readVaruint32(Ctx);
1328  Decl.Type = readUint8(Ctx);
1329  Function.Locals.push_back(Decl);
1330  }
1331 
1332  uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1333  Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1334  // This will be set later when reading in the linking metadata section.
1335  Function.Comdat = UINT32_MAX;
1336  Ctx.Ptr += BodySize;
1337  assert(Ctx.Ptr == FunctionEnd);
1338  }
1339  if (Ctx.Ptr != Ctx.End)
1340  return make_error<GenericBinaryError>("code section ended prematurely",
1342  return Error::success();
1343 }
1344 
1345 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1346  uint32_t Count = readVaruint32(Ctx);
1347  ElemSegments.reserve(Count);
1348  while (Count--) {
1349  wasm::WasmElemSegment Segment;
1350  Segment.Flags = readVaruint32(Ctx);
1351 
1355  if (Segment.Flags & ~SupportedFlags)
1356  return make_error<GenericBinaryError>(
1357  "Unsupported flags for element segment", object_error::parse_failed);
1358 
1360  Segment.TableNumber = readVaruint32(Ctx);
1361  else
1362  Segment.TableNumber = 0;
1363  if (!isValidTableNumber(Segment.TableNumber))
1364  return make_error<GenericBinaryError>("invalid TableNumber",
1366 
1367  if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1369  Segment.Offset.Value.Int32 = 0;
1370  } else {
1371  if (Error Err = readInitExpr(Segment.Offset, Ctx))
1372  return Err;
1373  }
1374 
1376  Segment.ElemKind = readUint8(Ctx);
1378  if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1379  Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1380  return make_error<GenericBinaryError>("invalid reference type",
1382  }
1383  } else {
1384  if (Segment.ElemKind != 0)
1385  return make_error<GenericBinaryError>("invalid elemtype",
1387  Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1388  }
1389  } else {
1390  Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1391  }
1392 
1394  return make_error<GenericBinaryError>(
1395  "elem segment init expressions not yet implemented",
1397 
1398  uint32_t NumElems = readVaruint32(Ctx);
1399  while (NumElems--) {
1400  Segment.Functions.push_back(readVaruint32(Ctx));
1401  }
1402  ElemSegments.push_back(Segment);
1403  }
1404  if (Ctx.Ptr != Ctx.End)
1405  return make_error<GenericBinaryError>("elem section ended prematurely",
1407  return Error::success();
1408 }
1409 
1410 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1411  DataSection = Sections.size();
1412  uint32_t Count = readVaruint32(Ctx);
1413  if (DataCount && Count != DataCount.getValue())
1414  return make_error<GenericBinaryError>(
1415  "number of data segments does not match DataCount section");
1416  DataSegments.reserve(Count);
1417  while (Count--) {
1418  WasmSegment Segment;
1419  Segment.Data.InitFlags = readVaruint32(Ctx);
1420  Segment.Data.MemoryIndex =
1421  (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1422  ? readVaruint32(Ctx)
1423  : 0;
1424  if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1425  if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1426  return Err;
1427  } else {
1428  Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1429  Segment.Data.Offset.Value.Int32 = 0;
1430  }
1431  uint32_t Size = readVaruint32(Ctx);
1432  if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1433  return make_error<GenericBinaryError>("invalid segment size",
1435  Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1436  // The rest of these Data fields are set later, when reading in the linking
1437  // metadata section.
1438  Segment.Data.Alignment = 0;
1439  Segment.Data.LinkingFlags = 0;
1440  Segment.Data.Comdat = UINT32_MAX;
1441  Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1442  Ctx.Ptr += Size;
1443  DataSegments.push_back(Segment);
1444  }
1445  if (Ctx.Ptr != Ctx.End)
1446  return make_error<GenericBinaryError>("data section ended prematurely",
1448  return Error::success();
1449 }
1450 
1451 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1452  DataCount = readVaruint32(Ctx);
1453  return Error::success();
1454 }
1455 
1457  return Header;
1458 }
1459 
1460 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1461 
1463  uint32_t Result = SymbolRef::SF_None;
1464  const WasmSymbol &Sym = getWasmSymbol(Symb);
1465 
1466  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1467  if (Sym.isBindingWeak())
1468  Result |= SymbolRef::SF_Weak;
1469  if (!Sym.isBindingLocal())
1470  Result |= SymbolRef::SF_Global;
1471  if (Sym.isHidden())
1472  Result |= SymbolRef::SF_Hidden;
1473  if (!Sym.isDefined())
1474  Result |= SymbolRef::SF_Undefined;
1475  if (Sym.isTypeFunction())
1476  Result |= SymbolRef::SF_Executable;
1477  return Result;
1478 }
1479 
1481  DataRefImpl Ref;
1482  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1483  Ref.d.b = 0; // Symbol index
1484  return BasicSymbolRef(Ref, this);
1485 }
1486 
1488  DataRefImpl Ref;
1489  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1490  Ref.d.b = Symbols.size(); // Symbol index
1491  return BasicSymbolRef(Ref, this);
1492 }
1493 
1495  return Symbols[Symb.d.b];
1496 }
1497 
1498 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1499  return getWasmSymbol(Symb.getRawDataRefImpl());
1500 }
1501 
1503  return getWasmSymbol(Symb).Info.Name;
1504 }
1505 
1507  auto &Sym = getWasmSymbol(Symb);
1508  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1509  isDefinedFunctionIndex(Sym.Info.ElementIndex))
1510  return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1511  else
1512  return getSymbolValue(Symb);
1513 }
1514 
1516  switch (Sym.Info.Kind) {
1521  return Sym.Info.ElementIndex;
1523  // The value of a data symbol is the segment offset, plus the symbol
1524  // offset within the segment.
1525  uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1526  const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1527  if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1528  return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1529  } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1530  return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
1531  } else {
1532  llvm_unreachable("unknown init expr opcode");
1533  }
1534  }
1536  return 0;
1537  }
1538  llvm_unreachable("invalid symbol type");
1539 }
1540 
1542  return getWasmSymbolValue(getWasmSymbol(Symb));
1543 }
1544 
1546  llvm_unreachable("not yet implemented");
1547  return 0;
1548 }
1549 
1551  llvm_unreachable("not yet implemented");
1552  return 0;
1553 }
1554 
1557  const WasmSymbol &Sym = getWasmSymbol(Symb);
1558 
1559  switch (Sym.Info.Kind) {
1561  return SymbolRef::ST_Function;
1563  return SymbolRef::ST_Other;
1565  return SymbolRef::ST_Data;
1567  return SymbolRef::ST_Debug;
1569  return SymbolRef::ST_Other;
1571  return SymbolRef::ST_Other;
1572  }
1573 
1574  llvm_unreachable("unknown WasmSymbol::SymbolType");
1575  return SymbolRef::ST_Other;
1576 }
1577 
1580  const WasmSymbol &Sym = getWasmSymbol(Symb);
1581  if (Sym.isUndefined())
1582  return section_end();
1583 
1584  DataRefImpl Ref;
1585  Ref.d.a = getSymbolSectionIdImpl(Sym);
1586  return section_iterator(SectionRef(Ref, this));
1587 }
1588 
1590  const WasmSymbol &Sym = getWasmSymbol(Symb);
1591  return getSymbolSectionIdImpl(Sym);
1592 }
1593 
1594 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1595  switch (Sym.Info.Kind) {
1597  return CodeSection;
1599  return GlobalSection;
1601  return DataSection;
1603  return Sym.Info.ElementIndex;
1605  return TagSection;
1607  return TableSection;
1608  default:
1609  llvm_unreachable("unknown WasmSymbol::SymbolType");
1610  }
1611 }
1612 
1613 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1614 
1616  const WasmSection &S = Sections[Sec.d.a];
1617 #define ECase(X) \
1618  case wasm::WASM_SEC_##X: \
1619  return #X;
1620  switch (S.Type) {
1621  ECase(TYPE);
1622  ECase(IMPORT);
1623  ECase(FUNCTION);
1624  ECase(TABLE);
1625  ECase(MEMORY);
1626  ECase(GLOBAL);
1627  ECase(TAG);
1628  ECase(EXPORT);
1629  ECase(START);
1630  ECase(ELEM);
1631  ECase(CODE);
1632  ECase(DATA);
1633  ECase(DATACOUNT);
1634  case wasm::WASM_SEC_CUSTOM:
1635  return S.Name;
1636  default:
1638  }
1639 #undef ECase
1640 }
1641 
1642 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1643 
1645  return Sec.d.a;
1646 }
1647 
1649  const WasmSection &S = Sections[Sec.d.a];
1650  return S.Content.size();
1651 }
1652 
1655  const WasmSection &S = Sections[Sec.d.a];
1656  // This will never fail since wasm sections can never be empty (user-sections
1657  // must have a name and non-user sections each have a defined structure).
1658  return S.Content;
1659 }
1660 
1662  return 1;
1663 }
1664 
1666  return false;
1667 }
1668 
1670  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1671 }
1672 
1674  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1675 }
1676 
1677 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1678 
1679 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1680 
1682  DataRefImpl RelocRef;
1683  RelocRef.d.a = Ref.d.a;
1684  RelocRef.d.b = 0;
1685  return relocation_iterator(RelocationRef(RelocRef, this));
1686 }
1687 
1689  const WasmSection &Sec = getWasmSection(Ref);
1690  DataRefImpl RelocRef;
1691  RelocRef.d.a = Ref.d.a;
1692  RelocRef.d.b = Sec.Relocations.size();
1693  return relocation_iterator(RelocationRef(RelocRef, this));
1694 }
1695 
1697 
1700  return Rel.Offset;
1701 }
1702 
1705  if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1706  return symbol_end();
1707  DataRefImpl Sym;
1708  Sym.d.a = 1;
1709  Sym.d.b = Rel.Index;
1710  return symbol_iterator(SymbolRef(Sym, this));
1711 }
1712 
1715  return Rel.Type;
1716 }
1717 
1719  DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1721  StringRef Res = "Unknown";
1722 
1723 #define WASM_RELOC(name, value) \
1724  case wasm::name: \
1725  Res = #name; \
1726  break;
1727 
1728  switch (Rel.Type) {
1729 #include "llvm/BinaryFormat/WasmRelocs.def"
1730  }
1731 
1732 #undef WASM_RELOC
1733 
1734  Result.append(Res.begin(), Res.end());
1735 }
1736 
1738  DataRefImpl Ref;
1739  Ref.d.a = 0;
1740  return section_iterator(SectionRef(Ref, this));
1741 }
1742 
1744  DataRefImpl Ref;
1745  Ref.d.a = Sections.size();
1746  return section_iterator(SectionRef(Ref, this));
1747 }
1748 
1750  return HasMemory64 ? 8 : 4;
1751 }
1752 
1754 
1756  return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1757 }
1758 
1760  return SubtargetFeatures();
1761 }
1762 
1763 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1764 
1765 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1766 
1768  assert(Ref.d.a < Sections.size());
1769  return Sections[Ref.d.a];
1770 }
1771 
1772 const WasmSection &
1774  return getWasmSection(Section.getRawDataRefImpl());
1775 }
1776 
1777 const wasm::WasmRelocation &
1779  return getWasmRelocation(Ref.getRawDataRefImpl());
1780 }
1781 
1782 const wasm::WasmRelocation &
1784  assert(Ref.d.a < Sections.size());
1785  const WasmSection &Sec = Sections[Ref.d.a];
1786  assert(Ref.d.b < Sec.Relocations.size());
1787  return Sec.Relocations[Ref.d.b];
1788 }
1789 
1790 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1791  StringRef CustomSectionName) {
1792  switch (ID) {
1793  case wasm::WASM_SEC_CUSTOM:
1794  return StringSwitch<unsigned>(CustomSectionName)
1795  .Case("dylink", WASM_SEC_ORDER_DYLINK)
1796  .Case("linking", WASM_SEC_ORDER_LINKING)
1797  .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1798  .Case("name", WASM_SEC_ORDER_NAME)
1799  .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1800  .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1802  case wasm::WASM_SEC_TYPE:
1803  return WASM_SEC_ORDER_TYPE;
1804  case wasm::WASM_SEC_IMPORT:
1805  return WASM_SEC_ORDER_IMPORT;
1807  return WASM_SEC_ORDER_FUNCTION;
1808  case wasm::WASM_SEC_TABLE:
1809  return WASM_SEC_ORDER_TABLE;
1810  case wasm::WASM_SEC_MEMORY:
1811  return WASM_SEC_ORDER_MEMORY;
1812  case wasm::WASM_SEC_GLOBAL:
1813  return WASM_SEC_ORDER_GLOBAL;
1814  case wasm::WASM_SEC_EXPORT:
1815  return WASM_SEC_ORDER_EXPORT;
1816  case wasm::WASM_SEC_START:
1817  return WASM_SEC_ORDER_START;
1818  case wasm::WASM_SEC_ELEM:
1819  return WASM_SEC_ORDER_ELEM;
1820  case wasm::WASM_SEC_CODE:
1821  return WASM_SEC_ORDER_CODE;
1822  case wasm::WASM_SEC_DATA:
1823  return WASM_SEC_ORDER_DATA;
1825  return WASM_SEC_ORDER_DATACOUNT;
1826  case wasm::WASM_SEC_TAG:
1827  return WASM_SEC_ORDER_TAG;
1828  default:
1829  return WASM_SEC_ORDER_NONE;
1830  }
1831 }
1832 
1833 // Represents the edges in a directed graph where any node B reachable from node
1834 // A is not allowed to appear before A in the section ordering, but may appear
1835 // afterward.
1837  [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1838  // WASM_SEC_ORDER_NONE
1839  {},
1840  // WASM_SEC_ORDER_TYPE
1841  {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1842  // WASM_SEC_ORDER_IMPORT
1843  {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1844  // WASM_SEC_ORDER_FUNCTION
1845  {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1846  // WASM_SEC_ORDER_TABLE
1847  {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1848  // WASM_SEC_ORDER_MEMORY
1849  {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1850  // WASM_SEC_ORDER_TAG
1851  {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1852  // WASM_SEC_ORDER_GLOBAL
1853  {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1854  // WASM_SEC_ORDER_EXPORT
1855  {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1856  // WASM_SEC_ORDER_START
1857  {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1858  // WASM_SEC_ORDER_ELEM
1859  {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1860  // WASM_SEC_ORDER_DATACOUNT
1861  {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1862  // WASM_SEC_ORDER_CODE
1863  {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1864  // WASM_SEC_ORDER_DATA
1865  {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1866 
1867  // Custom Sections
1868  // WASM_SEC_ORDER_DYLINK
1869  {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1870  // WASM_SEC_ORDER_LINKING
1871  {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1872  // WASM_SEC_ORDER_RELOC (can be repeated)
1873  {},
1874  // WASM_SEC_ORDER_NAME
1875  {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1876  // WASM_SEC_ORDER_PRODUCERS
1877  {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1878  // WASM_SEC_ORDER_TARGET_FEATURES
1879  {WASM_SEC_ORDER_TARGET_FEATURES}};
1880 
1882  StringRef CustomSectionName) {
1883  int Order = getSectionOrder(ID, CustomSectionName);
1884  if (Order == WASM_SEC_ORDER_NONE)
1885  return true;
1886 
1887  // Disallowed predecessors we need to check for
1889 
1890  // Keep track of completed checks to avoid repeating work
1891  bool Checked[WASM_NUM_SEC_ORDERS] = {};
1892 
1893  int Curr = Order;
1894  while (true) {
1895  // Add new disallowed predecessors to work list
1896  for (size_t I = 0;; ++I) {
1897  int Next = DisallowedPredecessors[Curr][I];
1898  if (Next == WASM_SEC_ORDER_NONE)
1899  break;
1900  if (Checked[Next])
1901  continue;
1902  WorkList.push_back(Next);
1903  Checked[Next] = true;
1904  }
1905 
1906  if (WorkList.empty())
1907  break;
1908 
1909  // Consider next disallowed predecessor
1910  Curr = WorkList.pop_back_val();
1911  if (Seen[Curr])
1912  return false;
1913  }
1914 
1915  // Have not seen any disallowed predecessors
1916  Seen[Order] = true;
1917  return true;
1918 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:67
i
i
Definition: README.txt:29
llvm::object::WasmSectionOrderChecker
Definition: Wasm.h:307
llvm::wasm::WasmImport::Memory
WasmLimits Memory
Definition: Wasm.h:124
llvm::wasm::WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:355
llvm::wasm::WasmTag
Definition: Wasm.h:110
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_TABLE
@ WASM_SEC_ORDER_TABLE
Definition: Wasm.h:318
llvm::wasm::WASM_NAMES_GLOBAL
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:330
llvm::wasm::WASM_OPCODE_F64_CONST
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:279
llvm::wasm::WasmDataSegment::Offset
WasmInitExpr Offset
Definition: Wasm.h:152
llvm::StringSwitch::StartsWith
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:81
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_IMPORT
@ WASM_SEC_ORDER_IMPORT
Definition: Wasm.h:316
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:491
llvm::object::Kind
Kind
Definition: COFFModuleDefinition.cpp:33
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::wasm::WasmElemSegment::Offset
WasmInitExpr Offset
Definition: Wasm.h:165
llvm::object::WasmObjectFile::WasmObjectFile
WasmObjectFile(MemoryBufferRef Object, Error &Err)
Definition: WasmObjectFile.cpp:260
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::wasm::NameType
NameType
Definition: Wasm.h:208
llvm::object::DataRefImpl::a
uint32_t a
Definition: SymbolicFile.h:37
llvm::object::WasmObjectFile::symbol_begin
basic_symbol_iterator symbol_begin() const override
Definition: WasmObjectFile.cpp:1480
type
llvm::wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:317
llvm::object::WasmObjectFile::getFeatures
SubtargetFeatures getFeatures() const override
Definition: WasmObjectFile.cpp:1759
llvm::object::WasmObjectFile::ReadContext::Start
const uint8_t * Start
Definition: Wasm.h:214
llvm::Triple::wasm32
@ wasm32
Definition: Triple.h:99
llvm::Function::empty
bool empty() const
Definition: Function.h:784
llvm::object::WasmSection::Content
ArrayRef< uint8_t > Content
Definition: Wasm.h:113
llvm::Function
Definition: Function.h:61
StringRef.h
llvm::StringSwitch::Default
LLVM_NODISCARD R Default(T Value)
Definition: StringSwitch.h:181
llvm::wasm::WasmVersion
const uint32_t WasmVersion
Definition: Wasm.h:28
TAG
static constexpr auto TAG
Definition: OpenMPOpt.cpp:126
llvm::object::ObjectFile::RelocationRef
friend class RelocationRef
Definition: ObjectFile.h:286
llvm::toString
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:1020
llvm::object::WasmObjectFile::getBytesInAddress
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
Definition: WasmObjectFile.cpp:1749
llvm::wasm::WasmFeatureEntry
Definition: Wasm.h:53
llvm::object::WasmSectionOrderChecker::isValidSectionOrder
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
Definition: WasmObjectFile.cpp:1881
llvm::object::ObjectFile::createWasmObjectFile
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Definition: WasmObjectFile.cpp:58
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::wasm::WasmObjectHeader::Version
uint32_t Version
Definition: Wasm.h:36
llvm::object::WasmSymbol::Info
const wasm::WasmSymbolInfo & Info
Definition: Wasm.h:45
llvm::dwarf::Form
Form
Definition: Dwarf.h:131
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_TAG
@ WASM_SEC_ORDER_TAG
Definition: Wasm.h:320
ErrorHandling.h
llvm::wasm::WasmLinkingData::SymbolTable
std::vector< WasmSymbolInfo > SymbolTable
Definition: Wasm.h:224
llvm::object::WasmSymbol::isDefined
bool isDefined() const
Definition: Wasm.h:69
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
readVaruint32
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:148
llvm::wasm::WasmFunction::Comdat
uint32_t Comdat
Definition: Wasm.h:144
llvm::wasm::WASM_SYMBOL_BINDING_LOCAL
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:375
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:357
llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:354
llvm::object::WasmSection
Definition: Wasm.h:106
Error.h
llvm::wasm::WasmRelocation
Definition: Wasm.h:177
llvm::wasm::WASM_SEC_TABLE
@ WASM_SEC_TABLE
Definition: Wasm.h:232
llvm::wasm::WasmImport::Table
WasmTableType Table
Definition: Wasm.h:123
llvm::object::WasmSymbol::isTypeFunction
bool isTypeFunction() const
Definition: Wasm.h:51
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_TARGET_FEATURES
Definition: Wasm.h:342
llvm::wasm::WASM_LIMITS_FLAG_IS_64
@ WASM_LIMITS_FLAG_IS_64
Definition: Wasm.h:304
llvm::object::ObjectFile::getSymbolValue
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
Definition: ObjectFile.cpp:57
llvm::object::relocation_iterator
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:76
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::object::WasmObjectFile::isSectionCompressed
bool isSectionCompressed(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1665
llvm::wasm::WasmImport::SigIndex
uint32_t SigIndex
Definition: Wasm.h:121
llvm::wasm::WASM_OPCODE_GLOBAL_GET
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:272
llvm::object::Binary::Data
MemoryBufferRef Data
Definition: Binary.h:37
readVaruint1
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:134
llvm::wasm::WASM_SEC_CUSTOM
@ WASM_SEC_CUSTOM
Definition: Wasm.h:228
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
llvm::wasm::WASM_COMDAT_FUNCTION
@ WASM_COMDAT_FUNCTION
Definition: Wasm.h:345
llvm::wasm::WasmElemSegment::ElemKind
uint8_t ElemKind
Definition: Wasm.h:164
llvm::object::WasmObjectFile::getSectionName
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1615
llvm::wasm::WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:378
T
#define T
Definition: Mips16ISelLowering.cpp:341
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::object::WasmObjectFile::getSymbolValueImpl
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1541
llvm::object::WasmObjectFile::getRelocationTypeName
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
Definition: WasmObjectFile.cpp:1718
llvm::object::WasmObjectFile::isSectionBSS
bool isSectionBSS(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1677
llvm::wasm::WasmSymbolInfo::Kind
uint8_t Kind
Definition: Wasm.h:191
llvm::StringSet::insert
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:33
llvm::object::SymbolRef::ST_Data
@ ST_Data
Definition: ObjectFile.h:173
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
STLExtras.h
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:635
llvm::wasm::WasmFunction
Definition: Wasm.h:134
llvm::object::BasicSymbolRef::SF_Weak
@ SF_Weak
Definition: SymbolicFile.h:110
llvm::wasm::WasmExport::Kind
uint8_t Kind
Definition: Wasm.h:60
llvm::wasm::WASM_NAMES_FUNCTION
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:328
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:104
SymbolicFile.h
llvm::object::WasmObjectFile::isRelocatableObject
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
Definition: WasmObjectFile.cpp:1763
llvm::object::WasmObjectFile::getArch
Triple::ArchType getArch() const override
Definition: WasmObjectFile.cpp:1755
llvm::wasm::WasmDataReference::Offset
uint64_t Offset
Definition: Wasm.h:173
llvm::wasm::WASM_SEC_CODE
@ WASM_SEC_CODE
Definition: Wasm.h:238
llvm::detail::DenseSetImpl::insert
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_NAME
@ WASM_SEC_ORDER_NAME
Definition: Wasm.h:338
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_PRODUCERS
Definition: Wasm.h:340
llvm::wasm::WASM_SEC_TYPE
@ WASM_SEC_TYPE
Definition: Wasm.h:229
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::wasm::WasmDataReference
Definition: Wasm.h:171
readInitExpr
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:167
llvm::wasm::WasmExport::Index
uint32_t Index
Definition: Wasm.h:61
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
llvm::object::BasicSymbolRef::SF_Executable
@ SF_Executable
Definition: SymbolicFile.h:120
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:162
llvm::object::WasmObjectFile::moveSectionNext
void moveSectionNext(DataRefImpl &Sec) const override
Definition: WasmObjectFile.cpp:1613
llvm::wasm::WasmRelocation::Offset
uint64_t Offset
Definition: Wasm.h:180
llvm::wasm::WasmTagType::SigIndex
uint32_t SigIndex
Definition: Wasm.h:107
llvm::object::WasmSymbol::isHidden
bool isHidden() const
Definition: Wasm.h:91
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::StringRef::substr
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:611
llvm::wasm::WASM_EXTERNAL_TAG
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:263
readULEB128
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:104
readVarint32
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:141
llvm::wasm::WasmElemSegment::TableNumber
uint32_t TableNumber
Definition: Wasm.h:163
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_GLOBAL
@ WASM_SEC_ORDER_GLOBAL
Definition: Wasm.h:321
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_START
@ WASM_SEC_ORDER_START
Definition: Wasm.h:323
llvm::decodeULEB128
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:128
llvm::wasm::WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition: Wasm.h:374
llvm::wasm::WasmFunction::DebugName
StringRef DebugName
Definition: Wasm.h:143
llvm::object::WasmSection::Type
uint32_t Type
Definition: Wasm.h:109
Error.h
SubtargetFeature.h
llvm::wasm::WasmInitExpr::Global
uint32_t Global
Definition: Wasm.h:88
llvm::Triple::ArchType
ArchType
Definition: Triple.h:47
llvm::object::WasmObjectFile::ReadContext::End
const uint8_t * End
Definition: Wasm.h:216
llvm::ModRefInfo::Ref
@ Ref
The access may reference the value stored in memory.
llvm::object::WasmObjectFile::ReadContext::Ptr
const uint8_t * Ptr
Definition: Wasm.h:215
llvm::wasm::WasmGlobalType::Mutable
bool Mutable
Definition: Wasm.h:94
llvm::wasm::WasmLimits
Definition: Wasm.h:64
llvm::object::BasicSymbolRef::getRawDataRefImpl
DataRefImpl getRawDataRefImpl() const
Definition: SymbolicFile.h:206
llvm::wasm::WasmRelocation::Addend
int64_t Addend
Definition: Wasm.h:181
llvm::wasm::WasmInitExpr::Float64
uint64_t Float64
Definition: Wasm.h:87
llvm::wasm::WasmTableType::ElemType
uint8_t ElemType
Definition: Wasm.h:71
llvm::object::WasmObjectFile::getWasmRelocation
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
Definition: WasmObjectFile.cpp:1778
llvm::object::BasicSymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: SymbolicFile.h:101
llvm::object::WasmSymbol
Definition: Wasm.h:35
llvm::wasm::WasmFeatureEntry::Prefix
uint8_t Prefix
Definition: Wasm.h:54
llvm::wasm::WASM_ELEM_SEGMENT_IS_PASSIVE
@ WASM_ELEM_SEGMENT_IS_PASSIVE
Definition: Wasm.h:313
llvm::object::WasmObjectFile::isSectionText
bool isSectionText(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1669
llvm::object::WasmObjectFile::getSymbolAlignment
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1545
llvm::SubtargetFeatures
Manages the enabling and disabling of subtarget specific features.
Definition: SubtargetFeature.h:183
llvm::wasm::WasmInitExpr::Int64
int64_t Int64
Definition: Wasm.h:85
llvm::ms_demangle::NodeKind::TagType
@ TagType
llvm::object::WasmObjectFile::getSymbolSectionId
uint32_t getSymbolSectionId(SymbolRef Sym) const
Definition: WasmObjectFile.cpp:1589
llvm::wasm::WASM_EXTERNAL_MEMORY
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:261
readUint8
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:72
llvm::wasm::WasmGlobalType
Definition: Wasm.h:92
DenseSet.h
llvm::wasm::WasmTagType::Attribute
uint8_t Attribute
Definition: Wasm.h:106
llvm::wasm::WasmFunction::CodeSectionOffset
uint32_t CodeSectionOffset
Definition: Wasm.h:138
llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:308
llvm::wasm::WASM_TYPE_EXTERNREF
@ WASM_TYPE_EXTERNREF
Definition: Wasm.h:252
llvm::wasm::WasmProducerInfo::Languages
std::vector< std::pair< std::string, std::string > > Languages
Definition: Wasm.h:48
llvm::wasm::WasmTable::SymbolName
StringRef SymbolName
Definition: Wasm.h:78
llvm::object::WasmObjectFile::getSymbolSection
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1579
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::wasm::WasmDylinkInfo::MemoryAlignment
uint32_t MemoryAlignment
Definition: Wasm.h:41
llvm::wasm::WasmDataReference::Size
uint64_t Size
Definition: Wasm.h:174
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::AMDGPU::ElfNote::SectionName
const char SectionName[]
Definition: AMDGPUPTNote.h:24
llvm::ErrorAsOutParameter
Helper for Errors used as out-parameters.
Definition: Error.h:1089
llvm::wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:314
llvm::object::object_error::parse_failed
@ parse_failed
llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:352
llvm::object::WasmObjectFile::moveRelocationNext
void moveRelocationNext(DataRefImpl &Rel) const override
Definition: WasmObjectFile.cpp:1696
llvm::wasm::WasmMetadataVersion
const uint32_t WasmMetadataVersion
Definition: Wasm.h:30
llvm::wasm::NameType::FUNCTION
@ FUNCTION
llvm::wasm::ValType
ValType
Definition: Wasm.h:392
llvm::IndexedInstrProf::Version
const uint64_t Version
Definition: InstrProf.h:991
llvm::wasm::WasmLocalDecl::Type
uint8_t Type
Definition: Wasm.h:130
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::wasm::WASM_COMDAT_SECTION
@ WASM_COMDAT_SECTION
Definition: Wasm.h:347
llvm::wasm::WASM_FEATURE_PREFIX_DISALLOWED
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition: Wasm.h:323
llvm::wasm::WasmTable::Type
WasmTableType Type
Definition: Wasm.h:77
llvm::Comdat
Definition: Comdat.h:31
llvm::object::WasmSymbol::isUndefined
bool isUndefined() const
Definition: Wasm.h:71
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:302
llvm::wasm::WasmSymbolInfo::Name
StringRef Name
Definition: Wasm.h:190
llvm::object::WasmObjectFile::getHeader
const wasm::WasmObjectHeader & getHeader() const
Definition: WasmObjectFile.cpp:1456
Wasm.h
llvm::wasm::WasmImport::Field
StringRef Field
Definition: Wasm.h:118
llvm::wasm::WasmSymbolInfo::ElementIndex
uint32_t ElementIndex
Definition: Wasm.h:202
llvm::object::WasmSymbol::print
void print(raw_ostream &Out) const
Definition: WasmObjectFile.cpp:40
llvm::PassSummaryAction::Import
@ Import
Import information from summary.
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_DATACOUNT
Definition: Wasm.h:325
llvm::wasm::WasmInitExpr::Float32
uint32_t Float32
Definition: Wasm.h:86
llvm::object::WasmObjectFile::getSectionIndex
uint64_t getSectionIndex(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1644
llvm::wasm::WasmObjectHeader::Magic
StringRef Magic
Definition: Wasm.h:35
readLEB128
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:124
llvm::wasm::NameType::GLOBAL
@ GLOBAL
llvm::wasm::WasmLinkingData::Comdats
std::vector< StringRef > Comdats
Definition: Wasm.h:223
llvm::wasm::WasmLimits::Flags
uint8_t Flags
Definition: Wasm.h:65
llvm::wasm::WASM_OPCODE_F32_CONST
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:278
llvm::object::SectionRef
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
llvm::wasm::WasmRelocation::Type
uint8_t Type
Definition: Wasm.h:178
llvm::DenseSet< uint64_t >
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_EXPORT
@ WASM_SEC_ORDER_EXPORT
Definition: Wasm.h:322
llvm::object::ObjectFile::SymbolRef
friend class SymbolRef
Definition: ObjectFile.h:246
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_MEMORY
@ WASM_SEC_ORDER_MEMORY
Definition: Wasm.h:319
object
bar al al movzbl eax ret Missed when stored in a memory object
Definition: README.txt:1411
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_TYPE
@ WASM_SEC_ORDER_TYPE
Definition: Wasm.h:315
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
llvm::Twine::utohexstr
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:408
llvm::object::WasmSymbol::isBindingWeak
bool isBindingWeak() const
Definition: Wasm.h:75
llvm::wasm::WASM_SEC_IMPORT
@ WASM_SEC_IMPORT
Definition: Wasm.h:230
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::wasm::WASM_SEGMENT_INFO
@ WASM_SEGMENT_INFO
Definition: Wasm.h:336
llvm::object::WasmObjectFile::getSymbolType
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1556
llvm::object::symbol_iterator
Definition: ObjectFile.h:207
llvm::StringRef::end
iterator end() const
Definition: StringRef.h:130
llvm::wasm::WasmElemSegment::Functions
std::vector< uint32_t > Functions
Definition: Wasm.h:166
llvm::object::SymbolRef::ST_Function
@ ST_Function
Definition: ObjectFile.h:176
llvm::wasm::ValType::EXTERNREF
@ EXTERNREF
llvm::wasm::WASM_INIT_FUNCS
@ WASM_INIT_FUNCS
Definition: Wasm.h:337
llvm::wasm::WasmExport::Name
StringRef Name
Definition: Wasm.h:59
llvm::object::WasmObjectFile::section_begin
section_iterator section_begin() const override
Definition: WasmObjectFile.cpp:1737
llvm::wasm::WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:380
llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:309
LEB128.h
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::object::WasmSymbol::isTypeData
bool isTypeData() const
Definition: Wasm.h:57
llvm::object::BasicSymbolRef::SF_None
@ SF_None
Definition: SymbolicFile.h:107
llvm::wasm::WasmLocalDecl
Definition: Wasm.h:129
llvm::wasm::ValType::FUNCREF
@ FUNCREF
llvm::object::ObjectFile::SectionRef
friend class SectionRef
Definition: ObjectFile.h:260
readUint32
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:78
llvm::wasm::WasmProducerInfo::Tools
std::vector< std::pair< std::string, std::string > > Tools
Definition: Wasm.h:49
llvm::object::WasmObjectFile::getSymbolFlags
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1462
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::object::BasicSymbolRef::SF_Undefined
@ SF_Undefined
Definition: SymbolicFile.h:108
llvm::wasm::WasmSignature::Returns
SmallVector< ValType, 1 > Returns
Definition: Wasm.h:403
llvm::wasm::WasmDylinkInfo::TableSize
uint32_t TableSize
Definition: Wasm.h:42
llvm::wasm::WASM_EXTERNAL_GLOBAL
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:262
llvm::wasm::WasmImport
Definition: Wasm.h:116
ArrayRef.h
llvm::wasm::WASM_SYMBOL_TYPE_TAG
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:356
llvm::wasm::WASM_SEC_GLOBAL
@ WASM_SEC_GLOBAL
Definition: Wasm.h:234
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_RELOC
@ WASM_SEC_ORDER_RELOC
Definition: Wasm.h:335
llvm::object::SymbolRef::ST_Debug
@ ST_Debug
Definition: ObjectFile.h:174
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::wasm::WasmDebugName
Definition: Wasm.h:214
ObjectFile.h
llvm::object::WasmObjectFile::getSectionAddress
uint64_t getSectionAddress(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1642
llvm::wasm::WasmImport::Tag
WasmTagType Tag
Definition: Wasm.h:125
readFloat64
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:95
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::object::content_iterator
Definition: SymbolicFile.h:67
llvm::wasm::WasmTagType
Definition: Wasm.h:104
llvm::object::WasmObjectFile::getWasmSymbolValue
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const
Definition: WasmObjectFile.cpp:1515
llvm::wasm::WASM_FEATURE_PREFIX_REQUIRED
@ WASM_FEATURE_PREFIX_REQUIRED
Definition: Wasm.h:322
llvm::object::WasmObjectFile::isSharedObject
bool isSharedObject() const
Definition: WasmObjectFile.cpp:1765
llvm::wasm::WASM_EXTERNAL_FUNCTION
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:259
llvm::StringRef::bytes_begin
const unsigned char * bytes_begin() const
Definition: StringRef.h:132
llvm::ARM::WinEH::ReturnType
ReturnType
Definition: ARMWinEH.h:25
llvm::object::WasmObjectFile::getSymbolName
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1502
Triple.h
llvm::StringSet
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:22
llvm::wasm::WasmElemSegment::Flags
uint32_t Flags
Definition: Wasm.h:162
llvm::wasm::WasmInitExpr::Int32
int32_t Int32
Definition: Wasm.h:84
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_ELEM
@ WASM_SEC_ORDER_ELEM
Definition: Wasm.h:324
llvm::ArrayRef< uint8_t >
llvm::object::section_iterator
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:47
llvm::wasm::WASM_COMDAT_INFO
@ WASM_COMDAT_INFO
Definition: Wasm.h:338
llvm::wasm::WASM_NAMES_LOCAL
@ WASM_NAMES_LOCAL
Definition: Wasm.h:329
readVarint64
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:155
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:228
llvm::wasm::WASM_TYPE_FUNCREF
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:251
llvm::object::Binary
Definition: Binary.h:32
llvm::object::WasmObjectFile::getSectionContents
Expected< ArrayRef< uint8_t > > getSectionContents(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1654
llvm::wasm::WASM_SEC_TAG
@ WASM_SEC_TAG
Definition: Wasm.h:241
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::wasm::WasmObjectHeader
Definition: Wasm.h:34
llvm::wasm::WasmGlobal
Definition: Wasm.h:97
uint32_t
llvm::wasm::WASM_SYMBOL_BINDING_MASK
const unsigned WASM_SYMBOL_BINDING_MASK
Definition: Wasm.h:370
llvm::object::WasmSectionOrderChecker::WASM_NUM_SEC_ORDERS
@ WASM_NUM_SEC_ORDERS
Definition: Wasm.h:345
llvm::wasm::WasmSymbolType
WasmSymbolType
Definition: Wasm.h:351
llvm::wasm::WASM_SEC_ELEM
@ WASM_SEC_ELEM
Definition: Wasm.h:237
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::object::DataRefImpl
Definition: SymbolicFile.h:33
llvm::object::WasmObjectFile::isSectionVirtual
bool isSectionVirtual(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1679
llvm::wasm::WASM_SEC_MEMORY
@ WASM_SEC_MEMORY
Definition: Wasm.h:233
llvm::wasm::WasmTableType::Limits
WasmLimits Limits
Definition: Wasm.h:72
llvm::wasm::WASM_SEC_EXPORT
@ WASM_SEC_EXPORT
Definition: Wasm.h:235
llvm::wasm::WasmSymbolInfo
Definition: Wasm.h:189
llvm::SmallSet::insert
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:180
llvm::wasm::WasmDylinkInfo::Needed
std::vector< StringRef > Needed
Definition: Wasm.h:44
llvm::wasm::WasmImport::Global
WasmGlobalType Global
Definition: Wasm.h:122
llvm::wasm::WasmGlobalType::Type
uint8_t Type
Definition: Wasm.h:93
llvm::object::object_error::invalid_section_index
@ invalid_section_index
llvm::Init
Definition: Record.h:271
readSection
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
Definition: WasmObjectFile.cpp:224
llvm::wasm::WasmSymbolInfo::DataRef
WasmDataReference DataRef
Definition: Wasm.h:204
llvm::wasm::WASM_EXTERNAL_TABLE
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:260
llvm::object::WasmObjectFile::isSectionData
bool isSectionData(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1673
llvm::object::WasmObjectFile::getSectionSize
uint64_t getSectionSize(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1648
llvm::wasm::WASM_SEC_START
@ WASM_SEC_START
Definition: Wasm.h:236
llvm::wasm::WasmProducerInfo::SDKs
std::vector< std::pair< std::string, std::string > > SDKs
Definition: Wasm.h:50
llvm::object::WasmObjectFile::getWasmSection
const WasmSection & getWasmSection(const SectionRef &Section) const
Definition: WasmObjectFile.cpp:1773
StringSet.h
llvm::wasm::WASM_OPCODE_END
@ WASM_OPCODE_END
Definition: Wasm.h:268
llvm::object::WasmObjectFile::ReadContext
Definition: Wasm.h:213
llvm::object::WasmObjectFile::getSectionAlignment
uint64_t getSectionAlignment(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1661
llvm::wasm::WasmDataReference::Segment
uint32_t Segment
Definition: Wasm.h:172
llvm::object::WasmObjectFile::moveSymbolNext
void moveSymbolNext(DataRefImpl &Symb) const override
Definition: WasmObjectFile.cpp:1460
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
readFloat32
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:86
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1231
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::object::WasmObjectFile::getRelocationSymbol
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Definition: WasmObjectFile.cpp:1703
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_NONE
@ WASM_SEC_ORDER_NONE
Definition: Wasm.h:312
VARUINT1_MAX
#define VARUINT1_MAX
Definition: WasmObjectFile.cpp:70
llvm::wasm::WasmLinkingData::InitFunctions
std::vector< WasmInitFunc > InitFunctions
Definition: Wasm.h:222
llvm::SectionName
Definition: DWARFSection.h:21
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::wasm::WasmDylinkInfo::MemorySize
uint32_t MemorySize
Definition: Wasm.h:40
llvm::wasm::WASM_OPCODE_I32_CONST
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:276
llvm::object::WasmObjectFile::getWasmSymbol
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
Definition: WasmObjectFile.cpp:1494
llvm::wasm::WasmInitFunc
Definition: Wasm.h:184
llvm::wasm::WasmSymbolInfo::Flags
uint32_t Flags
Definition: Wasm.h:192
llvm::wasm::WasmLocalDecl::Count
uint32_t Count
Definition: Wasm.h:131
readOpcode
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:163
readTableType
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:217
llvm::object::WasmObjectFile::section_end
section_iterator section_end() const override
Definition: WasmObjectFile.cpp:1743
llvm::wasm::WasmDataSegment
Definition: Wasm.h:147
llvm::object::WasmObjectFile::getSymbolAddress
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1506
llvm::object::WasmObjectFile::getRelocationOffset
uint64_t getRelocationOffset(DataRefImpl Rel) const override
Definition: WasmObjectFile.cpp:1698
llvm::object::WasmObjectFile::symbol_end
basic_symbol_iterator symbol_end() const override
Definition: WasmObjectFile.cpp:1487
llvm::wasm::WasmInitExpr
Definition: Wasm.h:81
StringSwitch.h
llvm::wasm::WasmFunction::ExportName
Optional< StringRef > ExportName
Definition: Wasm.h:141
llvm::object::WasmObjectFile::section_rel_begin
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1681
llvm::wasm::WasmLinkingData::Version
uint32_t Version
Definition: Wasm.h:221
Wasm.h
llvm::object::SymbolRef::ST_Other
@ ST_Other
Definition: ObjectFile.h:177
llvm::wasm::WASM_COMDAT_DATA
@ WASM_COMDAT_DATA
Definition: Wasm.h:344
llvm::wasm::WasmTable
Definition: Wasm.h:75
llvm::wasm::NameType::DATA_SEGMENT
@ DATA_SEGMENT
llvm::wasm::WASM_SEC_FUNCTION
@ WASM_SEC_FUNCTION
Definition: Wasm.h:231
llvm::decodeSLEB128
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:161
llvm::wasm::WASM_NAMES_DATA_SEGMENT
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:331
Binary.h
llvm::wasm::WasmImport::Module
StringRef Module
Definition: Wasm.h:117
llvm::wasm::WasmRelocation::Index
uint32_t Index
Definition: Wasm.h:179
llvm::support::endian::read32le
uint32_t read32le(const void *P)
Definition: Endian.h:381
llvm::object::WasmObjectFile::getCommonSymbolSizeImpl
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
Definition: WasmObjectFile.cpp:1550
llvm::wasm::WasmElemSegment
Definition: Wasm.h:161
llvm::wasm::WasmInitExpr::Value
union llvm::wasm::WasmInitExpr::@161 Value
llvm::object::BasicSymbolRef::SF_Global
@ SF_Global
Definition: SymbolicFile.h:109
llvm::wasm::WASM_OPCODE_REF_NULL
@ WASM_OPCODE_REF_NULL
Definition: Wasm.h:282
llvm::object::BasicSymbolRef::SF_Hidden
@ SF_Hidden
Definition: SymbolicFile.h:118
llvm::to_string
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:63
readVaruint64
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:159
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_DATA
@ WASM_SEC_ORDER_DATA
Definition: Wasm.h:327
llvm::pdb::PDB_DataKind::Global
@ Global
llvm::wasm::WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_USED
Definition: Wasm.h:321
llvm::SmallVectorImpl< char >
llvm::wasm::WasmFeatureEntry::Name
std::string Name
Definition: Wasm.h:55
llvm::object::SymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:167
llvm::object::Binary::getData
StringRef getData() const
Definition: Binary.cpp:40
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_DYLINK
@ WASM_SEC_ORDER_DYLINK
Definition: Wasm.h:331
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
llvm::wasm::WasmInitExpr::Opcode
uint8_t Opcode
Definition: Wasm.h:82
llvm::wasm::WASM_SYMBOL_TABLE
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:339
ECase
#define ECase(X)
llvm::object::DataRefImpl::b
uint32_t b
Definition: SymbolicFile.h:37
llvm::object::WasmSymbol::dump
LLVM_DUMP_METHOD void dump() const
Definition: WasmObjectFile.cpp:54
llvm::wasm::WasmImport::Kind
uint8_t Kind
Definition: Wasm.h:119
llvm::object::WasmObjectFile::getRelocationType
uint64_t getRelocationType(DataRefImpl Rel) const override
Definition: WasmObjectFile.cpp:1713
llvm::wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
Definition: Wasm.h:315
llvm::object::RelocationRef
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:51
llvm::wasm::WASM_SEC_DATACOUNT
@ WASM_SEC_DATACOUNT
Definition: Wasm.h:240
readString
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:114
llvm::object::WasmSectionOrderChecker::DisallowedPredecessors
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
Definition: Wasm.h:350
llvm::object::WasmObjectFile::section_rel_end
relocation_iterator section_rel_end(DataRefImpl Sec) const override
Definition: WasmObjectFile.cpp:1688
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::SmallVectorImpl::reserve
void reserve(size_type N)
Definition: SmallVector.h:624
llvm::wasm::WasmTableType
Definition: Wasm.h:70
Endian.h
llvm::StringRef::begin
iterator begin() const
Definition: StringRef.h:128
llvm::Triple::wasm64
@ wasm64
Definition: Triple.h:100
llvm::wasm::WASM_OPCODE_I64_CONST
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:277
llvm::wasm::WasmDylinkInfo::TableAlignment
uint32_t TableAlignment
Definition: Wasm.h:43
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_LINKING
@ WASM_SEC_ORDER_LINKING
Definition: Wasm.h:333
llvm::object::DataRefImpl::d
struct llvm::object::DataRefImpl::@317 d
llvm::wasm::WasmSignature::Params
SmallVector< ValType, 4 > Params
Definition: Wasm.h:404
llvm::object::WasmSection::Relocations
std::vector< wasm::WasmRelocation > Relocations
Definition: Wasm.h:114
llvm::object::WasmObjectFile::getFileFormatName
StringRef getFileFormatName() const override
Definition: WasmObjectFile.cpp:1753
llvm::wasm::WasmExport
Definition: Wasm.h:58
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_FUNCTION
@ WASM_SEC_ORDER_FUNCTION
Definition: Wasm.h:317
llvm::wasm::WASM_SYMBOL_TYPE_DATA
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:353
llvm::wasm::WasmSignature
Definition: Wasm.h:402
llvm::Optional::getValue
constexpr const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:282
readLimits
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
Definition: WasmObjectFile.cpp:208
llvm::wasm::WASM_SEC_DATA
@ WASM_SEC_DATA
Definition: Wasm.h:239
llvm::object::WasmSectionOrderChecker::WASM_SEC_ORDER_CODE
@ WASM_SEC_ORDER_CODE
Definition: Wasm.h:326
llvm::wasm::WASM_TYPE_FUNC
@ WASM_TYPE_FUNC
Definition: Wasm.h:253
llvm::object::WasmSymbol::isBindingLocal
bool isBindingLocal() const
Definition: Wasm.h:83
SmallSet.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
ScopedPrinter.h