llvm.org GIT mirror llvm / 581d231
[WebAssembly] clang-format (NFC) Summary: This patch runs clang-format on all wasm-only files. Reviewers: aardappel, dschuff, sunfish, tlively Subscribers: MatzeB, sbc100, jgravelle-google, llvm-commits Differential Revision: https://reviews.llvm.org/D51447 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341439 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 1 year, 18 days ago
51 changed file(s) with 826 addition(s) and 730 deletion(s). Raw diff Collapse all Expand all
103103 uint32_t Size;
104104 uint32_t CodeOffset; // start of Locals and Body
105105 StringRef SymbolName; // from the "linking" section
106 StringRef DebugName; // from the "name" section
107 uint32_t Comdat; // from the "comdat info" section
106 StringRef DebugName; // from the "name" section
107 uint32_t Comdat; // from the "comdat info" section
108108 };
109109
110110 struct WasmDataSegment {
230230 // Kind codes used in the custom "name" section
231231 enum : unsigned {
232232 WASM_NAMES_FUNCTION = 0x1,
233 WASM_NAMES_LOCAL = 0x2,
233 WASM_NAMES_LOCAL = 0x2,
234234 };
235235
236236 // Kind codes used in the custom "linking" section
237237 enum : unsigned {
238 WASM_SEGMENT_INFO = 0x5,
239 WASM_INIT_FUNCS = 0x6,
240 WASM_COMDAT_INFO = 0x7,
241 WASM_SYMBOL_TABLE = 0x8,
238 WASM_SEGMENT_INFO = 0x5,
239 WASM_INIT_FUNCS = 0x6,
240 WASM_COMDAT_INFO = 0x7,
241 WASM_SYMBOL_TABLE = 0x8,
242242 };
243243
244244 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
245245 enum : unsigned {
246 WASM_COMDAT_DATA = 0x0,
247 WASM_COMDAT_FUNCTION = 0x1,
246 WASM_COMDAT_DATA = 0x0,
247 WASM_COMDAT_FUNCTION = 0x1,
248248 };
249249
250250 // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
255255 WASM_SYMBOL_TYPE_SECTION = 0x3,
256256 };
257257
258 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
259 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
260
261 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
262 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
263 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
258 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
259 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
260
261 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
262 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
263 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
264264 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
265 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
266 const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
265 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
266 const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
267267
268268 #define WASM_RELOC(name, value) name = value,
269269
1313 #ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
1414 #define LLVM_CODEGEN_WASMEHFUNCINFO_H
1515
16 #include "llvm/ADT/DenseMap.h"
1617 #include "llvm/ADT/PointerUnion.h"
17 #include "llvm/ADT/DenseMap.h"
1818 #include "llvm/CodeGen/MachineBasicBlock.h"
1919 #include "llvm/IR/BasicBlock.h"
2020
1818 protected:
1919 MCAsmInfoWasm();
2020 };
21 }
21 } // namespace llvm
2222
2323 #endif
3434 // Use a module name of "env" for now, for compatibility with existing tools.
3535 // This is temporary, and may change, as the ABI is not yet stable.
3636 MCSymbolWasm(const StringMapEntry *Name, bool isTemporary)
37 : MCSymbol(SymbolKindWasm, Name, isTemporary),
38 ModuleName("env") {}
37 : MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {}
3938 static bool classof(const MCSymbol *S) { return S->isWasm(); }
4039
4140 const MCExpr *getSize() const { return SymbolSize; }
9190 }
9291 };
9392
94 } // end namespace llvm
93 } // end namespace llvm
9594
9695 #endif // LLVM_MC_MCSYMBOLWASM_H
5050 createWasmObjectWriter(std::unique_ptr MOTW,
5151 raw_pwrite_stream &OS);
5252
53 } // End llvm namespace
53 } // namespace llvm
5454
5555 #endif
1717 #define LLVM_OBJECT_WASM_H
1818
1919 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringMap.h"
2021 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/StringMap.h"
2222 #include "llvm/BinaryFormat/Wasm.h"
2323 #include "llvm/Config/llvm-config.h"
2424 #include "llvm/Object/Binary.h"
9797 struct WasmSection {
9898 WasmSection() = default;
9999
100 uint32_t Type = 0; // Section type (See below)
101 uint32_t Offset = 0; // Offset with in the file
102 StringRef Name; // Section name (User-defined sections only)
100 uint32_t Type = 0; // Section type (See below)
101 uint32_t Offset = 0; // Offset with in the file
102 StringRef Name; // Section name (User-defined sections only)
103103 ArrayRef Content; // Section content
104104 std::vector Relocations; // Relocations for this section
105105 };
118118 const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
119119 const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
120120 const WasmSection &getWasmSection(const SectionRef &Section) const;
121 const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
121 const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
122122
123123 static bool classof(const Binary *v) { return v->isWasm(); }
124124
130130 ArrayRef globals() const { return Globals; }
131131 ArrayRef exports() const { return Exports; }
132132 ArrayRef syms() const { return Symbols; }
133 const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
133 const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
134134 uint32_t getNumberOfSymbols() const { return Symbols.size(); }
135135 ArrayRef elements() const { return ElemSegments; }
136136 ArrayRef dataSegments() const { return DataSegments; }
150150 Expected getSymbolName(DataRefImpl Symb) const override;
151151
152152 Expected getSymbolAddress(DataRefImpl Symb) const override;
153 uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const;
153 uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
154154 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
155155 uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
156156 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
263263
264264 } // end namespace object
265265
266 inline raw_ostream &operator<<(raw_ostream &OS,
267 const object::WasmSymbol &Sym) {
266 inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
268267 Sym.print(OS);
269268 return OS;
270269 }
2424
2525 std::string llvm::wasm::relocTypetoString(uint32_t type) {
2626 switch (type) {
27 #define WASM_RELOC(NAME, VALUE) case VALUE: return #NAME;
27 #define WASM_RELOC(NAME, VALUE) \
28 case VALUE: \
29 return #NAME;
2830 #include "llvm/BinaryFormat/WasmRelocs.def"
2931 #undef WASM_RELOC
3032 default:
1414 #include "llvm/MC/MCAsmInfoWasm.h"
1515 using namespace llvm;
1616
17 void MCAsmInfoWasm::anchor() { }
17 void MCAsmInfoWasm::anchor() {}
1818
1919 MCAsmInfoWasm::MCAsmInfoWasm() {
2020 HasIdentDirective = true;
136136
137137 // Information about a single relocation.
138138 struct WasmRelocationEntry {
139 uint64_t Offset; // Where is the relocation.
140 const MCSymbolWasm *Symbol; // The symbol to relocate with.
141 int64_t Addend; // A value to add to the symbol.
142 unsigned Type; // The type of the relocation.
143 const MCSectionWasm *FixupSection;// The section the relocation is targeting.
139 uint64_t Offset; // Where is the relocation.
140 const MCSymbolWasm *Symbol; // The symbol to relocate with.
141 int64_t Addend; // A value to add to the symbol.
142 unsigned Type; // The type of the relocation.
143 const MCSectionWasm *FixupSection; // The section the relocation is targeting.
144144
145145 WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
146146 int64_t Addend, unsigned Type,
162162 }
163163
164164 void print(raw_ostream &Out) const {
165 Out << wasm::relocTypetoString(Type)
166 << " Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
165 Out << wasm::relocTypetoString(Type) << " Off=" << Offset
166 << ", Sym=" << *Symbol << ", Addend=" << Addend
167167 << ", FixupSection=" << FixupSection->getSectionName();
168168 }
169169
290290 W.OS << Str;
291291 }
292292
293 void writeValueType(wasm::ValType Ty) {
294 W.OS << static_cast(Ty);
295 }
293 void writeValueType(wasm::ValType Ty) { W.OS << static_cast(Ty); }
296294
297295 void writeTypeSection(ArrayRef FunctionTypes);
298296 void writeImportSection(ArrayRef Imports, uint32_t DataSize,
305303 ArrayRef Functions);
306304 void writeDataSection();
307305 void writeRelocSection(uint32_t SectionIndex, StringRef Name,
308 std::vector& Relocations);
306 std::vector &Relocations);
309307 void writeLinkingMetaDataSection(
310308 ArrayRef SymbolInfos,
311309 ArrayRef> InitFuncs,
528526
529527 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
530528 // to allow patching.
531 static void
532 WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
529 static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
530 uint64_t Offset) {
533531 uint8_t Buffer[5];
534532 unsigned SizeLen = encodeULEB128(X, Buffer, 5);
535533 assert(SizeLen == 5);
538536
539537 // Write X as an signed LEB value at offset Offset in Stream, padded
540538 // to allow patching.
541 static void
542 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
539 static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
540 uint64_t Offset) {
543541 uint8_t Buffer[5];
544542 unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
545543 assert(SizeLen == 5);
553551 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
554552 }
555553
556 static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
554 static const MCSymbolWasm *ResolveSymbol(const MCSymbolWasm &Symbol) {
557555 if (Symbol.isVariable()) {
558556 const MCExpr *Expr = Symbol.getVariableValue();
559557 auto *Inner = cast(Expr);
625623 report_fatal_error("only byte values supported for alignment");
626624 // If nops are requested, use zeros, as this is the data section.
627625 uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
628 uint64_t Size = std::min(alignTo(DataBytes.size(),
629 Align->getAlignment()),
630 DataBytes.size() +
631 Align->getMaxBytesToEmit());
626 uint64_t Size =
627 std::min(alignTo(DataBytes.size(), Align->getAlignment()),
628 DataBytes.size() + Align->getMaxBytesToEmit());
632629 DataBytes.resize(Size, Value);
633630 } else if (auto *Fill = dyn_cast(&Frag)) {
634631 int64_t NumValues;
744741 W.OS << char(Import.Global.Mutable ? 1 : 0);
745742 break;
746743 case wasm::WASM_EXTERNAL_MEMORY:
747 encodeULEB128(0, W.OS); // flags
744 encodeULEB128(0, W.OS); // flags
748745 encodeULEB128(NumPages, W.OS); // initial
749746 break;
750747 case wasm::WASM_EXTERNAL_TABLE:
751748 W.OS << char(Import.Table.ElemType);
752 encodeULEB128(0, W.OS); // flags
749 encodeULEB128(0, W.OS); // flags
753750 encodeULEB128(NumElements, W.OS); // initial
754751 break;
755752 default:
891888
892889 void WasmObjectWriter::writeRelocSection(
893890 uint32_t SectionIndex, StringRef Name,
894 std::vector& Relocs) {
891 std::vector &Relocs) {
895892 // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
896893 // for descriptions of the reloc sections.
897894
915912
916913 encodeULEB128(SectionIndex, W.OS);
917914 encodeULEB128(Relocs.size(), W.OS);
918 for (const WasmRelocationEntry& RelEntry : Relocs) {
919 uint64_t Offset = RelEntry.Offset +
920 RelEntry.FixupSection->getSectionOffset();
915 for (const WasmRelocationEntry &RelEntry : Relocs) {
916 uint64_t Offset =
917 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
921918 uint32_t Index = getRelocationIndexValue(RelEntry);
922919
923920 W.OS << char(RelEntry.Type);
995992 startSection(SubSection, wasm::WASM_INIT_FUNCS);
996993 encodeULEB128(InitFuncs.size(), W.OS);
997994 for (auto &StartFunc : InitFuncs) {
998 encodeULEB128(StartFunc.first, W.OS); // priority
995 encodeULEB128(StartFunc.first, W.OS); // priority
999996 encodeULEB128(StartFunc.second, W.OS); // function index
1000997 }
1001998 endSection(SubSection);
10401037 }
10411038 }
10421039
1043 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
1040 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
10441041 assert(Symbol.isFunction());
10451042 assert(TypeIndices.count(&Symbol));
10461043 return TypeIndices[&Symbol];
10471044 }
10481045
1049 uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
1046 uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
10501047 assert(Symbol.isFunction());
10511048
10521049 WasmFunctionType F;
1053 const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
1050 const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
10541051 F.Returns = ResolvedSym->getReturns();
10551052 F.Params = ResolvedSym->getParams();
10561053
12061203 if (Name.startswith(".custom_section."))
12071204 Name = Name.substr(strlen(".custom_section."));
12081205
1209 MCSymbol* Begin = Sec.getBeginSymbol();
1206 MCSymbol *Begin = Sec.getBeginSymbol();
12101207 if (Begin) {
12111208 WasmIndices[cast(Begin)] = CustomSections.size();
12121209 if (SectionName != Begin->getName())
14351432 unsigned PrefixLength = strlen(".init_array");
14361433 if (WS.getSectionName().size() > PrefixLength) {
14371434 if (WS.getSectionName()[PrefixLength] != '.')
1438 report_fatal_error(".init_array section priority should start with '.'");
1435 report_fatal_error(
1436 ".init_array section priority should start with '.'");
14391437 if (WS.getSectionName()
14401438 .substr(PrefixLength + 1)
14411439 .getAsInteger(10, Priority))
14431441 }
14441442 const auto &DataFrag = cast(Frag);
14451443 const SmallVectorImpl &Contents = DataFrag.getContents();
1446 for (const uint8_t *p = (const uint8_t *)Contents.data(),
1447 *end = (const uint8_t *)Contents.data() + Contents.size();
1444 for (const uint8_t *
1445 p = (const uint8_t *)Contents.data(),
1446 *end = (const uint8_t *)Contents.data() + Contents.size();
14481447 p != end; ++p) {
14491448 if (*p != 0)
14501449 report_fatal_error("non-symbolic data in .init_array section");
14511450 }
14521451 for (const MCFixup &Fixup : DataFrag.getFixups()) {
1453 assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1452 assert(Fixup.getKind() ==
1453 MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
14541454 const MCExpr *Expr = Fixup.getValue();
14551455 auto *Sym = dyn_cast(Expr);
14561456 if (!Sym)
3636
3737 void WasmSymbol::print(raw_ostream &Out) const {
3838 Out << "Name=" << Info.Name
39 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
40 << ", Flags=" << Info.Flags;
39 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
40 << ", Flags=" << Info.Flags;
4141 if (!isTypeData()) {
4242 Out << ", ElemIndex=" << Info.ElementIndex;
4343 } else if (isDefined()) {
6161 return std::move(ObjectFile);
6262 }
6363
64 #define VARINT7_MAX ((1<<7)-1)
65 #define VARINT7_MIN (-(1<<7))
66 #define VARUINT7_MAX (1<<7)
64 #define VARINT7_MAX ((1 << 7) - 1)
65 #define VARINT7_MIN (-(1 << 7))
66 #define VARUINT7_MAX (1 << 7)
6767 #define VARUINT1_MAX (1)
6868
6969 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
100100
101101 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
102102 unsigned Count;
103 const char* Error = nullptr;
103 const char *Error = nullptr;
104104 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
105105 if (Error)
106106 report_fatal_error(Error);
120120
121121 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
122122 unsigned Count;
123 const char* Error = nullptr;
123 const char *Error = nullptr;
124124 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
125125 if (Error)
126126 report_fatal_error(Error);
240240 ErrorAsOutParameter ErrAsOutParam(&Err);
241241 Header.Magic = getData().substr(0, 4);
242242 if (Header.Magic != StringRef("\0asm", 4)) {
243 Err = make_error("Bad magic number",
244 object_error::parse_failed);
243 Err =
244 make_error("Bad magic number", object_error::parse_failed);
245245 return;
246246 }
247247
346346 break;
347347 }
348348 if (Ctx.Ptr != SubSectionEnd)
349 return make_error("Name sub-section ended prematurely",
350 object_error::parse_failed);
349 return make_error(
350 "Name sub-section ended prematurely", object_error::parse_failed);
351351 }
352352
353353 if (Ctx.Ptr != Ctx.End)
360360 HasLinkingSection = true;
361361 if (Functions.size() != FunctionTypes.size()) {
362362 return make_error(
363 "Linking data must come after code section", object_error::parse_failed);
363 "Linking data must come after code section",
364 object_error::parse_failed);
364365 }
365366
366367 LinkingData.Version = readVaruint32(Ctx);
483484 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
484485 return make_error("invalid global symbol index",
485486 object_error::parse_failed);
486 if (!IsDefined &&
487 (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
488 wasm::WASM_SYMBOL_BINDING_WEAK)
487 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
488 wasm::WASM_SYMBOL_BINDING_WEAK)
489489 return make_error("undefined weak global symbol",
490490 object_error::parse_failed);
491491 if (IsDefined) {
557557 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
558558 StringRef Name = readString(Ctx);
559559 if (Name.empty() || !ComdatSet.insert(Name).second)
560 return make_error("Bad/duplicate COMDAT name " + Twine(Name),
560 return make_error("Bad/duplicate COMDAT name " +
561 Twine(Name),
561562 object_error::parse_failed);
562563 LinkingData.Comdats.emplace_back(Name);
563564 uint32_t Flags = readVaruint32(Ctx);
575576 object_error::parse_failed);
576577 case wasm::WASM_COMDAT_DATA:
577578 if (Index >= DataSegments.size())
578 return make_error("COMDAT data index out of range",
579 object_error::parse_failed);
579 return make_error(
580 "COMDAT data index out of range", object_error::parse_failed);
580581 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
581582 return make_error("Data segment in two COMDATs",
582583 object_error::parse_failed);
584585 break;
585586 case wasm::WASM_COMDAT_FUNCTION:
586587 if (!isDefinedFunctionIndex(Index))
587 return make_error("COMDAT function index out of range",
588 object_error::parse_failed);
588 return make_error(
589 "COMDAT function index out of range", object_error::parse_failed);
589590 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
590591 return make_error("Function in two COMDATs",
591592 object_error::parse_failed);
602603 if (SectionIndex >= Sections.size())
603604 return make_error("Invalid section index",
604605 object_error::parse_failed);
605 WasmSection& Section = Sections[SectionIndex];
606 WasmSection &Section = Sections[SectionIndex];
606607 uint32_t RelocCount = readVaruint32(Ctx);
607608 uint32_t EndOffset = Section.Content.size();
608609 uint32_t PreviousOffset = 0;
755756 object_error::parse_failed);
756757 break;
757758 default:
758 return make_error(
759 "Unexpected import kind", object_error::parse_failed);
759 return make_error("Unexpected import kind",
760 object_error::parse_failed);
760761 }
761762 Imports.push_back(Im);
762763 }
853854 case wasm::WASM_EXTERNAL_TABLE:
854855 break;
855856 default:
856 return make_error(
857 "Unexpected export kind", object_error::parse_failed);
857 return make_error("Unexpected export kind",
858 object_error::parse_failed);
858859 }
859860 Exports.push_back(Ex);
860861 }
10651066 return getSymbolValue(Symb);
10661067 }
10671068
1068 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
1069 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
10691070 switch (Sym.Info.Kind) {
10701071 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
10711072 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
11191120
11201121 Expected
11211122 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1122 const WasmSymbol& Sym = getWasmSymbol(Symb);
1123 const WasmSymbol &Sym = getWasmSymbol(Symb);
11231124 if (Sym.isUndefined())
11241125 return section_end();
11251126
12331234 return relocation_iterator(RelocationRef(RelocRef, this));
12341235 }
12351236
1236 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1237 Rel.d.b++;
1238 }
1237 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
12391238
12401239 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
12411240 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
12591258
12601259 void WasmObjectFile::getRelocationTypeName(
12611260 DataRefImpl Ref, SmallVectorImpl &Result) const {
1262 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
1261 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
12631262 StringRef Res = "Unknown";
12641263
1265 #define WASM_RELOC(name, value) \
1266 case wasm::name: \
1267 Res = #name; \
1264 #define WASM_RELOC(name, value) \
1265 case wasm::name: \
1266 Res = #name; \
12681267 break;
12691268
12701269 switch (Rel.Type) {
12981297 return SubtargetFeatures();
12991298 }
13001299
1301 bool WasmObjectFile::isRelocatableObject() const {
1302 return HasLinkingSection;
1303 }
1300 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
13041301
13051302 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
13061303 assert(Ref.d.a < Sections.size());
13201317 const wasm::WasmRelocation &
13211318 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
13221319 assert(Ref.d.a < Sections.size());
1323 const WasmSection& Sec = Sections[Ref.d.a];
1320 const WasmSection &Sec = Sections[Ref.d.a];
13241321 assert(Ref.d.b < Sec.Relocations.size());
13251322 return Sec.Relocations[Ref.d.b];
13261323 }
308308 IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
309309 } else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
310310 IO.mapRequired("Table", Import.TableImport);
311 } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY ) {
311 } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY) {
312312 IO.mapRequired("Memory", Import.Memory);
313313 } else {
314314 llvm_unreachable("unhandled import type");
382382 IO.mapRequired("Index", ComdatEntry.Index);
383383 }
384384
385 void MappingTraits::mapping(
386 IO &IO, WasmYAML::Comdat &Comdat) {
385 void MappingTraits::mapping(IO &IO,
386 WasmYAML::Comdat &Comdat) {
387387 IO.mapRequired("Name", Comdat.Name);
388388 IO.mapRequired("Entries", Comdat.Entries);
389389 }
419419 }
420420
421421 void ScalarBitSetTraits::bitset(
422 IO &IO, WasmYAML::SegmentFlags &Value) {
423 }
422 IO &IO, WasmYAML::SegmentFlags &Value) {}
424423
425424 void ScalarBitSetTraits::bitset(
426425 IO &IO, WasmYAML::SymbolFlags &Value) {
427 #define BCaseMask(M, X) IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M)
428 //BCaseMask(BINDING_MASK, BINDING_GLOBAL);
426 #define BCaseMask(M, X) \
427 IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M)
428 // BCaseMask(BINDING_MASK, BINDING_GLOBAL);
429429 BCaseMask(BINDING_MASK, BINDING_WEAK);
430430 BCaseMask(BINDING_MASK, BINDING_LOCAL);
431 //BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
431 // BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
432432 BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN);
433433 BCaseMask(UNDEFINED, UNDEFINED);
434434 #undef BCaseMask
1717 #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
1818 #include "WebAssembly.h"
1919 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
21 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
2220 #include "llvm/MC/MCInst.h"
2321 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
24 #include "llvm/MC/MCStreamer.h"
2425 #include "llvm/MC/MCSubtargetInfo.h"
2526 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/MCStreamer.h"
2727 #include "llvm/Support/Endian.h"
2828 #include "llvm/Support/TargetRegistry.h"
2929
6464 };
6565
6666 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
67 : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
67 : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
6868 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
69 : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
69 : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
7070 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
71 : Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {}
71 : Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {}
7272 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, SymOp S)
73 : Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
73 : Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
7474
7575 bool isToken() const override { return Kind == Token; }
76 bool isImm() const override { return Kind == Integer ||
77 Kind == Float ||
78 Kind == Symbol; }
76 bool isImm() const override {
77 return Kind == Integer || Kind == Float || Kind == Symbol;
78 }
7979 bool isMem() const override { return false; }
8080 bool isReg() const override { return false; }
8181
144144 #include "WebAssemblyGenAsmMatcher.inc"
145145
146146 // TODO: This is required to be implemented, but appears unused.
147 bool ParseRegister(unsigned &/*RegNo*/, SMLoc &/*StartLoc*/,
148 SMLoc &/*EndLoc*/) override {
147 bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
148 SMLoc & /*EndLoc*/) override {
149149 llvm_unreachable("ParseRegister is not implemented.");
150150 }
151151
155155
156156 bool IsNext(AsmToken::TokenKind Kind) {
157157 auto ok = Lexer.is(Kind);
158 if (ok) Parser.Lex();
158 if (ok)
159 Parser.Lex();
159160 return ok;
160161 }
161162
189190 void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
190191 auto &Int = Lexer.getTok();
191192 int64_t Val = Int.getIntVal();
192 if (IsNegative) Val = -Val;
193 if (IsNegative)
194 Val = -Val;
193195 Operands.push_back(make_unique(
194 WebAssemblyOperand::Integer, Int.getLoc(),
195 Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
196 WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
197 WebAssemblyOperand::IntOp{Val}));
196198 Parser.Lex();
197199 }
198200
199 bool ParseOperandStartingWithInteger(bool IsNegative,
200 OperandVector &Operands,
201 bool ParseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands,
201202 StringRef InstName) {
202203 ParseSingleInteger(IsNegative, Operands);
203204 // FIXME: there is probably a cleaner way to do this.
216217 // We can't just call WebAssembly::GetDefaultP2Align since we don't have
217218 // an opcode until after the assembly matcher.
218219 Operands.push_back(make_unique(
219 WebAssemblyOperand::Integer, Offset.getLoc(),
220 Offset.getEndLoc(), WebAssemblyOperand::IntOp{0}));
220 WebAssemblyOperand::Integer, Offset.getLoc(), Offset.getEndLoc(),
221 WebAssemblyOperand::IntOp{0}));
221222 }
222223 }
223224 return false;
224225 }
225226
226 bool ParseInstruction(ParseInstructionInfo &/*Info*/, StringRef Name,
227 bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
227228 SMLoc NameLoc, OperandVector &Operands) override {
228 Operands.push_back(
229 make_unique(WebAssemblyOperand::Token, NameLoc,
230 SMLoc::getFromPointer(
231 NameLoc.getPointer() + Name.size()),
232 WebAssemblyOperand::TokOp{
233 StringRef(NameLoc.getPointer(),
234 Name.size())}));
229 Operands.push_back(make_unique(
230 WebAssemblyOperand::Token, NameLoc,
231 SMLoc::getFromPointer(NameLoc.getPointer() + Name.size()),
232 WebAssemblyOperand::TokOp{
233 StringRef(NameLoc.getPointer(), Name.size())}));
235234 auto NamePair = Name.split('.');
236235 // If no '.', there is no type prefix.
237 if (NamePair.second.empty()) std::swap(NamePair.first, NamePair.second);
236 if (NamePair.second.empty())
237 std::swap(NamePair.first, NamePair.second);
238238 while (Lexer.isNot(AsmToken::EndOfStatement)) {
239239 auto &Tok = Lexer.getTok();
240240 switch (Tok.getKind()) {
245245 if (Parser.parsePrimaryExpr(Val, End))
246246 return Error("Cannot parse symbol: ", Lexer.getTok());
247247 Operands.push_back(make_unique(
248 WebAssemblyOperand::Symbol, Id.getLoc(),
249 Id.getEndLoc(), WebAssemblyOperand::SymOp{Val}));
248 WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
249 WebAssemblyOperand::SymOp{Val}));
250250 break;
251251 }
252252 case AsmToken::Minus:
265265 if (Tok.getString().getAsDouble(Val, false))
266266 return Error("Cannot parse real: ", Tok);
267267 Operands.push_back(make_unique(
268 WebAssemblyOperand::Float, Tok.getLoc(),
269 Tok.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
268 WebAssemblyOperand::Float, Tok.getLoc(), Tok.getEndLoc(),
269 WebAssemblyOperand::FltOp{Val}));
270270 Parser.Lex();
271271 break;
272272 }
274274 return Error("Unexpected token in operand: ", Tok);
275275 }
276276 if (Lexer.isNot(AsmToken::EndOfStatement)) {
277 if (Expect(AsmToken::Comma, ",")) return true;
277 if (Expect(AsmToken::Comma, ","))
278 return true;
278279 }
279280 }
280281 Parser.Lex();
284285 // the wasm module is generated).
285286 if (NamePair.second == "block" || NamePair.second == "loop") {
286287 Operands.push_back(make_unique(
287 WebAssemblyOperand::Integer, NameLoc,
288 NameLoc, WebAssemblyOperand::IntOp{-1}));
288 WebAssemblyOperand::Integer, NameLoc, NameLoc,
289 WebAssemblyOperand::IntOp{-1}));
289290 }
290291 return false;
291292 }
292293
293 void onLabelParsed(MCSymbol *Symbol) override {
294 LastLabel = Symbol;
295 }
294 void onLabelParsed(MCSymbol *Symbol) override { LastLabel = Symbol; }
296295
297296 bool ParseDirective(AsmToken DirectiveID) override {
298297 assert(DirectiveID.getKind() == AsmToken::Identifier);
299298 auto &Out = getStreamer();
300 auto &TOut = reinterpret_cast(
301 *Out.getTargetStreamer());
299 auto &TOut =
300 reinterpret_cast(*Out.getTargetStreamer());
302301 // TODO: we're just parsing the subset of directives we're interested in,
303302 // and ignoring ones we don't recognise. We should ideally verify
304303 // all directives here.
305304 if (DirectiveID.getString() == ".type") {
306305 // This could be the start of a function, check if followed by
307306 // "label,@function"
308 if (!(IsNext(AsmToken::Identifier) &&
309 IsNext(AsmToken::Comma) &&
310 IsNext(AsmToken::At) &&
311 Lexer.is(AsmToken::Identifier)))
307 if (!(IsNext(AsmToken::Identifier) && IsNext(AsmToken::Comma) &&
308 IsNext(AsmToken::At) && Lexer.is(AsmToken::Identifier)))
312309 return Error("Expected label,@type declaration, got: ", Lexer.getTok());
313310 Parser.Lex();
314 //Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
311 // Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
315312 } else if (DirectiveID.getString() == ".param" ||
316313 DirectiveID.getString() == ".local") {
317314 // Track the number of locals, needed for correct virtual register
321318 std::vector Locals;
322319 while (Lexer.is(AsmToken::Identifier)) {
323320 auto RegType = ParseRegType(Lexer.getTok().getString());
324 if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE) return true;
321 if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
322 return true;
325323 if (DirectiveID.getString() == ".param") {
326324 Params.push_back(RegType);
327325 } else {
328326 Locals.push_back(RegType);
329327 }
330328 Parser.Lex();
331 if (!IsNext(AsmToken::Comma)) break;
329 if (!IsNext(AsmToken::Comma))
330 break;
332331 }
333332 assert(LastLabel);
334333 TOut.emitParam(LastLabel, Params);
335334 TOut.emitLocal(Locals);
336335 } else {
337336 // For now, ignore anydirective we don't recognize:
338 while (Lexer.isNot(AsmToken::EndOfStatement)) Parser.Lex();
337 while (Lexer.isNot(AsmToken::EndOfStatement))
338 Parser.Lex();
339339 }
340340 return Expect(AsmToken::EndOfStatement, "EOL");
341341 }
342342
343 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &/*Opcode*/,
344 OperandVector &Operands,
345 MCStreamer &Out, uint64_t &ErrorInfo,
343 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
344 OperandVector &Operands, MCStreamer &Out,
345 uint64_t &ErrorInfo,
346346 bool MatchingInlineAsm) override {
347347 MCInst Inst;
348348 unsigned MatchResult =
353353 return false;
354354 }
355355 case Match_MissingFeature:
356 return Parser.Error(IDLoc,
357 "instruction requires a WASM feature not currently enabled");
356 return Parser.Error(
357 IDLoc, "instruction requires a WASM feature not currently enabled");
358358 case Match_MnemonicFail:
359359 return Parser.Error(IDLoc, "invalid instruction");
360360 case Match_NearMisses:
5656 // FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because
5757 // we have an extra flags operand which is not currently printed, for
5858 // compatiblity reasons.
59 if (i != 0 &&
60 ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
61 MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
62 i != Desc.getNumOperands()))
59 if (i != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
60 MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
61 i != Desc.getNumOperands()))
6362 OS << ", ";
6463 printOperand(MI, i, OS);
6564 }
8786 case WebAssembly::END_LOOP_S:
8887 // Have to guard against an empty stack, in case of mismatched pairs
8988 // in assembly parsing.
90 if (!ControlFlowStack.empty()) ControlFlowStack.pop_back();
89 if (!ControlFlowStack.empty())
90 ControlFlowStack.pop_back();
9191 break;
9292 case WebAssembly::END_BLOCK:
9393 case WebAssembly::END_BLOCK_S:
94 if (!ControlFlowStack.empty()) printAnnotation(
95 OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
94 if (!ControlFlowStack.empty())
95 printAnnotation(
96 OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
9697 break;
9798 }
9899
117118
118119 static std::string toString(const APFloat &FP) {
119120 // Print NaNs with custom payloads specially.
120 if (FP.isNaN() &&
121 !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
121 if (FP.isNaN() && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
122122 !FP.bitwiseIsEqual(
123123 APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) {
124124 APInt AI = FP.bitcastToAPInt();
125 return
126 std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
127 utohexstr(AI.getZExtValue() &
128 (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) :
129 INT64_C(0x000fffffffffffff)),
130 /*LowerCase=*/true);
125 return std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
126 utohexstr(AI.getZExtValue() &
127 (AI.getBitWidth() == 32 ? INT64_C(0x007fffff)
128 : INT64_C(0x000fffffffffffff)),
129 /*LowerCase=*/true);
131130 }
132131
133132 // Use C99's hexadecimal floating-point representation.
198197 }
199198 }
200199
201 void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(
202 const MCInst *MI, unsigned OpNo, raw_ostream &O) {
200 void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI,
201 unsigned OpNo,
202 raw_ostream &O) {
203203 int64_t Imm = MI->getOperand(OpNo).getImm();
204204 if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode()))
205205 return;
206206 O << ":p2align=" << Imm;
207207 }
208208
209 void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(
210 const MCInst *MI, unsigned OpNo, raw_ostream &O) {
209 void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
210 unsigned OpNo,
211 raw_ostream &O) {
211212 int64_t Imm = MI->getOperand(OpNo).getImm();
212213 switch (WebAssembly::ExprType(Imm)) {
213 case WebAssembly::ExprType::Void: break;
214 case WebAssembly::ExprType::I32: O << "i32"; break;
215 case WebAssembly::ExprType::I64: O << "i64"; break;
216 case WebAssembly::ExprType::F32: O << "f32"; break;
217 case WebAssembly::ExprType::F64: O << "f64"; break;
218 case WebAssembly::ExprType::V128: O << "v128"; break;
219 case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break;
214 case WebAssembly::ExprType::Void:
215 break;
216 case WebAssembly::ExprType::I32:
217 O << "i32";
218 break;
219 case WebAssembly::ExprType::I64:
220 O << "i64";
221 break;
222 case WebAssembly::ExprType::F32:
223 O << "f32";
224 break;
225 case WebAssembly::ExprType::F64:
226 O << "f64";
227 break;
228 case WebAssembly::ExprType::V128:
229 O << "v128";
230 break;
231 case WebAssembly::ExprType::ExceptRef:
232 O << "except_ref";
233 break;
220234 }
221235 }
222236
7272 const MCFixupKindInfo &
7373 WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
7474 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
75 // This table *must* be in the order that the fixup_* kinds are defined in
76 // WebAssemblyFixupKinds.h.
77 //
78 // Name Offset (bits) Size (bits) Flags
79 { "fixup_code_sleb128_i32", 0, 5*8, 0 },
80 { "fixup_code_sleb128_i64", 0, 10*8, 0 },
81 { "fixup_code_uleb128_i32", 0, 5*8, 0 },
75 // This table *must* be in the order that the fixup_* kinds are defined in
76 // WebAssemblyFixupKinds.h.
77 //
78 // Name Offset (bits) Size (bits) Flags
79 {"fixup_code_sleb128_i32", 0, 5 * 8, 0},
80 {"fixup_code_sleb128_i64", 0, 10 * 8, 0},
81 {"fixup_code_uleb128_i32", 0, 5 * 8, 0},
8282 };
8383
8484 if (Kind < FirstTargetFixupKind)
1414 namespace llvm {
1515 namespace WebAssembly {
1616 enum Fixups {
17 fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed
18 fixup_code_sleb128_i64, // 64-bit signed
19 fixup_code_uleb128_i32, // 32-bit unsigned
17 fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed
18 fixup_code_sleb128_i64, // 64-bit signed
19 fixup_code_uleb128_i32, // 32-bit unsigned
2020
2121 // Marker
2222 LastTargetFixupKind,
6666 OS << uint8_t(Binary);
6767 } else {
6868 assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet");
69 OS << uint8_t(Binary >> 8)
70 << uint8_t(Binary);
69 OS << uint8_t(Binary >> 8) << uint8_t(Binary);
7170 }
7271
7372 // For br_table instructions, encode the size of the table. In the MCInst,
161160 } else {
162161 llvm_unreachable("unexpected symbolic operand kind");
163162 }
164 Fixups.push_back(MCFixup::create(
165 OS.tell() - Start, MO.getExpr(),
166 FixupKind, MI.getLoc()));
163 Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
164 FixupKind, MI.getLoc()));
167165 ++MCNumFixups;
168166 encodeULEB128(0, OS, PaddedSize);
169167 } else {
124124
125125 wasm::ValType WebAssembly::toValType(const MVT &Ty) {
126126 switch (Ty.SimpleTy) {
127 case MVT::i32: return wasm::ValType::I32;
128 case MVT::i64: return wasm::ValType::I64;
129 case MVT::f32: return wasm::ValType::F32;
130 case MVT::f64: return wasm::ValType::F64;
131 case MVT::ExceptRef: return wasm::ValType::EXCEPT_REF;
132 default: llvm_unreachable("unexpected type");
127 case MVT::i32:
128 return wasm::ValType::I32;
129 case MVT::i64:
130 return wasm::ValType::I64;
131 case MVT::f32:
132 return wasm::ValType::F32;
133 case MVT::f64:
134 return wasm::ValType::F64;
135 case MVT::ExceptRef:
136 return wasm::ValType::EXCEPT_REF;
137 default:
138 llvm_unreachable("unexpected type");
133139 }
134140 }
9595
9696 // Flags to indicate the type of the symbol being referenced
9797 MO_SYMBOL_FUNCTION = 0x1,
98 MO_SYMBOL_GLOBAL = 0x2,
99 MO_SYMBOL_MASK = 0x3,
98 MO_SYMBOL_GLOBAL = 0x2,
99 MO_SYMBOL_MASK = 0x3,
100100 };
101101 } // end namespace WebAssemblyII
102102
8484 void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
8585
8686 void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
87 MCSymbol *Symbol, SmallVectorImpl &Params, SmallVectorImpl &Results) {
87 MCSymbol *Symbol, SmallVectorImpl &Params,
88 SmallVectorImpl &Results) {
8889 OS << "\t.functype\t" << Symbol->getName();
8990 if (Results.empty())
9091 OS << ", void";
6464 void emitResult(MCSymbol *Symbol, ArrayRef Types) override;
6565 void emitLocal(ArrayRef Types) override;
6666 void emitEndFunc() override;
67 void emitIndirectFunctionType(MCSymbol *Symbol,
68 SmallVectorImpl &Params,
67 void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl &Params,
6968 SmallVectorImpl &Results) override;
7069 void emitIndIdx(const MCExpr *Value) override;
7170 void emitGlobalImport(StringRef name) override;
8180 void emitResult(MCSymbol *Symbol, ArrayRef Types) override;
8281 void emitLocal(ArrayRef Types) override;
8382 void emitEndFunc() override;
84 void emitIndirectFunctionType(MCSymbol *Symbol,
85 SmallVectorImpl &Params,
83 void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl &Params,
8684 SmallVectorImpl &Results) override;
8785 void emitIndIdx(const MCExpr *Value) override;
8886 void emitGlobalImport(StringRef name) override;
8585 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
8686 }
8787
88 unsigned
89 WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
90 const MCFixup &Fixup) const {
88 unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
89 const MCFixup &Fixup) const {
9190 // WebAssembly functions are not allocated in the data address space. To
9291 // resolve a pointer to a function, we must use a special relocation type.
9392 bool IsFunction = IsFunctionExpr(Fixup.getValue());
2323 #include "llvm/IR/IRBuilder.h"
2424 #include "llvm/IR/Module.h"
2525 #include "llvm/IR/Operator.h"
26 #include "llvm/Transforms/Utils/ModuleUtils.h"
27 #include "llvm/Transforms/Utils/Local.h"
2826 #include "llvm/Pass.h"
2927 #include "llvm/Support/Debug.h"
28 #include "llvm/Transforms/Utils/Local.h"
29 #include "llvm/Transforms/Utils/ModuleUtils.h"
3030 using namespace llvm;
3131
3232 #define DEBUG_TYPE "wasm-add-missing-prototypes"
6161 bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
6262 LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n");
6363
64 std::vector*, Function*>> Replacements;
64 std::vector *, Function *>> Replacements;
6565
6666 // Find all the prototype-less function declarations
6767 for (Function &F : M) {
6868 if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
6969 continue;
7070
71 LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName() << "\n");
71 LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName()
72 << "\n");
7273
7374 // When clang emits prototype-less C functions it uses (...), i.e. varargs
7475 // function that take no arguments (have no sentinel). When we see a
8283 "Functions with 'no-prototype' attribute should not have params: " +
8384 F.getName());
8485
85
8686 // Create a function prototype based on the first call site (first bitcast)
8787 // that we find.
8888 FunctionType *NewType = nullptr;
89 Function* NewF = nullptr;
89 Function *NewF = nullptr;
9090 for (Use &U : F.uses()) {
9191 LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
9292 if (BitCastOperator *BC = dyn_cast(U.getUser())) {
133133
134134 // Finally replace the old function declarations with the new ones
135135 for (auto &Pair : Replacements) {
136 Function* Old = Pair.first;
137 Function* New = Pair.second;
136 Function *Old = Pair.first;
137 Function *New = Pair.second;
138138 Old->eraseFromParent();
139139 M.getFunctionList().push_back(New);
140140 }
8989 if (TM.getTargetTriple().isOSBinFormatWasm() &&
9090 F.hasFnAttribute("wasm-import-module")) {
9191 MCSymbolWasm *WasmSym = cast(Sym);
92 StringRef Name = F.getFnAttribute("wasm-import-module")
93 .getValueAsString();
92 StringRef Name =
93 F.getFnAttribute("wasm-import-module").getValueAsString();
9494 getTargetStreamer()->emitImportModule(WasmSym, Name);
9595 }
9696 }
2828 public:
2929 explicit WebAssemblyAsmPrinter(TargetMachine &TM,
3030 std::unique_ptr Streamer)
31 : AsmPrinter(TM, std::move(Streamer)),
32 Subtarget(nullptr), MRI(nullptr), MFI(nullptr) {}
31 : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), MRI(nullptr),
32 MFI(nullptr) {}
3333
3434 StringRef getPassName() const override {
3535 return "WebAssembly Assembly Printer";
9696
9797 char WebAssemblyCFGStackify::ID = 0;
9898 INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
99 "Insert BLOCK and LOOP markers for WebAssembly scopes",
100 false, false)
99 "Insert BLOCK and LOOP markers for WebAssembly scopes", false,
100 false)
101101
102102 FunctionPass *llvm::createWebAssemblyCFGStackify() {
103103 return new WebAssemblyCFGStackify();
632632
633633 WebAssembly::ExprType retType;
634634 switch (MFI.getResults().front().SimpleTy) {
635 case MVT::i32: retType = WebAssembly::ExprType::I32; break;
636 case MVT::i64: retType = WebAssembly::ExprType::I64; break;
637 case MVT::f32: retType = WebAssembly::ExprType::F32; break;
638 case MVT::f64: retType = WebAssembly::ExprType::F64; break;
635 case MVT::i32:
636 retType = WebAssembly::ExprType::I32;
637 break;
638 case MVT::i64:
639 retType = WebAssembly::ExprType::I64;
640 break;
641 case MVT::f32:
642 retType = WebAssembly::ExprType::F32;
643 break;
644 case MVT::f64:
645 retType = WebAssembly::ExprType::F64;
646 break;
639647 case MVT::v16i8:
640648 case MVT::v8i16:
641649 case MVT::v4i32:
644652 case MVT::v2f64:
645653 retType = WebAssembly::ExprType::V128;
646654 break;
647 case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break;
648 default: llvm_unreachable("unexpected return type");
655 case MVT::ExceptRef:
656 retType = WebAssembly::ExprType::ExceptRef;
657 break;
658 default:
659 llvm_unreachable("unexpected return type");
649660 }
650661
651662 for (MachineBasicBlock &MBB : reverse(MF)) {
668679
669680 // WebAssembly functions end with an end instruction, as if the function body
670681 // were a block.
671 static void AppendEndToFunction(
672 MachineFunction &MF,
673 const WebAssemblyInstrInfo &TII) {
682 static void AppendEndToFunction(MachineFunction &MF,
683 const WebAssemblyInstrInfo &TII) {
674684 BuildMI(MF.back(), MF.back().end(),
675685 MF.back().findPrevDebugLoc(MF.back().end()),
676686 TII.get(WebAssembly::END_FUNCTION));
6363 static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
6464 switch (MI.getOpcode()) {
6565 using namespace WebAssembly;
66 case PCALL_INDIRECT_VOID: return CALL_INDIRECT_VOID;
67 case PCALL_INDIRECT_I32: return CALL_INDIRECT_I32;
68 case PCALL_INDIRECT_I64: return CALL_INDIRECT_I64;
69 case PCALL_INDIRECT_F32: return CALL_INDIRECT_F32;
70 case PCALL_INDIRECT_F64: return CALL_INDIRECT_F64;
71 case PCALL_INDIRECT_v16i8: return CALL_INDIRECT_v16i8;
72 case PCALL_INDIRECT_v8i16: return CALL_INDIRECT_v8i16;
73 case PCALL_INDIRECT_v4i32: return CALL_INDIRECT_v4i32;
74 case PCALL_INDIRECT_v2i64: return CALL_INDIRECT_v2i64;
75 case PCALL_INDIRECT_v4f32: return CALL_INDIRECT_v4f32;
76 case PCALL_INDIRECT_v2f64: return CALL_INDIRECT_v2f64;
77 default: return INSTRUCTION_LIST_END;
66 case PCALL_INDIRECT_VOID:
67 return CALL_INDIRECT_VOID;
68 case PCALL_INDIRECT_I32:
69 return CALL_INDIRECT_I32;
70 case PCALL_INDIRECT_I64:
71 return CALL_INDIRECT_I64;
72 case PCALL_INDIRECT_F32:
73 return CALL_INDIRECT_F32;
74 case PCALL_INDIRECT_F64:
75 return CALL_INDIRECT_F64;
76 case PCALL_INDIRECT_v16i8:
77 return CALL_INDIRECT_v16i8;
78 case PCALL_INDIRECT_v8i16:
79 return CALL_INDIRECT_v8i16;
80 case PCALL_INDIRECT_v4i32:
81 return CALL_INDIRECT_v4i32;
82 case PCALL_INDIRECT_v2i64:
83 return CALL_INDIRECT_v2i64;
84 case PCALL_INDIRECT_v4f32:
85 return CALL_INDIRECT_v4f32;
86 case PCALL_INDIRECT_v2f64:
87 return CALL_INDIRECT_v2f64;
88 default:
89 return INSTRUCTION_LIST_END;
7890 }
7991 }
8092
111123 Ops.push_back(MachineOperand::CreateImm(0));
112124
113125 for (const MachineOperand &MO :
114 make_range(MI.operands_begin() +
115 MI.getDesc().getNumDefs() + 1,
116 MI.operands_begin() +
117 MI.getNumExplicitOperands()))
126 make_range(MI.operands_begin() + MI.getDesc().getNumDefs() + 1,
127 MI.operands_begin() + MI.getNumExplicitOperands()))
118128 Ops.push_back(MO);
119129 Ops.push_back(MI.getOperand(MI.getDesc().getNumDefs()));
120130
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "WebAssemblyExceptionInfo.h"
15 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1516 #include "WebAssemblyUtilities.h"
16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1717 #include "llvm/ADT/PostOrderIterator.h"
1818 #include "llvm/CodeGen/MachineDominanceFrontier.h"
1919 #include "llvm/CodeGen/MachineDominators.h"
113113 // Utility helper routines
114114 MVT::SimpleValueType getSimpleType(Type *Ty) {
115115 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
116 return VT.isSimple() ? VT.getSimpleVT().SimpleTy :
117 MVT::INVALID_SIMPLE_VALUE_TYPE;
116 return VT.isSimple() ? VT.getSimpleVT().SimpleTy
117 : MVT::INVALID_SIMPLE_VALUE_TYPE;
118118 }
119119 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
120120 switch (VT) {
154154 MVT::SimpleValueType From);
155155 unsigned signExtendToI32(unsigned Reg, const Value *V,
156156 MVT::SimpleValueType From);
157 unsigned zeroExtend(unsigned Reg, const Value *V,
158 MVT::SimpleValueType From,
157 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
159158 MVT::SimpleValueType To);
160 unsigned signExtend(unsigned Reg, const Value *V,
161 MVT::SimpleValueType From,
159 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
162160 MVT::SimpleValueType To);
163161 unsigned getRegForUnsignedValue(const Value *V);
164162 unsigned getRegForSignedValue(const Value *V);
375373 if (Addr.isRegBase()) {
376374 unsigned Reg = Addr.getReg();
377375 if (Reg == 0) {
378 Reg = createResultReg(Subtarget->hasAddr64() ?
379 &WebAssembly::I64RegClass :
380 &WebAssembly::I32RegClass);
381 unsigned Opc = Subtarget->hasAddr64() ?
382 WebAssembly::CONST_I64 :
383 WebAssembly::CONST_I32;
376 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
377 : &WebAssembly::I32RegClass);
378 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
379 : WebAssembly::CONST_I32;
384380 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
385 .addImm(0);
381 .addImm(0);
386382 Addr.setReg(Reg);
387383 }
388384 }
458454 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
459455 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
460456 TII.get(WebAssembly::CONST_I32), Imm)
461 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
457 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
462458
463459 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
464460 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
465461 TII.get(WebAssembly::AND_I32), Result)
466 .addReg(Reg)
467 .addReg(Imm);
462 .addReg(Reg)
463 .addReg(Imm);
468464
469465 return Result;
470466 }
488484 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
489485 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
490486 TII.get(WebAssembly::CONST_I32), Imm)
491 .addImm(32 - MVT(From).getSizeInBits());
487 .addImm(32 - MVT(From).getSizeInBits());
492488
493489 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
494490 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
495491 TII.get(WebAssembly::SHL_I32), Left)
496 .addReg(Reg)
497 .addReg(Imm);
492 .addReg(Reg)
493 .addReg(Imm);
498494
499495 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
500496 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
501497 TII.get(WebAssembly::SHR_S_I32), Right)
502 .addReg(Left)
503 .addReg(Imm);
498 .addReg(Left)
499 .addReg(Imm);
504500
505501 return Right;
506502 }
563559
564560 unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
565561 bool IsSigned) {
566 return IsSigned ? getRegForSignedValue(V) :
567 getRegForUnsignedValue(V);
562 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
568563 }
569564
570565 unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
573568 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
574569 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
575570 TII.get(WebAssembly::EQZ_I32), NotReg)
576 .addReg(Reg);
571 .addReg(Reg);
577572 return NotReg;
578573 }
579574
580575 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
581576 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
582 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
583 TII.get(WebAssembly::COPY), ResultReg)
584 .addReg(Reg);
577 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
578 ResultReg)
579 .addReg(Reg);
585580 return ResultReg;
586581 }
587582
590585 FuncInfo.StaticAllocaMap.find(AI);
591586
592587 if (SI != FuncInfo.StaticAllocaMap.end()) {
593 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
594 &WebAssembly::I64RegClass :
595 &WebAssembly::I32RegClass);
596 unsigned Opc = Subtarget->hasAddr64() ?
597 WebAssembly::COPY_I64 :
598 WebAssembly::COPY_I32;
588 unsigned ResultReg =
589 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
590 : &WebAssembly::I32RegClass);
591 unsigned Opc =
592 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
599593 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
600594 .addFrameIndex(SI->second);
601595 return ResultReg;
606600
607601 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
608602 if (const GlobalValue *GV = dyn_cast(C)) {
609 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
610 &WebAssembly::I64RegClass :
611 &WebAssembly::I32RegClass);
612 unsigned Opc = Subtarget->hasAddr64() ?
613 WebAssembly::CONST_I64 :
614 WebAssembly::CONST_I32;
603 unsigned ResultReg =
604 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
605 : &WebAssembly::I32RegClass);
606 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
607 : WebAssembly::CONST_I32;
615608 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
616 .addGlobalAddress(GV);
609 .addGlobalAddress(GV);
617610 return ResultReg;
618611 }
619612
700693 }
701694 unsigned ResultReg = createResultReg(RC);
702695 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
703 .addImm(i);
696 .addImm(i);
704697 updateValueMap(&Arg, ResultReg);
705698
706699 ++i;
719712 }
720713
721714 if (!F->getReturnType()->isVoidTy()) {
722 MVT::SimpleValueType RetTy = getLegalType(getSimpleType(F->getReturnType()));
715 MVT::SimpleValueType RetTy =
716 getLegalType(getSimpleType(F->getReturnType()));
723717 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
724718 MFI->clearParamsAndResults();
725719 return false;
777771 ResultReg = createResultReg(&WebAssembly::F64RegClass);
778772 break;
779773 case MVT::v16i8:
780 Opc =
781 IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8;
774 Opc = IsDirect ? WebAssembly::CALL_v16i8
775 : WebAssembly::PCALL_INDIRECT_v16i8;
782776 ResultReg = createResultReg(&WebAssembly::V128RegClass);
783777 break;
784778 case MVT::v8i16:
785 Opc =
786 IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16;
779 Opc = IsDirect ? WebAssembly::CALL_v8i16
780 : WebAssembly::PCALL_INDIRECT_v8i16;
787781 ResultReg = createResultReg(&WebAssembly::V128RegClass);
788782 break;
789783 case MVT::v4i32:
790 Opc =
791 IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32;
784 Opc = IsDirect ? WebAssembly::CALL_v4i32
785 : WebAssembly::PCALL_INDIRECT_v4i32;
792786 ResultReg = createResultReg(&WebAssembly::V128RegClass);
793787 break;
794788 case MVT::v2i64:
795 Opc =
796 IsDirect ? WebAssembly::CALL_v2i64 : WebAssembly::PCALL_INDIRECT_v2i64;
789 Opc = IsDirect ? WebAssembly::CALL_v2i64
790 : WebAssembly::PCALL_INDIRECT_v2i64;
797791 ResultReg = createResultReg(&WebAssembly::V128RegClass);
798792 break;
799793 case MVT::v4f32:
800 Opc =
801 IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32;
794 Opc = IsDirect ? WebAssembly::CALL_v4f32
795 : WebAssembly::PCALL_INDIRECT_v4f32;
802796 ResultReg = createResultReg(&WebAssembly::V128RegClass);
803797 break;
804798 case MVT::v2f64:
805 Opc =
806 IsDirect ? WebAssembly::CALL_v2f64 : WebAssembly::PCALL_INDIRECT_v2f64;
799 Opc = IsDirect ? WebAssembly::CALL_v2f64
800 : WebAssembly::PCALL_INDIRECT_v2f64;
807801 ResultReg = createResultReg(&WebAssembly::V128RegClass);
808802 break;
809803 case MVT::ExceptRef:
872866 const SelectInst *Select = cast(I);
873867
874868 bool Not;
875 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
869 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
876870 if (CondReg == 0)
877871 return false;
878872
879 unsigned TrueReg = getRegForValue(Select->getTrueValue());
873 unsigned TrueReg = getRegForValue(Select->getTrueValue());
880874 if (TrueReg == 0)
881875 return false;
882876
919913
920914 unsigned ResultReg = createResultReg(RC);
921915 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
922 .addReg(TrueReg)
923 .addReg(FalseReg)
924 .addReg(CondReg);
916 .addReg(TrueReg)
917 .addReg(FalseReg)
918 .addReg(CondReg);
925919
926920 updateValueMap(Select, ResultReg);
927921 return true;
10211015 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
10221016 isSigned = true;
10231017 break;
1024 default: return false;
1018 default:
1019 return false;
10251020 }
10261021
10271022 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
12291224 case MVT::f64:
12301225 Opc = WebAssembly::STORE_F64;
12311226 break;
1232 default: return false;
1227 default:
1228 return false;
12331229 }
12341230
12351231 materializeLoadStoreOperands(Addr);
12941290
12951291 unsigned Opc;
12961292 switch (getSimpleType(RV->getType())) {
1297 case MVT::i1: case MVT::i8:
1298 case MVT::i16: case MVT::i32:
1293 case MVT::i1:
1294 case MVT::i8:
1295 case MVT::i16:
1296 case MVT::i32:
12991297 Opc = WebAssembly::RETURN_I32;
13001298 break;
13011299 case MVT::i64:
13281326 case MVT::ExceptRef:
13291327 Opc = WebAssembly::RETURN_EXCEPT_REF;
13301328 break;
1331 default: return false;
1329 default:
1330 return false;
13321331 }
13331332
13341333 unsigned Reg;
13581357 if (selectCall(I))
13591358 return true;
13601359 break;
1361 case Instruction::Select: return selectSelect(I);
1362 case Instruction::Trunc: return selectTrunc(I);
1363 case Instruction::ZExt: return selectZExt(I);
1364 case Instruction::SExt: return selectSExt(I);
1365 case Instruction::ICmp: return selectICmp(I);
1366 case Instruction::FCmp: return selectFCmp(I);
1367 case Instruction::BitCast: return selectBitCast(I);
1368 case Instruction::Load: return selectLoad(I);
1369 case Instruction::Store: return selectStore(I);
1370 case Instruction::Br: return selectBr(I);
1371 case Instruction::Ret: return selectRet(I);
1372 case Instruction::Unreachable: return selectUnreachable(I);
1373 default: break;
1360 case Instruction::Select:
1361 return selectSelect(I);
1362 case Instruction::Trunc:
1363 return selectTrunc(I);
1364 case Instruction::ZExt:
1365 return selectZExt(I);
1366 case Instruction::SExt:
1367 return selectSExt(I);
1368 case Instruction::ICmp:
1369 return selectICmp(I);
1370 case Instruction::FCmp:
1371 return selectFCmp(I);
1372 case Instruction::BitCast:
1373 return selectBitCast(I);
1374 case Instruction::Load:
1375 return selectLoad(I);
1376 case Instruction::Store:
1377 return selectStore(I);
1378 case Instruction::Br:
1379 return selectBr(I);
1380 case Instruction::Ret:
1381 return selectRet(I);
1382 case Instruction::Unreachable:
1383 return selectUnreachable(I);
1384 default:
1385 break;
13741386 }
13751387
13761388 // Fall back to target-independent instruction selection.
3535
3636 #define DEBUG_TYPE "wasm-fix-function-bitcasts"
3737
38 static cl::opt TemporaryWorkarounds(
39 "wasm-temporary-workarounds",
40 cl::desc("Apply certain temporary workarounds"),
41 cl::init(true), cl::Hidden);
38 static cl::opt
39 TemporaryWorkarounds("wasm-temporary-workarounds",
40 cl::desc("Apply certain temporary workarounds"),
41 cl::init(true), cl::Hidden);
4242
4343 namespace {
4444 class FixFunctionBitcasts final : public ModulePass {
107107 // instead).
108108 //
109109 // If there is a type mismatch that we know would result in an invalid wasm
110 // module then generate wrapper that contains unreachable (i.e. abort at
110 // module then generate wrapper that contains unreachable (i.e. abort at
111111 // runtime). Such programs are deep into undefined behaviour territory,
112112 // but we choose to fail at runtime rather than generate and invalid module
113113 // or fail at compiler time. The reason we delay the error is that we want
116116 // CMake detects the existence of a function in a toolchain).
117117 //
118118 // For bitcasts that involve struct types we don't know at this stage if they
119 // would be equivalent at the wasm level and so we can't know if we need to
119 // would be equivalent at the wasm level and so we can't know if we need to
120120 // generate a wrapper.
121121 static Function *CreateWrapper(Function *F, FunctionType *Ty) {
122122 Module *M = F->getParent();
211211 if (TypeMismatch) {
212212 // Create a new wrapper that simply contains `unreachable`.
213213 Wrapper->eraseFromParent();
214 Wrapper = Function::Create(Ty, Function::PrivateLinkage, F->getName() + "_bitcast_invalid", M);
214 Wrapper = Function::Create(Ty, Function::PrivateLinkage,
215 F->getName() + "_bitcast_invalid", M);
215216 BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper);
216217 new UnreachableInst(M->getContext(), BB);
217218 Wrapper->setName(F->getName() + "_bitcast_invalid");
242243 if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") {
243244 Main = &F;
244245 LLVMContext &C = M.getContext();
245 Type *MainArgTys[] = {
246 PointerType::get(Type::getInt8PtrTy(C), 0),
247 Type::getInt32Ty(C)
248 };
246 Type *MainArgTys[] = {PointerType::get(Type::getInt8PtrTy(C), 0),
247 Type::getInt32Ty(C)};
249248 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
250249 /*isVarArg=*/false);
251250 if (F.getFunctionType() != MainTy) {
252 Value *Args[] = {
253 UndefValue::get(MainArgTys[0]),
254 UndefValue::get(MainArgTys[1])
255 };
256 Value *Casted = ConstantExpr::getBitCast(Main,
257 PointerType::get(MainTy, 0));
251 Value *Args[] = {UndefValue::get(MainArgTys[0]),
252 UndefValue::get(MainArgTys[1])};
253 Value *Casted =
254 ConstantExpr::getBitCast(Main, PointerType::get(MainTy, 0));
258255 CallMain = CallInst::Create(Casted, Args, "call_main");
259256 Use *UseMain = &CallMain->getOperandUse(2);
260257 Uses.push_back(std::make_pair(UseMain, &F));
4242 /// require stricter alignment than the stack pointer itself. Because we need
4343 /// to shift the stack pointer by some unknown amount to force the alignment,
4444 /// we need to record the value of the stack pointer on entry to the function.
45 bool WebAssemblyFrameLowering::hasBP(
46 const MachineFunction &MF) const {
45 bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const {
4746 const auto *RegInfo =
4847 MF.getSubtarget().getRegisterInfo();
4948 return RegInfo->needsStackRealignment(MF);
157156 assert(MFI.getCalleeSavedInfo().empty() &&
158157 "WebAssembly should not have callee-saved registers");
159158
160 if (!needsSP(MF)) return;
159 if (!needsSP(MF))
160 return;
161161 uint64_t StackSize = MFI.getStackSize();
162162
163163 const auto *TII = MF.getSubtarget().getInstrInfo();
201201 unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC);
202202 unsigned Alignment = MFI.getMaxAlignment();
203203 assert((1u << countTrailingZeros(Alignment)) == Alignment &&
204 "Alignment must be a power of 2");
204 "Alignment must be a power of 2");
205205 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg)
206206 .addImm((int)~(Alignment - 1));
207207 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32),
213213 // Unlike most conventional targets (where FP points to the saved FP),
214214 // FP points to the bottom of the fixed-size locals, so we can use positive
215215 // offsets in load/store instructions.
216 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY),
217 WebAssembly::FP32)
216 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32)
218217 .addReg(WebAssembly::SP32);
219218 }
220219 if (StackSize && needsSPWriteback(MF)) {
225224 void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
226225 MachineBasicBlock &MBB) const {
227226 uint64_t StackSize = MF.getFrameInfo().getStackSize();
228 if (!needsSP(MF) || !needsSPWriteback(MF)) return;
227 if (!needsSP(MF) || !needsSPWriteback(MF))
228 return;
229229 const auto *TII = MF.getSubtarget().getInstrInfo();
230230 auto &MRI = MF.getRegInfo();
231231 auto InsertPt = MBB.getFirstTerminator();
2121 class MachineFrameInfo;
2222
2323 class WebAssemblyFrameLowering final : public TargetFrameLowering {
24 public:
24 public:
2525 /// Size of the red zone for the user stack (leaf functions can use this much
2626 /// space below the stack pointer without writing it back to __stack_pointer
2727 /// global).
3434 /*TransientStackAlignment=*/16,
3535 /*StackRealignable=*/true) {}
3636
37 MachineBasicBlock::iterator eliminateCallFramePseudoInstr(
38 MachineFunction &MF, MachineBasicBlock &MBB,
39 MachineBasicBlock::iterator I) const override;
37 MachineBasicBlock::iterator
38 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
39 MachineBasicBlock::iterator I) const override;
4040
4141 /// These methods insert prolog and epilog code into the function.
4242 void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
6060 bool needsSPWriteback(const MachineFunction &MF) const;
6161 };
6262
63 } // end namespace llvm
63 } // end namespace llvm
6464
6565 #endif
9494 ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
9595 setCondCodeAction(CC, T, Expand);
9696 // Expand floating-point library function operators.
97 for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM,
98 ISD::FMA})
97 for (auto Op :
98 {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FMA})
9999 setOperationAction(Op, T, Expand);
100100 // Note supported floating-point library function operators that otherwise
101101 // default to expand.
115115 for (auto T : {MVT::i32, MVT::i64}) {
116116 // Expand unavailable integer operations.
117117 for (auto Op :
118 {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI,
119 ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS,
120 ISD::SRA_PARTS, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC,
121 ISD::SUBE}) {
118 {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
119 ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
120 ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
122121 setOperationAction(Op, T, Expand);
123122 }
124123 }
200199 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
201200 EVT VT) const {
202201 unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
203 if (BitWidth > 1 && BitWidth < 8) BitWidth = 8;
202 if (BitWidth > 1 && BitWidth < 8)
203 BitWidth = 8;
204204
205205 if (BitWidth > 64) {
206206 // The shift will be lowered to a libcall, and compiler-rt libcalls expect
219219 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
220220 // undefined result on invalid/overflow, to the WebAssembly opcode, which
221221 // traps on invalid/overflow.
222 static MachineBasicBlock *
223 LowerFPToInt(
224 MachineInstr &MI,
225 DebugLoc DL,
226 MachineBasicBlock *BB,
227 const TargetInstrInfo &TII,
228 bool IsUnsigned,
229 bool Int64,
230 bool Float64,
231 unsigned LoweredOpcode
232 ) {
222 static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
223 MachineBasicBlock *BB,
224 const TargetInstrInfo &TII,
225 bool IsUnsigned, bool Int64,
226 bool Float64, unsigned LoweredOpcode) {
233227 MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
234228
235229 unsigned OutReg = MI.getOperand(0).getReg();
261255
262256 // Transfer the remainder of BB and its successor edges to DoneMBB.
263257 DoneMBB->splice(DoneMBB->begin(), BB,
264 std::next(MachineBasicBlock::iterator(MI)),
265 BB->end());
258 std::next(MachineBasicBlock::iterator(MI)), BB->end());
266259 DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
267260
268261 BB->addSuccessor(TrueMBB);
284277 if (IsUnsigned) {
285278 Tmp0 = InReg;
286279 } else {
287 BuildMI(BB, DL, TII.get(Abs), Tmp0)
288 .addReg(InReg);
280 BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
289281 }
290282 BuildMI(BB, DL, TII.get(FConst), Tmp1)
291283 .addFPImm(cast(ConstantFP::get(Ty, CmpVal)));
292 BuildMI(BB, DL, TII.get(LT), CmpReg)
293 .addReg(Tmp0)
294 .addReg(Tmp1);
284 BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
295285
296286 // For unsigned numbers, we have to do a separate comparison with zero.
297287 if (IsUnsigned) {
298288 Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
299 unsigned SecondCmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
289 unsigned SecondCmpReg =
290 MRI.createVirtualRegister(&WebAssembly::I32RegClass);
300291 unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
301292 BuildMI(BB, DL, TII.get(FConst), Tmp1)
302293 .addFPImm(cast(ConstantFP::get(Ty, 0.0)));
303 BuildMI(BB, DL, TII.get(GE), SecondCmpReg)
304 .addReg(Tmp0)
305 .addReg(Tmp1);
306 BuildMI(BB, DL, TII.get(And), AndReg)
307 .addReg(CmpReg)
308 .addReg(SecondCmpReg);
294 BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
295 BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
309296 CmpReg = AndReg;
310297 }
311298
312 BuildMI(BB, DL, TII.get(Eqz), EqzReg)
313 .addReg(CmpReg);
299 BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
314300
315301 // Create the CFG diamond to select between doing the conversion or using
316302 // the substitute value.
317 BuildMI(BB, DL, TII.get(WebAssembly::BR_IF))
318 .addMBB(TrueMBB)
319 .addReg(EqzReg);
320 BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg)
321 .addReg(InReg);
322 BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR))
323 .addMBB(DoneMBB);
324 BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg)
325 .addImm(Substitute);
303 BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
304 BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
305 BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
306 BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
326307 BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
327308 .addReg(FalseReg)
328309 .addMBB(FalseMBB)
332313 return DoneMBB;
333314 }
334315
335 MachineBasicBlock *
336 WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
337 MachineInstr &MI,
338 MachineBasicBlock *BB
339 ) const {
316 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
317 MachineInstr &MI, MachineBasicBlock *BB) const {
340318 const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
341319 DebugLoc DL = MI.getDebugLoc();
342320
343321 switch (MI.getOpcode()) {
344 default: llvm_unreachable("Unexpected instr type to insert");
322 default:
323 llvm_unreachable("Unexpected instr type to insert");
345324 case WebAssembly::FP_TO_SINT_I32_F32:
346325 return LowerFPToInt(MI, DL, BB, TII, false, false, false,
347326 WebAssembly::I32_TRUNC_S_F32);
366345 case WebAssembly::FP_TO_UINT_I64_F64:
367346 return LowerFPToInt(MI, DL, BB, TII, true, true, true,
368347 WebAssembly::I64_TRUNC_U_F64);
369 llvm_unreachable("Unexpected instruction to emit with custom inserter");
370 }
371 }
372
373 const char *WebAssemblyTargetLowering::getTargetNodeName(
374 unsigned Opcode) const {
348 llvm_unreachable("Unexpected instruction to emit with custom inserter");
349 }
350 }
351
352 const char *
353 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
375354 switch (static_cast(Opcode)) {
376 case WebAssemblyISD::FIRST_NUMBER:
377 break;
378 #define HANDLE_NODETYPE(NODE) \
379 case WebAssemblyISD::NODE: \
355 case WebAssemblyISD::FIRST_NUMBER:
356 break;
357 #define HANDLE_NODETYPE(NODE) \
358 case WebAssemblyISD::NODE: \
380359 return "WebAssemblyISD::" #NODE;
381360 #include "WebAssemblyISD.def"
382361 #undef HANDLE_NODETYPE
391370 // WebAssembly register class.
392371 if (Constraint.size() == 1) {
393372 switch (Constraint[0]) {
394 case 'r':
395 assert(VT != MVT::iPTR && "Pointer MVT not expected here");
396 if (Subtarget->hasSIMD128() && VT.isVector()) {
397 if (VT.getSizeInBits() == 128)
398 return std::make_pair(0U, &WebAssembly::V128RegClass);
399 }
400 if (VT.isInteger() && !VT.isVector()) {
401 if (VT.getSizeInBits() <= 32)
402 return std::make_pair(0U, &WebAssembly::I32RegClass);
403 if (VT.getSizeInBits() <= 64)
404 return std::make_pair(0U, &WebAssembly::I64RegClass);
405 }
406 break;
407 default:
408 break;
373 case 'r':
374 assert(VT != MVT::iPTR && "Pointer MVT not expected here");
375 if (Subtarget->hasSIMD128() && VT.isVector()) {
376 if (VT.getSizeInBits() == 128)
377 return std::make_pair(0U, &WebAssembly::V128RegClass);
378 }
379 if (VT.isInteger() && !VT.isVector()) {
380 if (VT.getSizeInBits() <= 32)
381 return std::make_pair(0U, &WebAssembly::I32RegClass);
382 if (VT.getSizeInBits() <= 64)
383 return std::make_pair(0U, &WebAssembly::I64RegClass);
384 }
385 break;
386 default:
387 break;
409388 }
410389 }
411390
424403
425404 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
426405 const AddrMode &AM,
427 Type *Ty,
428 unsigned AS,
406 Type *Ty, unsigned AS,
429407 Instruction *I) const {
430408 // WebAssembly offsets are added as unsigned without wrapping. The
431409 // isLegalAddressingMode gives us no way to determine if wrapping could be
432410 // happening, so we approximate this by accepting only non-negative offsets.
433 if (AM.BaseOffs < 0) return false;
411 if (AM.BaseOffs < 0)
412 return false;
434413
435414 // WebAssembly has no scale register operands.
436 if (AM.Scale != 0) return false;
415 if (AM.Scale != 0)
416 return false;
437417
438418 // Everything else is legal.
439419 return true;
447427 // for the kinds of things that LLVM uses this for (merging adjacent stores
448428 // of constants, etc.), WebAssembly implementations will either want the
449429 // unaligned access or they'll split anyway.
450 if (Fast) *Fast = true;
430 if (Fast)
431 *Fast = true;
451432 return true;
452433 }
453434
534515 CallConv == CallingConv::CXX_FAST_TLS;
535516 }
536517
537 SDValue WebAssemblyTargetLowering::LowerCall(
538 CallLoweringInfo &CLI, SmallVectorImpl &InVals) const {
518 SDValue
519 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
520 SmallVectorImpl &InVals) const {
539521 SelectionDAG &DAG = CLI.DAG;
540522 SDLoc DL = CLI.DL;
541523 SDValue Chain = CLI.Chain;
637619 FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
638620 SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
639621 DAG.getConstant(Offset, DL, PtrVT));
640 Chains.push_back(DAG.getStore(
641 Chain, DL, Arg, Add,
642 MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
622 Chains.push_back(
623 DAG.getStore(Chain, DL, Arg, Add,
624 MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
643625 }
644626 if (!Chains.empty())
645627 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
657639 Ops.append(OutVals.begin(),
658640 IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
659641 // Add a pointer to the vararg buffer.
660 if (IsVarArg) Ops.push_back(FINode);
642 if (IsVarArg)
643 Ops.push_back(FINode);
661644
662645 SmallVector InTys;
663646 for (const auto &In : Ins) {
751734 fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
752735 // Ignore In.getOrigAlign() because all our arguments are passed in
753736 // registers.
754 InVals.push_back(
755 In.Used
756 ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
757 DAG.getTargetConstant(InVals.size(), DL, MVT::i32))
758 : DAG.getUNDEF(In.VT));
737 InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
738 DAG.getTargetConstant(InVals.size(),
739 DL, MVT::i32))
740 : DAG.getUNDEF(In.VT));
759741
760742 // Record the number and types of arguments.
761743 MFI->addParam(In.VT);
793775 SelectionDAG &DAG) const {
794776 SDLoc DL(Op);
795777 switch (Op.getOpcode()) {
796 default:
797 llvm_unreachable("unimplemented operation lowering");
798 return SDValue();
799 case ISD::FrameIndex:
800 return LowerFrameIndex(Op, DAG);
801 case ISD::GlobalAddress:
802 return LowerGlobalAddress(Op, DAG);
803 case ISD::ExternalSymbol:
804 return LowerExternalSymbol(Op, DAG);
805 case ISD::JumpTable:
806 return LowerJumpTable(Op, DAG);
807 case ISD::BR_JT:
808 return LowerBR_JT(Op, DAG);
809 case ISD::VASTART:
810 return LowerVASTART(Op, DAG);
811 case ISD::BlockAddress:
812 case ISD::BRIND:
813 fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
814 return SDValue();
815 case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
816 fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
817 return SDValue();
818 case ISD::FRAMEADDR:
819 return LowerFRAMEADDR(Op, DAG);
820 case ISD::CopyToReg:
821 return LowerCopyToReg(Op, DAG);
822 case ISD::INTRINSIC_WO_CHAIN:
823 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
778 default:
779 llvm_unreachable("unimplemented operation lowering");
780 return SDValue();
781 case ISD::FrameIndex:
782 return LowerFrameIndex(Op, DAG);
783 case ISD::GlobalAddress:
784 return LowerGlobalAddress(Op, DAG);
785 case ISD::ExternalSymbol:
786 return LowerExternalSymbol(Op, DAG);
787 case ISD::JumpTable:
788 return LowerJumpTable(Op, DAG);
789 case ISD::BR_JT:
790 return LowerBR_JT(Op, DAG);
791 case ISD::VASTART:
792 return LowerVASTART(Op, DAG);
793 case ISD::BlockAddress:
794 case ISD::BRIND:
795 fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
796 return SDValue();
797 case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
798 fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
799 return SDValue();
800 case ISD::FRAMEADDR:
801 return LowerFRAMEADDR(Op, DAG);
802 case ISD::CopyToReg:
803 return LowerCopyToReg(Op, DAG);
804 case ISD::INTRINSIC_WO_CHAIN:
805 return LowerINTRINSIC_WO_CHAIN(Op, DAG);
824806 }
825807 }
826808
837819 SDLoc DL(Op);
838820 unsigned Reg = cast(Op.getOperand(1))->getReg();
839821 EVT VT = Src.getValueType();
840 SDValue Copy(
841 DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
842 : WebAssembly::COPY_I64,
843 DL, VT, Src),
844 0);
822 SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
823 : WebAssembly::COPY_I64,
824 DL, VT, Src),
825 0);
845826 return Op.getNode()->getNumValues() == 1
846827 ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
847 : DAG.getCopyToReg(Chain, DL, Reg, Copy, Op.getNumOperands() == 4
848 ? Op.getOperand(3)
849 : SDValue());
828 : DAG.getCopyToReg(Chain, DL, Reg, Copy,
829 Op.getNumOperands() == 4 ? Op.getOperand(3)
830 : SDValue());
850831 }
851832 return SDValue();
852833 }
886867 DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
887868 }
888869
889 SDValue WebAssemblyTargetLowering::LowerExternalSymbol(
890 SDValue Op, SelectionDAG &DAG) const {
870 SDValue
871 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
872 SelectionDAG &DAG) const {
891873 SDLoc DL(Op);
892874 const auto *ES = cast(Op);
893875 EVT VT = Op.getValueType();
898880 // we don't know anything about the symbol other than its name, because all
899881 // external symbols used in target-independent SelectionDAG code are for
900882 // functions.
901 return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
902 DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
903 WebAssemblyII::MO_SYMBOL_FUNCTION));
883 return DAG.getNode(
884 WebAssemblyISD::Wrapper, DL, VT,
885 DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
886 WebAssemblyII::MO_SYMBOL_FUNCTION));
904887 }
905888
906889 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
929912 const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
930913
931914 // Add an operand for each case.
932 for (auto MBB : MBBs) Ops.push_back(DAG.getBasicBlock(MBB));
915 for (auto MBB : MBBs)
916 Ops.push_back(DAG.getBasicBlock(MBB));
933917
934918 // TODO: For now, we just pick something arbitrary for a default case for now.
935919 // We really want to sniff out the guard and put in the real default case (and
2828 #undef HANDLE_NODETYPE
2929 };
3030
31 } // end namespace WebAssemblyISD
31 } // end namespace WebAssemblyISD
3232
3333 class WebAssemblySubtarget;
3434 class WebAssemblyTargetMachine;
3535
3636 class WebAssemblyTargetLowering final : public TargetLowering {
37 public:
37 public:
3838 WebAssemblyTargetLowering(const TargetMachine &TM,
3939 const WebAssemblySubtarget &STI);
4040
41 private:
41 private:
4242 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
4343 /// right decision when generating code for different targets.
4444 const WebAssemblySubtarget *Subtarget;
5252 EmitInstrWithCustomInserter(MachineInstr &MI,
5353 MachineBasicBlock *MBB) const override;
5454 const char *getTargetNodeName(unsigned Opcode) const override;
55 std::pair getRegForInlineAsmConstraint(
56 const TargetRegisterInfo *TRI, StringRef Constraint,
57 MVT VT) const override;
55 std::pair
56 getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
57 StringRef Constraint, MVT VT) const override;
5858 bool isCheapToSpeculateCttz() const override;
5959 bool isCheapToSpeculateCtlz() const override;
6060 bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
102102 namespace WebAssembly {
103103 FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
104104 const TargetLibraryInfo *libInfo);
105 } // end namespace WebAssembly
105 } // end namespace WebAssembly
106106
107 } // end namespace llvm
107 } // end namespace llvm
108108
109109 #endif
7676 .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
7777 }
7878
79 MachineInstr *
80 WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
81 unsigned OpIdx1,
82 unsigned OpIdx2) const {
79 MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(
80 MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {
8381 // If the operands are stackified, we can't reorder them.
8482 WebAssemblyFunctionInfo &MFI =
8583 *MI.getParent()->getParent()->getInfo();
164162 return Count;
165163 }
166164
167 unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB,
168 MachineBasicBlock *TBB,
169 MachineBasicBlock *FBB,
170 ArrayRef Cond,
171 const DebugLoc &DL,
172 int *BytesAdded) const {
165 unsigned WebAssemblyInstrInfo::insertBranch(
166 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
167 ArrayRef Cond, const DebugLoc &DL, int *BytesAdded) const {
173168 assert(!BytesAdded && "code size not handled");
174169
175170 if (Cond.empty()) {
7777 MachineInstr *Def = MRI.getVRegDef(Cond);
7878 switch (Def->getOpcode()) {
7979 using namespace WebAssembly;
80 case EQ_I32: Def->setDesc(TII.get(NE_I32)); Inverted = true; break;
81 case NE_I32: Def->setDesc(TII.get(EQ_I32)); Inverted = true; break;
82 case GT_S_I32: Def->setDesc(TII.get(LE_S_I32)); Inverted = true; break;
83 case GE_S_I32: Def->setDesc(TII.get(LT_S_I32)); Inverted = true; break;
84 case LT_S_I32: Def->setDesc(TII.get(GE_S_I32)); Inverted = true; break;
85 case LE_S_I32: Def->setDesc(TII.get(GT_S_I32)); Inverted = true; break;
86 case GT_U_I32: Def->setDesc(TII.get(LE_U_I32)); Inverted = true; break;
87 case GE_U_I32: Def->setDesc(TII.get(LT_U_I32)); Inverted = true; break;
88 case LT_U_I32: Def->setDesc(TII.get(GE_U_I32)); Inverted = true; break;
89 case LE_U_I32: Def->setDesc(TII.get(GT_U_I32)); Inverted = true; break;
90 case EQ_I64: Def->setDesc(TII.get(NE_I64)); Inverted = true; break;
91 case NE_I64: Def->setDesc(TII.get(EQ_I64)); Inverted = true; break;
92 case GT_S_I64: Def->setDesc(TII.get(LE_S_I64)); Inverted = true; break;
93 case GE_S_I64: Def->setDesc(TII.get(LT_S_I64)); Inverted = true; break;
94 case LT_S_I64: Def->setDesc(TII.get(GE_S_I64)); Inverted = true; break;
95 case LE_S_I64: Def->setDesc(TII.get(GT_S_I64)); Inverted = true; break;
96 case GT_U_I64: Def->setDesc(TII.get(LE_U_I64)); Inverted = true; break;
97 case GE_U_I64: Def->setDesc(TII.get(LT_U_I64)); Inverted = true; break;
98 case LT_U_I64: Def->setDesc(TII.get(GE_U_I64)); Inverted = true; break;
99 case LE_U_I64: Def->setDesc(TII.get(GT_U_I64)); Inverted = true; break;
100 case EQ_F32: Def->setDesc(TII.get(NE_F32)); Inverted = true; break;
101 case NE_F32: Def->setDesc(TII.get(EQ_F32)); Inverted = true; break;
102 case EQ_F64: Def->setDesc(TII.get(NE_F64)); Inverted = true; break;
103 case NE_F64: Def->setDesc(TII.get(EQ_F64)); Inverted = true; break;
80 case EQ_I32:
81 Def->setDesc(TII.get(NE_I32));
82 Inverted = true;
83 break;
84 case NE_I32:
85 Def->setDesc(TII.get(EQ_I32));
86 Inverted = true;
87 break;
88 case GT_S_I32:
89 Def->setDesc(TII.get(LE_S_I32));
90 Inverted = true;
91 break;
92 case GE_S_I32:
93 Def->setDesc(TII.get(LT_S_I32));
94 Inverted = true;
95 break;
96 case LT_S_I32:
97 Def->setDesc(TII.get(GE_S_I32));
98 Inverted = true;
99 break;
100 case LE_S_I32:
101 Def->setDesc(TII.get(GT_S_I32));
102 Inverted = true;
103 break;
104 case GT_U_I32:
105 Def->setDesc(TII.get(LE_U_I32));
106 Inverted = true;
107 break;
108 case GE_U_I32:
109 Def->setDesc(TII.get(LT_U_I32));
110 Inverted = true;
111 break;
112 case LT_U_I32:
113 Def->setDesc(TII.get(GE_U_I32));
114 Inverted = true;
115 break;
116 case LE_U_I32:
117 Def->setDesc(TII.get(GT_U_I32));
118 Inverted = true;
119 break;
120 case EQ_I64:
121 Def->setDesc(TII.get(NE_I64));
122 Inverted = true;
123 break;
124 case NE_I64:
125 Def->setDesc(TII.get(EQ_I64));
126 Inverted = true;
127 break;
128 case GT_S_I64:
129 Def->setDesc(TII.get(LE_S_I64));
130 Inverted = true;
131 break;
132 case GE_S_I64:
133 Def->setDesc(TII.get(LT_S_I64));
134 Inverted = true;
135 break;
136 case LT_S_I64:
137 Def->setDesc(TII.get(GE_S_I64));
138 Inverted = true;
139 break;
140 case LE_S_I64:
141 Def->setDesc(TII.get(GT_S_I64));
142 Inverted = true;
143 break;
144 case GT_U_I64:
145 Def->setDesc(TII.get(LE_U_I64));
146 Inverted = true;
147 break;
148 case GE_U_I64:
149 Def->setDesc(TII.get(LT_U_I64));
150 Inverted = true;
151 break;
152 case LT_U_I64:
153 Def->setDesc(TII.get(GE_U_I64));
154 Inverted = true;
155 break;
156 case LE_U_I64:
157 Def->setDesc(TII.get(GT_U_I64));
158 Inverted = true;
159 break;
160 case EQ_F32:
161 Def->setDesc(TII.get(NE_F32));
162 Inverted = true;
163 break;
164 case NE_F32:
165 Def->setDesc(TII.get(EQ_F32));
166 Inverted = true;
167 break;
168 case EQ_F64:
169 Def->setDesc(TII.get(NE_F64));
170 Inverted = true;
171 break;
172 case NE_F64:
173 Def->setDesc(TII.get(EQ_F64));
174 Inverted = true;
175 break;
104176 case EQZ_I32: {
105177 // Invert an eqz by replacing it with its operand.
106178 Cond = Def->getOperand(1).getReg();
108180 Inverted = true;
109181 break;
110182 }
111 default: break;
183 default:
184 break;
112185 }
113186 }
114187
1717 //===----------------------------------------------------------------------===//
1818
1919 #include "WebAssembly.h"
20 #include "llvm/ADT/MapVector.h"
2021 #include "llvm/IR/Constants.h"
2122 #include "llvm/IR/Instructions.h"
2223 #include "llvm/IR/Intrinsics.h"
2324 #include "llvm/IR/Module.h"
24 #include "llvm/Transforms/Utils/ModuleUtils.h"
2525 #include "llvm/Pass.h"
26 #include "llvm/ADT/MapVector.h"
2726 #include "llvm/Support/Debug.h"
2827 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Transforms/Utils/ModuleUtils.h"
2929 using namespace llvm;
3030
3131 #define DEBUG_TYPE "wasm-lower-global-dtors"
7676
7777 // Collect the contents of @llvm.global_dtors, collated by priority and
7878 // associated symbol.
79 std::map > > DtorFuncs;
79 std::map>> DtorFuncs;
8080 for (Value *O : InitList->operands()) {
8181 ConstantStruct *CS = dyn_cast(O);
82 if (!CS) continue; // Malformed.
82 if (!CS)
83 continue; // Malformed.
8384
8485 ConstantInt *Priority = dyn_cast(CS->getOperand(0));
85 if (!Priority) continue; // Malformed.
86 if (!Priority)
87 continue; // Malformed.
8688 uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX);
8789
8890 Constant *DtorFunc = CS->getOperand(1);
8991 if (DtorFunc->isNullValue())
90 break; // Found a null terminator, skip the rest.
92 break; // Found a null terminator, skip the rest.
9193
9294 Constant *Associated = CS->getOperand(2);
9395 Associated = cast(Associated->stripPointerCastsNoFollowAliases());
100102 // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
101103 LLVMContext &C = M.getContext();
102104 PointerType *VoidStar = Type::getInt8PtrTy(C);
103 Type *AtExitFuncArgs[] = { VoidStar };
104 FunctionType *AtExitFuncTy = FunctionType::get(
105 Type::getVoidTy(C),
106 AtExitFuncArgs,
107 /*isVarArg=*/false);
105 Type *AtExitFuncArgs[] = {VoidStar};
106 FunctionType *AtExitFuncTy =
107 FunctionType::get(Type::getVoidTy(C), AtExitFuncArgs,
108 /*isVarArg=*/false);
108109
109 Type *AtExitArgs[] = {
110 PointerType::get(AtExitFuncTy, 0),
111 VoidStar,
112 VoidStar
113 };
114 FunctionType *AtExitTy = FunctionType::get(
115 Type::getInt32Ty(C),
116 AtExitArgs,
117 /*isVarArg=*/false);
110 Type *AtExitArgs[] = {PointerType::get(AtExitFuncTy, 0), VoidStar, VoidStar};
111 FunctionType *AtExitTy = FunctionType::get(Type::getInt32Ty(C), AtExitArgs,
112 /*isVarArg=*/false);
118113 Constant *AtExit = M.getOrInsertFunction("__cxa_atexit", AtExitTy);
119114
120115 // Declare __dso_local.
121116 Constant *DsoHandle = M.getNamedValue("__dso_handle");
122117 if (!DsoHandle) {
123118 Type *DsoHandleTy = Type::getInt8Ty(C);
124 GlobalVariable *Handle =
125 new GlobalVariable(M, DsoHandleTy, /*isConstant=*/true,
126 GlobalVariable::ExternalWeakLinkage,
127 nullptr, "__dso_handle");
119 GlobalVariable *Handle = new GlobalVariable(
120 M, DsoHandleTy, /*isConstant=*/true,
121 GlobalVariable::ExternalWeakLinkage, nullptr, "__dso_handle");
128122 Handle->setVisibility(GlobalVariable::HiddenVisibility);
129123 DsoHandle = Handle;
130124 }
138132 Constant *Associated = AssociatedAndMore.first;
139133
140134 Function *CallDtors = Function::Create(
141 AtExitFuncTy, Function::PrivateLinkage,
142 "call_dtors" +
143 (Priority != UINT16_MAX ?
144 (Twine(".") + Twine(Priority)) : Twine()) +
145 (!Associated->isNullValue() ?
146 (Twine(".") + Associated->getName()) : Twine()),
147 &M);
135 AtExitFuncTy, Function::PrivateLinkage,
136 "call_dtors" +
137 (Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
138 : Twine()) +
139 (!Associated->isNullValue() ? (Twine(".") + Associated->getName())
140 : Twine()),
141 &M);
148142 BasicBlock *BB = BasicBlock::Create(C, "body", CallDtors);
149143
150144 for (auto Dtor : AssociatedAndMore.second)
154148 FunctionType *VoidVoid = FunctionType::get(Type::getVoidTy(C),
155149 /*isVarArg=*/false);
156150 Function *RegisterCallDtors = Function::Create(
157 VoidVoid, Function::PrivateLinkage,
158 "register_call_dtors" +
159 (Priority != UINT16_MAX ?
160 (Twine(".") + Twine(Priority)) : Twine()) +
161 (!Associated->isNullValue() ?
162 (Twine(".") + Associated->getName()) : Twine()),
163 &M);
151 VoidVoid, Function::PrivateLinkage,
152 "register_call_dtors" +
153 (Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
154 : Twine()) +
155 (!Associated->isNullValue() ? (Twine(".") + Associated->getName())
156 : Twine()),
157 &M);
164158 BasicBlock *EntryBB = BasicBlock::Create(C, "entry", RegisterCallDtors);
165159 BasicBlock *FailBB = BasicBlock::Create(C, "fail", RegisterCallDtors);
166160 BasicBlock *RetBB = BasicBlock::Create(C, "return", RegisterCallDtors);
167161
168162 Value *Null = ConstantPointerNull::get(VoidStar);
169 Value *Args[] = { CallDtors, Null, DsoHandle };
163 Value *Args[] = {CallDtors, Null, DsoHandle};
170164 Value *Res = CallInst::Create(AtExit, Args, "call", EntryBB);
171165 Value *Cmp = new ICmpInst(*EntryBB, ICmpInst::ICMP_NE, Res,
172166 Constant::getNullValue(Res->getType()));
173167 BranchInst::Create(FailBB, RetBB, Cmp, EntryBB);
174168
175169 // If `__cxa_atexit` hits out-of-memory, trap, so that we don't misbehave.
176 // This should be very rare, because if the process is running out of memory
177 // before main has even started, something is wrong.
178 CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap),
179 "", FailBB);
170 // This should be very rare, because if the process is running out of
171 // memory before main has even started, something is wrong.
172 CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), "",
173 FailBB);
180174 new UnreachableInst(C, FailBB);
181175
182176 ReturnInst::Create(C, RetBB);
3131
3232 // This disables the removal of registers when lowering into MC, as required
3333 // by some current tests.
34 static cl::opt WasmKeepRegisters(
35 "wasm-keep-registers", cl::Hidden,
36 cl::desc("WebAssembly: output stack registers in"
37 " instruction output for test purposes only."),
38 cl::init(false));
34 static cl::opt
35 WasmKeepRegisters("wasm-keep-registers", cl::Hidden,
36 cl::desc("WebAssembly: output stack registers in"
37 " instruction output for test purposes only."),
38 cl::init(false));
3939
4040 static unsigned regInstructionToStackInstruction(unsigned OpCode);
4141 static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
5353 SmallVector Returns;
5454 SmallVector Params;
5555
56 wasm::ValType iPTR =
57 MF.getSubtarget().hasAddr64() ?
58 wasm::ValType::I64 :
59 wasm::ValType::I32;
56 wasm::ValType iPTR = MF.getSubtarget().hasAddr64()
57 ? wasm::ValType::I64
58 : wasm::ValType::I32;
6059
6160 SmallVector ResultMVTs;
6261 ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs);
121120 bool IsFunc,
122121 bool IsGlob) const {
123122 MCSymbolRefExpr::VariantKind VK =
124 IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION :
125 IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
126 : MCSymbolRefExpr::VK_None;
123 IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION
124 : IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
125 : MCSymbolRefExpr::VK_None;
127126
128127 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
129128
237236 // variable or a function.
238237 assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 &&
239238 "WebAssembly uses only symbol flags on ExternalSymbols");
240 MCOp = LowerSymbolOperand(GetExternalSymbolSymbol(MO), /*Offset=*/0,
239 MCOp = LowerSymbolOperand(
240 GetExternalSymbolSymbol(MO), /*Offset=*/0,
241241 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_FUNCTION) != 0,
242242 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0);
243243 break;
294294 switch (OpCode) {
295295 default:
296296 llvm_unreachable(
297 "unknown WebAssembly instruction in WebAssemblyMCInstLower pass");
297 "unknown WebAssembly instruction in WebAssemblyMCInstLower pass");
298298 #include "WebAssemblyGenStackifier.inc"
299299 }
300300 }
3232
3333 MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
3434 MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
35 MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset,
36 bool IsFunc, bool IsGlob) const;
35 MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
36 bool IsGlob) const;
3737
3838 public:
3939 WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)
4949 // overaligned values on the user stack.
5050 unsigned BasePtrVreg = -1U;
5151
52 public:
52 public:
5353 explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {}
5454 ~WebAssemblyFunctionInfo() override;
5555
5959 void addResult(MVT VT) { Results.push_back(VT); }
6060 const std::vector &getResults() const { return Results; }
6161
62 void clearParamsAndResults() { Params.clear(); Results.clear(); }
62 void clearParamsAndResults() {
63 Params.clear();
64 Results.clear();
65 }
6366
6467 void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
6568 void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
114117 }
115118 };
116119
117 void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
118 Type *Ty, SmallVectorImpl &ValueVTs);
120 void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
121 SmallVectorImpl &ValueVTs);
119122
120123 void ComputeSignatureVTs(const Function &F, const TargetMachine &TM,
121124 SmallVectorImpl &Params,
6464 return new WebAssemblyOptimizeLiveIntervals();
6565 }
6666
67 bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF) {
67 bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
68 MachineFunction &MF) {
6869 LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n"
6970 "********** Function: "
7071 << MF.getName() << '\n');
7576 // We don't preserve SSA form.
7677 MRI.leaveSSA();
7778
78 assert(MRI.tracksLiveness() &&
79 "OptimizeLiveIntervals expects liveness");
79 assert(MRI.tracksLiveness() && "OptimizeLiveIntervals expects liveness");
8080
8181 // Split multiple-VN LiveIntervals into multiple LiveIntervals.
82 SmallVector*, 4> SplitLIs;
82 SmallVector *, 4> SplitLIs;
8383 for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
8484 unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
8585 if (MRI.reg_nodbg_empty(Reg))
9393 // instructions to satisfy LiveIntervals' requirement that all uses be
9494 // dominated by defs. Now that LiveIntervals has computed which of these
9595 // defs are actually needed and which are dead, remove the dead ones.
96 for (auto MII = MF.begin()->begin(), MIE = MF.begin()->end(); MII != MIE; ) {
96 for (auto MII = MF.begin()->begin(), MIE = MF.begin()->end(); MII != MIE;) {
9797 MachineInstr *MI = &*MII++;
9898 if (MI->isImplicitDef() && MI->getOperand(0).isDead()) {
9999 LiveInterval &LI = LIS.getInterval(MI->getOperand(0).getReg());
6969 return false;
7070 }
7171
72 bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(MachineFunction &MF) {
72 bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(
73 MachineFunction &MF) {
7374 LLVM_DEBUG({
7475 dbgs() << "********** Prepare For LiveIntervals **********\n"
7576 << "********** Function: " << MF.getName() << '\n';
111112
112113 // Move ARGUMENT_* instructions to the top of the entry block, so that their
113114 // liveness reflects the fact that these really are live-in values.
114 for (auto MII = Entry.begin(), MIE = Entry.end(); MII != MIE; ) {
115 for (auto MII = Entry.begin(), MIE = Entry.end(); MII != MIE;) {
115116 MachineInstr &MI = *MII++;
116117 if (WebAssembly::isArgument(MI)) {
117118 MI.removeFromParent();
9999 MachineFunction &MF) {
100100 assert(MI->getOpcode() == TargetOpcode::IMPLICIT_DEF);
101101
102 const auto *RegClass =
103 MRI.getRegClass(MI->getOperand(0).getReg());
102 const auto *RegClass = MRI.getRegClass(MI->getOperand(0).getReg());
104103 if (RegClass == &WebAssembly::I32RegClass) {
105104 MI->setDesc(TII->get(WebAssembly::CONST_I32));
106105 MI->addOperand(MachineOperand::CreateImm(0));
186185 }
187186 } else if (MI.hasOrderedMemoryRef()) {
188187 switch (MI.getOpcode()) {
189 case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64:
190 case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64:
191 case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64:
192 case WebAssembly::REM_U_I32: case WebAssembly::REM_U_I64:
193 case WebAssembly::I32_TRUNC_S_F32: case WebAssembly::I64_TRUNC_S_F32:
194 case WebAssembly::I32_TRUNC_S_F64: case WebAssembly::I64_TRUNC_S_F64:
195 case WebAssembly::I32_TRUNC_U_F32: case WebAssembly::I64_TRUNC_U_F32:
196 case WebAssembly::I32_TRUNC_U_F64: case WebAssembly::I64_TRUNC_U_F64:
188 case WebAssembly::DIV_S_I32:
189 case WebAssembly::DIV_S_I64:
190 case WebAssembly::REM_S_I32:
191 case WebAssembly::REM_S_I64:
192 case WebAssembly::DIV_U_I32:
193 case WebAssembly::DIV_U_I64:
194 case WebAssembly::REM_U_I32:
195 case WebAssembly::REM_U_I64:
196 case WebAssembly::I32_TRUNC_S_F32:
197 case WebAssembly::I64_TRUNC_S_F32:
198 case WebAssembly::I32_TRUNC_S_F64:
199 case WebAssembly::I64_TRUNC_S_F64:
200 case WebAssembly::I32_TRUNC_U_F32:
201 case WebAssembly::I64_TRUNC_U_F32:
202 case WebAssembly::I32_TRUNC_U_F64:
203 case WebAssembly::I64_TRUNC_U_F64:
197204 // These instruction have hasUnmodeledSideEffects() returning true
198205 // because they trap on overflow and invalid so they can't be arbitrarily
199206 // moved, however hasOrderedMemoryRef() interprets this plus their lack
213220 // Check for side effects.
214221 if (MI.hasUnmodeledSideEffects()) {
215222 switch (MI.getOpcode()) {
216 case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64:
217 case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64:
218 case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64:
219 case WebAssembly::REM_U_I32: case WebAssembly::REM_U_I64:
220 case WebAssembly::I32_TRUNC_S_F32: case WebAssembly::I64_TRUNC_S_F32:
221 case WebAssembly::I32_TRUNC_S_F64: case WebAssembly::I64_TRUNC_S_F64:
222 case WebAssembly::I32_TRUNC_U_F32: case WebAssembly::I64_TRUNC_U_F32:
223 case WebAssembly::I32_TRUNC_U_F64: case WebAssembly::I64_TRUNC_U_F64:
223 case WebAssembly::DIV_S_I32:
224 case WebAssembly::DIV_S_I64:
225 case WebAssembly::REM_S_I32:
226 case WebAssembly::REM_S_I64:
227 case WebAssembly::DIV_U_I32:
228 case WebAssembly::DIV_U_I64:
229 case WebAssembly::REM_U_I32:
230 case WebAssembly::REM_U_I64:
231 case WebAssembly::I32_TRUNC_S_F32:
232 case WebAssembly::I64_TRUNC_S_F32:
233 case WebAssembly::I32_TRUNC_S_F64:
234 case WebAssembly::I64_TRUNC_S_F64:
235 case WebAssembly::I32_TRUNC_U_F32:
236 case WebAssembly::I64_TRUNC_U_F32:
237 case WebAssembly::I32_TRUNC_U_F64:
238 case WebAssembly::I64_TRUNC_U_F64:
224239 // These instructions have hasUnmodeledSideEffects() returning true
225240 // because they trap on overflow and invalid so they can't be arbitrarily
226241 // moved, however in the specific case of register stackifying, it is safe
250265 // LiveIntervals to handle complex cases.
251266 static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert,
252267 const MachineRegisterInfo &MRI,
253 const LiveIntervals &LIS)
254 {
268 const LiveIntervals &LIS) {
255269 // Most registers are in SSA form here so we try a quick MRI query first.
256270 if (MachineInstr *Def = MRI.getUniqueVRegDef(Reg))
257271 return Def;
267281 // Test whether Reg, as defined at Def, has exactly one use. This is a
268282 // generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals
269283 // to handle complex cases.
270 static bool HasOneUse(unsigned Reg, MachineInstr *Def,
271 MachineRegisterInfo &MRI, MachineDominatorTree &MDT,
272 LiveIntervals &LIS) {
284 static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
285 MachineDominatorTree &MDT, LiveIntervals &LIS) {
273286 // Most registers are in SSA form here so we try a quick MRI query first.
274287 if (MRI.hasOneUse(Reg))
275288 return true;
276289
277290 bool HasOne = false;
278291 const LiveInterval &LI = LIS.getInterval(Reg);
279 const VNInfo *DefVNI = LI.getVNInfoAt(
280 LIS.getInstructionIndex(*Def).getRegSlot());
292 const VNInfo *DefVNI =
293 LI.getVNInfoAt(LIS.getInstructionIndex(*Def).getRegSlot());
281294 assert(DefVNI);
282295 for (auto &I : MRI.use_nodbg_operands(Reg)) {
283296 const auto &Result = LI.Query(LIS.getInstructionIndex(*I.getParent()));
446459 // Shrink LI to its uses, cleaning up LI.
447460 static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
448461 if (LIS.shrinkToUses(&LI)) {
449 SmallVector*, 4> SplitLIs;
462 SmallVector *, 4> SplitLIs;
450463 LIS.splitSeparateComponents(LI, SplitLIs);
451464 }
452465 }
453466
454467 /// A single-use def in the same block with no intervening memory or register
455468 /// dependencies; move the def down and nest it with the current instruction.
456 static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand& Op,
457 MachineInstr *Def,
458 MachineBasicBlock &MBB,
469 static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand &Op,
470 MachineInstr *Def, MachineBasicBlock &MBB,
459471 MachineInstr *Insert, LiveIntervals &LIS,
460472 WebAssemblyFunctionInfo &MFI,
461473 MachineRegisterInfo &MRI) {
2121 #include "llvm/CodeGen/MachineFrameInfo.h"
2222 #include "llvm/CodeGen/MachineInstrBuilder.h"
2323 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/TargetFrameLowering.h"
2425 #include "llvm/IR/Function.h"
2526 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/CodeGen/TargetFrameLowering.h"
2727 #include "llvm/Target/TargetOptions.h"
2828 using namespace llvm;
2929
5353
5454 char WebAssemblyReplacePhysRegs::ID = 0;
5555 INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
56 "Replace physical registers with virtual registers",
57 false, false)
56 "Replace physical registers with virtual registers", false,
57 false)
5858
5959 FunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
6060 return new WebAssemblyReplacePhysRegs();
8585 // Replace explicit uses of the physical register with a virtual register.
8686 const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
8787 unsigned VReg = WebAssembly::NoRegister;
88 for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E; ) {
88 for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E;) {
8989 MachineOperand &MO = *I++;
9090 if (!MO.isImplicit()) {
9191 if (VReg == WebAssembly::NoRegister)
8686 i32_func_i64_i64_i64_i64,
8787 unsupported
8888 };
89
9089
9190 struct RuntimeLibcallSignatureTable {
9291 std::vector Table;
485484
486485 } // end anonymous namespace
487486
488
489
490487 void llvm::GetSignature(const WebAssemblySubtarget &Subtarget,
491488 RTLIB::Libcall LC, SmallVectorImpl &Rets,
492489 SmallVectorImpl &Params) {
496493 wasm::ValType iPTR =
497494 Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
498495
499 auto& Table = RuntimeLibcallSignatures->Table;
496 auto &Table = RuntimeLibcallSignatures->Table;
500497 switch (Table[LC]) {
501498 case func:
502499 break;
836833 void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, const char *Name,
837834 SmallVectorImpl &Rets,
838835 SmallVectorImpl &Params) {
839 auto& Map = LibcallNameMap->Map;
836 auto &Map = LibcallNameMap->Map;
840837 auto val = Map.find(Name);
841838 assert(val != Map.end() && "unexpected runtime library name");
842839 return GetSignature(Subtarget, val->second, Rets, Params);
5959 assert(MI.hasOneMemOperand() &&
6060 "Load and store instructions have exactly one mem operand");
6161 assert((*MI.memoperands_begin())->getSize() ==
62 (UINT64_C(1)
63 << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
62 (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
6463 "Default p2align value should be natural");
6564 assert(MI.getDesc().OpInfo[OperandNo].OperandType ==
6665 WebAssembly::OPERAND_P2ALIGN &&
6867 uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment());
6968
7069 // WebAssembly does not currently support supernatural alignment.
71 P2Align = std::min(
72 P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
70 P2Align = std::min(P2Align,
71 uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
7372
7473 MI.getOperand(OperandNo).setImm(P2Align);
7574 }
9090
9191 SmallVector Indices;
9292
93 for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end(); I != E;) {
93 for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end();
94 I != E;) {
9495 MachineOperand &O = *I++;
9596 MachineInstr *Where = O.getParent();
9697
131132
132133 // If we replaced all dominated uses, FromReg is now killed at MI.
133134 if (!FromLI->liveAt(FromIdx.getDeadSlot()))
134 MI.addRegisterKilled(FromReg,
135 MBB.getParent()->getSubtarget()
136 .getRegisterInfo());
135 MI.addRegisterKilled(FromReg, MBB.getParent()
136 ->getSubtarget()
137 .getRegisterInfo());
137138 }
138139
139140 return Changed;
141142
142143 static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI,
143144 const MachineRegisterInfo &MRI,
144 MachineDominatorTree &MDT,
145 LiveIntervals &LIS,
145 MachineDominatorTree &MDT, LiveIntervals &LIS,
146146 const WebAssemblyTargetLowering &TLI,
147147 const TargetLibraryInfo &LibInfo) {
148148 MachineOperand &Op1 = MI.getOperand(1);
149149 // pass just converts all GlobalVariables to NotThreadLocal
150150 static char ID;
151151
152 public:
152 public:
153153 StripThreadLocal() : ModulePass(ID) {}
154154 bool runOnModule(Module &M) override {
155155 for (auto &GV : M.globals())
2222 namespace {
2323
2424 static const EnumEntry WasmSymbolTypes[] = {
25 #define ENUM_ENTRY(X) { #X, wasm::WASM_SYMBOL_TYPE_##X }
26 ENUM_ENTRY(FUNCTION),
27 ENUM_ENTRY(DATA),
28 ENUM_ENTRY(GLOBAL),
29 ENUM_ENTRY(SECTION),
25 #define ENUM_ENTRY(X) \
26 { #X, wasm::WASM_SYMBOL_TYPE_##X }
27 ENUM_ENTRY(FUNCTION),
28 ENUM_ENTRY(DATA),
29 ENUM_ENTRY(GLOBAL),
30 ENUM_ENTRY(SECTION),
3031 #undef ENUM_ENTRY
3132 };
3233
3334 static const EnumEntry WasmSectionTypes[] = {
34 #define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
35 ENUM_ENTRY(CUSTOM),
36 ENUM_ENTRY(TYPE),
37 ENUM_ENTRY(IMPORT),
38 ENUM_ENTRY(FUNCTION),
39 ENUM_ENTRY(TABLE),
40 ENUM_ENTRY(MEMORY),
41 ENUM_ENTRY(GLOBAL),
42 ENUM_ENTRY(EXPORT),
43 ENUM_ENTRY(START),
44 ENUM_ENTRY(ELEM),
45 ENUM_ENTRY(CODE),
46 ENUM_ENTRY(DATA),
35 #define ENUM_ENTRY(X) \
36 { #X, wasm::WASM_SEC_##X }
37 ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
38 ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
39 ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EXPORT), ENUM_ENTRY(START),
40 ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE), ENUM_ENTRY(DATA),
4741 #undef ENUM_ENTRY
4842 };
4943
107101 if (HasAddend)
108102 W.printNumber("Addend", WasmReloc.Addend);
109103 } else {
110 raw_ostream& OS = W.startLine();
104 raw_ostream &OS = W.startLine();
111105 OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
112106 if (!SymName.empty())
113107 OS << SymName;
168162 const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
169163 if (!LinkingData.InitFunctions.empty()) {
170164 ListScope Group(W, "InitFunctions");
171 for (const wasm::WasmInitFunc &F: LinkingData.InitFunctions)
165 for (const wasm::WasmInitFunc &F : LinkingData.InitFunctions)
172166 W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
173167 }
174168 }
176170 case wasm::WASM_SEC_DATA: {
177171 ListScope Group(W, "Segments");
178172 for (const WasmSegment &Segment : Obj->dataSegments()) {
179 const wasm::WasmDataSegment& Seg = Segment.Data;
173 const wasm::WasmDataSegment &Seg = Segment.Data;
180174 DictScope Group(W, "Segment");
181175 if (!Seg.Name.empty())
182176 W.printString("Name", Seg.Name);
218212 W.printHex("Flags", Symbol.Info.Flags);
219213 }
220214
221 }
215 } // namespace
222216
223217 namespace llvm {
224218
4848 return L;
4949 }
5050
51 std::unique_ptr WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
51 std::unique_ptr
52 WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
5253 std::unique_ptr CustomSec;
5354 if (WasmSec.Name == "name") {
54 std::unique_ptr NameSec = make_unique();
55 for (const llvm::wasm::WasmFunctionName &Func: Obj.debugNames()) {
55 std::unique_ptr NameSec =
56 make_unique();
57 for (const llvm::wasm::WasmFunctionName &Func : Obj.debugNames()) {
5658 WasmYAML::NameEntry NameEntry;
5759 NameEntry.Name = Func.Name;
5860 NameEntry.Index = Func.Index;
6062 }
6163 CustomSec = std::move(NameSec);
6264 } else if (WasmSec.Name == "linking") {
63 std::unique_ptr LinkingSec = make_unique();
65 std::unique_ptr LinkingSec =
66 make_unique();
6467 LinkingSec->Version = Obj.linkingData().Version;
6568
6669 ArrayRef Comdats = Obj.linkingData().Comdats;
6972 for (auto &Func : Obj.functions()) {
7073 if (Func.Comdat != UINT32_MAX) {
7174 LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
72 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
75 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
7376 }
7477 }
7578
289292 llvm_unreachable("Unknown section type");
290293 break;
291294 }
292 for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
295 for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
293296 WasmYAML::Relocation R;
294297 R.Type = Reloc.Type;
295298 R.Index = Reloc.Index;
126126 OutString.clear();
127127 }
128128
129 raw_ostream& GetStream() {
130 return StringStream;
131 }
129 raw_ostream &GetStream() { return StringStream; }
132130 };
133131
134 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
132 int WasmWriter::writeSectionContent(raw_ostream &OS,
133 WasmYAML::LinkingSection &Section) {
135134 writeStringRef(Section.Name, OS);
136135 encodeULEB128(Section.Version, OS);
137136
217216 return 0;
218217 }
219218
220 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
219 int WasmWriter::writeSectionContent(raw_ostream &OS,
220 WasmYAML::NameSection &Section) {
221221 writeStringRef(Section.Name, OS);
222222 if (Section.FunctionNames.size()) {
223223 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
295295 writeLimits(Import.Memory, OS);
296296 break;
297297 case wasm::WASM_EXTERNAL_TABLE:
298 writeUint8(OS,Import.TableImport.ElemType);
298 writeUint8(OS, Import.TableImport.ElemType);
299299 writeLimits(Import.TableImport.TableLimits, OS);
300300 break;
301301 default:
427427 int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
428428 uint32_t SectionIndex) {
429429 switch (Sec.Type) {
430 case wasm::WASM_SEC_CODE:
431 writeStringRef("reloc.CODE", OS);
432 break;
433 case wasm::WASM_SEC_DATA:
434 writeStringRef("reloc.DATA", OS);
435 break;
436 case wasm::WASM_SEC_CUSTOM: {
437 auto CustomSection = dyn_cast(&Sec);
438 if (!CustomSection->Name.startswith(".debug_")) {
439 llvm_unreachable("not yet implemented (only for debug sections)");
440 return 1;
441 }
442
443 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
444 break;
445 }
446 default:
447 llvm_unreachable("not yet implemented");
430 case wasm::WASM_SEC_CODE:
431 writeStringRef("reloc.CODE", OS);
432 break;
433 case wasm::WASM_SEC_DATA:
434 writeStringRef("reloc.DATA", OS);
435 break;
436 case wasm::WASM_SEC_CUSTOM: {
437 auto CustomSection = dyn_cast(&Sec);
438 if (!CustomSection->Name.startswith(".debug_")) {
439 llvm_unreachable("not yet implemented (only for debug sections)");
448440 return 1;
441 }
442
443 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
444 break;
445 }
446 default:
447 llvm_unreachable("not yet implemented");
448 return 1;
449449 }
450450
451451 encodeULEB128(SectionIndex, OS);
452452 encodeULEB128(Sec.Relocations.size(), OS);
453453
454 for (auto Reloc: Sec.Relocations) {
454 for (auto Reloc : Sec.Relocations) {
455455 writeUint8(OS, Reloc.Type);
456456 encodeULEB128(Reloc.Offset, OS);
457457 encodeULEB128(Reloc.Index, OS);
458458 switch (Reloc.Type) {
459 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
460 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
461 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
462 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
463 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
464 encodeULEB128(Reloc.Addend, OS);
465 }
466 }
467 return 0;
468 }
469
459 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
460 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
461 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
462 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
463 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
464 encodeULEB128(Reloc.Addend, OS);
465 }
466 }
467 return 0;
468 }
470469
471470 int WasmWriter::writeWasm(raw_ostream &OS) {
472471 // Write headers