llvm.org GIT mirror llvm / 9ac1c04
[WebAssembly] clang-tidy (NFC) Summary: This patch fixes clang-tidy warnings on wasm-only files. The list of checks used is: `-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,modernize-*` (LLVM's default .clang-tidy list is the same except it does not have `modernize-*`. But I've seen in multiple CLs in LLVM the modernize style was recommended and code was fixed based on the style, so I added it as well.) The common fixes are: - Variable names start with an uppercase letter - Function names start with a lowercase letter - Use `auto` when you use casts so the type is evident - Use inline initialization for class member variables - Use `= default` for empty constructors / destructors - Use `using` in place of `typedef` Reviewers: sbc100, tlively, aardappel Subscribers: dschuff, sunfish, jgravelle-google, yurydelendik, kripken, MatzeB, mgorny, rupprecht, llvm-commits Differential Revision: https://reviews.llvm.org/D57500 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353075 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 9 months ago
46 changed file(s) with 534 addition(s) and 551 deletion(s). Raw diff Collapse all Expand all
5454
5555 /// Decides whether a '.section' directive should be printed before the
5656 /// section name
57 bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
57 bool shouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
5858
5959 StringRef getSectionName() const { return SectionName; }
6060 const MCSymbolWasm *getGroup() const { return Group; }
77
88 #include "llvm/BinaryFormat/Wasm.h"
99
10 std::string llvm::wasm::toString(wasm::WasmSymbolType type) {
11 switch (type) {
10 std::string llvm::wasm::toString(wasm::WasmSymbolType Type) {
11 switch (Type) {
1212 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1313 return "WASM_SYMBOL_TYPE_FUNCTION";
1414 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
2323 llvm_unreachable("unknown symbol type");
2424 }
2525
26 std::string llvm::wasm::relocTypetoString(uint32_t type) {
27 switch (type) {
26 std::string llvm::wasm::relocTypetoString(uint32_t Type) {
27 switch (Type) {
2828 #define WASM_RELOC(NAME, VALUE) \
2929 case VALUE: \
3030 return #NAME;
3131 namespace {
3232
3333 class WasmAsmParser : public MCAsmParserExtension {
34 MCAsmParser *Parser;
35 MCAsmLexer *Lexer;
34 MCAsmParser *Parser = nullptr;
35 MCAsmLexer *Lexer = nullptr;
3636
3737 template
3838 void addDirectiveHandler(StringRef Directive) {
4343 }
4444
4545 public:
46 WasmAsmParser() : Parser(nullptr), Lexer(nullptr) {
47 BracketExpressionsSupported = true;
48 }
46 WasmAsmParser() { BracketExpressionsSupported = true; }
4947
5048 void Initialize(MCAsmParser &P) override {
5149 Parser = &P;
5957 addDirectiveHandler<&WasmAsmParser::parseDirectiveType>(".type");
6058 }
6159
62 bool Error(const StringRef &msg, const AsmToken &tok) {
63 return Parser->Error(tok.getLoc(), msg + tok.getString());
60 bool error(const StringRef &Msg, const AsmToken &Tok) {
61 return Parser->Error(Tok.getLoc(), Msg + Tok.getString());
6462 }
6563
66 bool IsNext(AsmToken::TokenKind Kind) {
67 auto ok = Lexer->is(Kind);
68 if (ok) Lex();
69 return ok;
64 bool isNext(AsmToken::TokenKind Kind) {
65 auto Ok = Lexer->is(Kind);
66 if (Ok)
67 Lex();
68 return Ok;
7069 }
7170
72 bool Expect(AsmToken::TokenKind Kind, const char *KindName) {
73 if (!IsNext(Kind))
74 return Error(std::string("Expected ") + KindName + ", instead got: ",
71 bool expect(AsmToken::TokenKind Kind, const char *KindName) {
72 if (!isNext(Kind))
73 return error(std::string("Expected ") + KindName + ", instead got: ",
7574 Lexer->getTok());
7675 return false;
7776 }
8685 if (Parser->parseIdentifier(Name))
8786 return TokError("expected identifier in directive");
8887 // FIXME: currently requiring this very fixed format.
89 if (Expect(AsmToken::Comma, ",") || Expect(AsmToken::String, "string") ||
90 Expect(AsmToken::Comma, ",") || Expect(AsmToken::At, "@") ||
91 Expect(AsmToken::EndOfStatement, "eol"))
88 if (expect(AsmToken::Comma, ",") || expect(AsmToken::String, "string") ||
89 expect(AsmToken::Comma, ",") || expect(AsmToken::At, "@") ||
90 expect(AsmToken::EndOfStatement, "eol"))
9291 return true;
9392 // This is done automatically by the assembler for text sections currently,
9493 // so we don't need to emit that here. This is what it would do (and may
105104 if (Parser->parseIdentifier(Name))
106105 return TokError("expected identifier in directive");
107106 auto Sym = getContext().getOrCreateSymbol(Name);
108 if (Expect(AsmToken::Comma, ","))
107 if (expect(AsmToken::Comma, ","))
109108 return true;
110109 const MCExpr *Expr;
111110 if (Parser->parseExpression(Expr))
112111 return true;
113 if (Expect(AsmToken::EndOfStatement, "eol"))
112 if (expect(AsmToken::EndOfStatement, "eol"))
114113 return true;
115114 // This is done automatically by the assembler for functions currently,
116115 // so we don't need to emit that here. This is what it would do:
123122 // This could be the start of a function, check if followed by
124123 // "label,@function"
125124 if (!Lexer->is(AsmToken::Identifier))
126 return Error("Expected label after .type directive, got: ",
125 return error("Expected label after .type directive, got: ",
127126 Lexer->getTok());
128127 auto WasmSym = cast(
129128 getStreamer().getContext().getOrCreateSymbol(
130129 Lexer->getTok().getString()));
131130 Lex();
132 if (!(IsNext(AsmToken::Comma) && IsNext(AsmToken::At) &&
131 if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) &&
133132 Lexer->is(AsmToken::Identifier)))
134 return Error("Expected label,@type declaration, got: ", Lexer->getTok());
133 return error("Expected label,@type declaration, got: ", Lexer->getTok());
135134 auto TypeName = Lexer->getTok().getString();
136135 if (TypeName == "function")
137136 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
138137 else if (TypeName == "global")
139138 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
140139 else
141 return Error("Unknown WASM symbol type: ", Lexer->getTok());
140 return error("Unknown WASM symbol type: ", Lexer->getTok());
142141 Lex();
143 return Expect(AsmToken::EndOfStatement, "EOL");
142 return expect(AsmToken::EndOfStatement, "EOL");
144143 }
145144 };
146145
1313
1414 using namespace llvm;
1515
16 MCSectionWasm::~MCSectionWasm() {} // anchor.
16 MCSectionWasm::~MCSectionWasm() = default; // anchor.
1717
1818 // Decides whether a '.section' directive
1919 // should be printed before the section name.
20 bool MCSectionWasm::ShouldOmitSectionDirective(StringRef Name,
20 bool MCSectionWasm::shouldOmitSectionDirective(StringRef Name,
2121 const MCAsmInfo &MAI) const {
2222 return MAI.shouldOmitSectionDirective(Name);
2323 }
4949 raw_ostream &OS,
5050 const MCExpr *Subsection) const {
5151
52 if (ShouldOmitSectionDirective(SectionName, MAI)) {
52 if (shouldOmitSectionDirective(SectionName, MAI)) {
5353 OS << '\t' << getSectionName();
5454 if (Subsection) {
5555 OS << '\t';
99
1010 using namespace llvm;
1111
12 MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit_)
13 : Is64Bit(Is64Bit_) {}
12 MCWasmObjectTargetWriter::MCWasmObjectTargetWriter(bool Is64Bit)
13 : Is64Bit(Is64Bit) {}
1414
1515 // Pin the vtable to this object file
1616 MCWasmObjectTargetWriter::~MCWasmObjectTargetWriter() = default;
3333
3434 using namespace llvm;
3535
36 MCWasmStreamer::~MCWasmStreamer() {}
36 MCWasmStreamer::~MCWasmStreamer() = default; // anchor.
3737
3838 void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
3939 flushPendingLabels(DF, DF->getContents().size());
4040
41 for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) {
42 EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() +
41 for (unsigned I = 0, E = EF->getFixups().size(); I != E; ++I) {
42 EF->getFixups()[I].setOffset(EF->getFixups()[I].getOffset() +
4343 DF->getContents().size());
44 DF->getFixups().push_back(EF->getFixups()[i]);
44 DF->getFixups().push_back(EF->getFixups()[I]);
4545 }
4646 if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo())
4747 DF->setHasInstructions(*EF->getSubtargetInfo());
178178 MCDataFragment *DF = getOrCreateDataFragment();
179179
180180 // Add the fixups and data.
181 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
182 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
183 DF->getFixups().push_back(Fixups[i]);
181 for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
182 Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size());
183 DF->getFixups().push_back(Fixups[I]);
184184 }
185185 DF->setHasInstructions(STI);
186186 DF->getContents().append(Code.begin(), Code.end());
3939
4040 // Went we ceate the indirect function table we start at 1, so that there is
4141 // and emtpy slot at 0 and therefore calling a null function pointer will trap.
42 static const uint32_t kInitialTableOffset = 1;
42 static const uint32_t InitialTableOffset = 1;
4343
4444 // For patching purposes, we need to remember where each section starts, both
4545 // for patching up the section size field, and for patching up references to
5959 // TODO: Consider using wasm::WasmSignature directly instead.
6060 struct WasmSignature {
6161 // Support empty and tombstone instances, needed by DenseMap.
62 enum { Plain, Empty, Tombstone } State;
62 enum { Plain, Empty, Tombstone } State = Plain;
6363
6464 // The return types of the function.
6565 SmallVector Returns;
6666
6767 // The parameter types of the function.
6868 SmallVector Params;
69
70 WasmSignature() : State(Plain) {}
7169
7270 bool operator==(const WasmSignature &Other) const {
7371 return State == Other.State && Returns == Other.Returns &&
171169 #endif
172170 };
173171
174 static const uint32_t INVALID_INDEX = -1;
172 static const uint32_t InvalidIndex = -1;
175173
176174 struct WasmCustomSection {
177175
183181
184182 WasmCustomSection(StringRef Name, MCSectionWasm *Section)
185183 : Name(Name), Section(Section), OutputContentsOffset(0),
186 OutputIndex(INVALID_INDEX) {}
184 OutputIndex(InvalidIndex) {}
187185 };
188186
189187 #if !defined(NDEBUG)
195193
196194 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
197195 // to allow patching.
198 static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
196 static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
199197 uint64_t Offset) {
200198 uint8_t Buffer[5];
201199 unsigned SizeLen = encodeULEB128(X, Buffer, 5);
205203
206204 // Write X as an signed LEB value at offset Offset in Stream, padded
207205 // to allow patching.
208 static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
206 static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
209207 uint64_t Offset) {
210208 uint8_t Buffer[5];
211209 unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
214212 }
215213
216214 // Write X as a plain integer value at offset Offset in Stream.
217 static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
215 static void writeI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
218216 uint8_t Buffer[4];
219217 support::endian::write32le(Buffer, X);
220218 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
280278 WasmObjectWriter(std::unique_ptr MOTW,
281279 raw_pwrite_stream &OS)
282280 : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
283
284 ~WasmObjectWriter() override;
285281
286282 private:
287283 void reset() override {
359355
360356 } // end anonymous namespace
361357
362 WasmObjectWriter::~WasmObjectWriter() {}
363
364358 // Write out a section header and a patchable section size field.
365359 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
366360 unsigned SectionId) {
411405
412406 // Write the final section size to the payload_len field, which follows
413407 // the section id byte.
414 WritePatchableLEB(static_cast(W.OS), Size,
408 writePatchableLEB(static_cast(W.OS), Size,
415409 Section.SizeOffset);
416410 }
417411
561555 }
562556 }
563557
564 static const MCSymbolWasm *ResolveSymbol(const MCSymbolWasm &Symbol) {
558 static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
565559 if (Symbol.isVariable()) {
566560 const MCExpr *Expr = Symbol.getVariableValue();
567561 auto *Inner = cast(Expr);
580574 case wasm::R_WASM_TABLE_INDEX_SLEB:
581575 case wasm::R_WASM_TABLE_INDEX_I32: {
582576 // Provisional value is table address of the resolved symbol itself
583 const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
577 const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
584578 assert(Sym->isFunction());
585579 return TableIndices[Sym];
586580 }
605599 case wasm::R_WASM_MEMORY_ADDR_I32:
606600 case wasm::R_WASM_MEMORY_ADDR_SLEB: {
607601 // Provisional value is address of the global
608 const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
602 const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
609603 // For undefined symbols, use zero
610604 if (!Sym->isDefined())
611605 return 0;
688682 case wasm::R_WASM_GLOBAL_INDEX_LEB:
689683 case wasm::R_WASM_MEMORY_ADDR_LEB:
690684 case wasm::R_WASM_EVENT_INDEX_LEB:
691 WritePatchableLEB(Stream, Value, Offset);
685 writePatchableLEB(Stream, Value, Offset);
692686 break;
693687 case wasm::R_WASM_TABLE_INDEX_I32:
694688 case wasm::R_WASM_MEMORY_ADDR_I32:
695689 case wasm::R_WASM_FUNCTION_OFFSET_I32:
696690 case wasm::R_WASM_SECTION_OFFSET_I32:
697 WriteI32(Stream, Value, Offset);
691 writeI32(Stream, Value, Offset);
698692 break;
699693 case wasm::R_WASM_TABLE_INDEX_SLEB:
700694 case wasm::R_WASM_MEMORY_ADDR_SLEB:
701 WritePatchableSLEB(Stream, Value, Offset);
695 writePatchableSLEB(Stream, Value, Offset);
702696 break;
703697 default:
704698 llvm_unreachable("invalid relocation type");
853847
854848 // init expr for starting offset
855849 W.OS << char(wasm::WASM_OPCODE_I32_CONST);
856 encodeSLEB128(kInitialTableOffset, W.OS);
850 encodeSLEB128(InitialTableOffset, W.OS);
857851 W.OS << char(wasm::WASM_OPCODE_END);
858852
859853 encodeULEB128(TableElems.size(), W.OS);
10861080 assert(Symbol.isFunction());
10871081
10881082 WasmSignature S;
1089 const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
1083 const MCSymbolWasm *ResolvedSym = resolveSymbol(Symbol);
10901084 if (auto *Sig = ResolvedSym->getSignature()) {
10911085 S.Returns = Sig->Returns;
10921086 S.Params = Sig->Params;
11631157 // For now, always emit the memory import, since loads and stores are not
11641158 // valid without it. In the future, we could perhaps be more clever and omit
11651159 // it if there are no loads or stores.
1166 MCSymbolWasm *MemorySym =
1160 auto *MemorySym =
11671161 cast(Ctx.getOrCreateSymbol("__linear_memory"));
11681162 wasm::WasmImport MemImport;
11691163 MemImport.Module = MemorySym->getImportModule();
11741168 // For now, always emit the table section, since indirect calls are not
11751169 // valid without it. In the future, we could perhaps be more clever and omit
11761170 // it if there are no indirect calls.
1177 MCSymbolWasm *TableSym =
1171 auto *TableSym =
11781172 cast(Ctx.getOrCreateSymbol("__indirect_function_table"));
11791173 wasm::WasmImport TableImport;
11801174 TableImport.Module = TableSym->getImportModule();
13241318 report_fatal_error(
13251319 "function sections must contain one function each");
13261320
1327 if (WS.getSize() == 0)
1321 if (WS.getSize() == nullptr)
13281322 report_fatal_error(
13291323 "function symbols must have a size set with .size");
13301324
14211415
14221416 // Find the target symbol of this weak alias and export that index
14231417 const auto &WS = static_cast(S);
1424 const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
1418 const MCSymbolWasm *ResolvedSym = resolveSymbol(WS);
14251419 LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym
14261420 << "'\n");
14271421
14451439 for (const MCSymbol &S : Asm.symbols()) {
14461440 const auto &WS = static_cast(S);
14471441 if (!isInSymtab(WS)) {
1448 WS.setIndex(INVALID_INDEX);
1442 WS.setIndex(InvalidIndex);
14491443 continue;
14501444 }
14511445 LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
14841478 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB)
14851479 return;
14861480 assert(Rel.Symbol->isFunction());
1487 const MCSymbolWasm &WS = *ResolveSymbol(*Rel.Symbol);
1481 const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol);
14881482 uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
1489 uint32_t TableIndex = TableElems.size() + kInitialTableOffset;
1483 uint32_t TableIndex = TableElems.size() + InitialTableOffset;
14901484 if (TableIndices.try_emplace(&WS, TableIndex).second) {
14911485 LLVM_DEBUG(dbgs() << " -> adding " << WS.getName()
14921486 << " to table: " << TableIndex << "\n");
15451539 const auto &DataFrag = cast(Frag);
15461540 const SmallVectorImpl &Contents = DataFrag.getContents();
15471541 for (const uint8_t *
1548 p = (const uint8_t *)Contents.data(),
1549 *end = (const uint8_t *)Contents.data() + Contents.size();
1550 p != end; ++p) {
1551 if (*p != 0)
1542 P = (const uint8_t *)Contents.data(),
1543 *End = (const uint8_t *)Contents.data() + Contents.size();
1544 P != End; ++P) {
1545 if (*P != 0)
15521546 report_fatal_error("non-symbolic data in .init_array section");
15531547 }
15541548 for (const MCFixup &Fixup : DataFrag.getFixups()) {
15601554 report_fatal_error("fixups in .init_array should be symbol references");
15611555 if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
15621556 report_fatal_error("symbols in .init_array should be for functions");
1563 if (Sym->getSymbol().getIndex() == INVALID_INDEX)
1557 if (Sym->getSymbol().getIndex() == InvalidIndex)
15641558 report_fatal_error("symbols in .init_array should exist in symbtab");
15651559 InitFuncs.push_back(
15661560 std::make_pair(Priority, Sym->getSymbol().getIndex()));
130130 }
131131
132132 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
133 int64_t result = readLEB128(Ctx);
134 if (result > VARUINT1_MAX || result < 0)
133 int64_t Result = readLEB128(Ctx);
134 if (Result > VARUINT1_MAX || Result < 0)
135135 report_fatal_error("LEB is outside Varuint1 range");
136 return result;
136 return Result;
137137 }
138138
139139 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
140 int64_t result = readLEB128(Ctx);
141 if (result > INT32_MAX || result < INT32_MIN)
140 int64_t Result = readLEB128(Ctx);
141 if (Result > INT32_MAX || Result < INT32_MIN)
142142 report_fatal_error("LEB is outside Varint32 range");
143 return result;
143 return Result;
144144 }
145145
146146 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
147 uint64_t result = readULEB128(Ctx);
148 if (result > UINT32_MAX)
147 uint64_t Result = readULEB128(Ctx);
148 if (Result > UINT32_MAX)
149149 report_fatal_error("LEB is outside Varuint32 range");
150 return result;
150 return Result;
151151 }
152152
153153 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
417417 if (Count > DataSegments.size())
418418 return make_error("Too many segment names",
419419 object_error::parse_failed);
420 for (uint32_t i = 0; i < Count; i++) {
421 DataSegments[i].Data.Name = readString(Ctx);
422 DataSegments[i].Data.Alignment = readVaruint32(Ctx);
423 DataSegments[i].Data.Flags = readVaruint32(Ctx);
420 for (uint32_t I = 0; I < Count; I++) {
421 DataSegments[I].Data.Name = readString(Ctx);
422 DataSegments[I].Data.Alignment = readVaruint32(Ctx);
423 DataSegments[I].Data.Flags = readVaruint32(Ctx);
424424 }
425425 break;
426426 }
427427 case wasm::WASM_INIT_FUNCS: {
428428 uint32_t Count = readVaruint32(Ctx);
429429 LinkingData.InitFunctions.reserve(Count);
430 for (uint32_t i = 0; i < Count; i++) {
430 for (uint32_t I = 0; I < Count; I++) {
431431 wasm::WasmInitFunc Init;
432432 Init.Priority = readVaruint32(Ctx);
433433 Init.Symbol = readVaruint32(Ctx);
661661 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
662662 llvm::SmallSet FieldsSeen;
663663 uint32_t Fields = readVaruint32(Ctx);
664 for (size_t i = 0; i < Fields; ++i) {
664 for (size_t I = 0; I < Fields; ++I) {
665665 StringRef FieldName = readString(Ctx);
666666 if (!FieldsSeen.insert(FieldName).second)
667667 return make_error(
682682 }
683683 uint32_t ValueCount = readVaruint32(Ctx);
684684 llvm::SmallSet ProducersSeen;
685 for (size_t j = 0; j < ValueCount; ++j) {
685 for (size_t J = 0; J < ValueCount; ++J) {
686686 StringRef Name = readString(Ctx);
687687 StringRef Version = readString(Ctx);
688688 if (!ProducersSeen.insert(Name).second) {
842842 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
843843 uint32_t Count = readVaruint32(Ctx);
844844 Imports.reserve(Count);
845 for (uint32_t i = 0; i < Count; i++) {
845 for (uint32_t I = 0; I < Count; I++) {
846846 wasm::WasmImport Im;
847847 Im.Module = readString(Ctx);
848848 Im.Field = readString(Ctx);
968968 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
969969 uint32_t Count = readVaruint32(Ctx);
970970 Exports.reserve(Count);
971 for (uint32_t i = 0; i < Count; i++) {
971 for (uint32_t I = 0; I < Count; I++) {
972972 wasm::WasmExport Ex;
973973 Ex.Name = readString(Ctx);
974974 Ex.Kind = readUint8(Ctx);
252252 }
253253
254254 bool ensureEmptyNestingStack() {
255 auto err = !NestingStack.empty();
255 auto Err = !NestingStack.empty();
256256 while (!NestingStack.empty()) {
257257 error(Twine("Unmatched block construct(s) at function end: ") +
258258 nestingString(NestingStack.back()).first);
259259 NestingStack.pop_back();
260260 }
261 return err;
261 return Err;
262262 }
263263
264264 bool isNext(AsmToken::TokenKind Kind) {
5151 // Print any additional variadic operands.
5252 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
5353 if (Desc.isVariadic())
54 for (auto i = Desc.getNumOperands(), e = MI->getNumOperands(); i < e; ++i) {
54 for (auto I = Desc.getNumOperands(), E = MI->getNumOperands(); I < E; ++I) {
5555 // FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because
5656 // we have an extra flags operand which is not currently printed, for
5757 // compatiblity reasons.
58 if (i != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
58 if (I != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
5959 MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
60 i != Desc.getNumOperands()))
60 I != Desc.getNumOperands()))
6161 OS << ", ";
62 printOperand(MI, i, OS);
62 printOperand(MI, I, OS);
6363 }
6464
6565 // Print any added annotation.
191191
192192 // Use C99's hexadecimal floating-point representation.
193193 static const size_t BufBytes = 128;
194 char buf[BufBytes];
194 char Buf[BufBytes];
195195 auto Written = FP.convertToHexString(
196 buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven);
196 Buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven);
197197 (void)Written;
198198 assert(Written != 0);
199199 assert(Written < BufBytes);
200 return buf;
200 return Buf;
201201 }
202202
203203 void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
3434 public:
3535 explicit WebAssemblyAsmBackend(bool Is64Bit)
3636 : MCAsmBackend(support::little), Is64Bit(Is64Bit) {}
37 ~WebAssemblyAsmBackend() override {}
3837
3938 unsigned getNumFixupKinds() const override {
4039 return WebAssembly::NumTargetFixupKinds;
9089
9190 bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS,
9291 uint64_t Count) const {
93 for (uint64_t i = 0; i < Count; ++i)
92 for (uint64_t I = 0; I < Count; ++I)
9493 OS << char(WebAssembly::Nop);
9594
9695 return true;
117116
118117 // For each byte of the fragment that the fixup touches, mask in the
119118 // bits from the fixup value.
120 for (unsigned i = 0; i != NumBytes; ++i)
121 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
119 for (unsigned I = 0; I != NumBytes; ++I)
120 Data[Offset + I] |= uint8_t((Value >> (I * 8)) & 0xff);
122121 }
123122
124123 std::unique_ptr
1818
1919 #define DEBUG_TYPE "wasm-mc-asm-info"
2020
21 WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() {}
21 WebAssemblyMCAsmInfo::~WebAssemblyMCAsmInfo() = default; // anchor.
2222
2323 WebAssemblyMCAsmInfo::WebAssemblyMCAsmInfo(const Triple &T) {
2424 CodePointerSize = CalleeSaveStackSlotSize = T.isArch64Bit() ? 8 : 4;
4747 const MCSubtargetInfo &STI) const override;
4848
4949 public:
50 WebAssemblyMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {}
50 WebAssemblyMCCodeEmitter(const MCInstrInfo &MCII) : MCII(MCII) {}
5151 };
5252 } // end anonymous namespace
5353
8080 encodeULEB128(MI.getNumOperands() - 2, OS);
8181
8282 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
83 for (unsigned i = 0, e = MI.getNumOperands(); i < e; ++i) {
84 const MCOperand &MO = MI.getOperand(i);
83 for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
84 const MCOperand &MO = MI.getOperand(I);
8585 if (MO.isReg()) {
8686 /* nothing to encode */
8787
8888 } else if (MO.isImm()) {
89 if (i < Desc.getNumOperands()) {
90 const MCOperandInfo &Info = Desc.OpInfo[i];
89 if (I < Desc.getNumOperands()) {
90 const MCOperandInfo &Info = Desc.OpInfo[I];
9191 LLVM_DEBUG(dbgs() << "Encoding immediate: type="
9292 << int(Info.OperandType) << "\n");
9393 switch (Info.OperandType) {
125125 }
126126
127127 } else if (MO.isFPImm()) {
128 const MCOperandInfo &Info = Desc.OpInfo[i];
128 const MCOperandInfo &Info = Desc.OpInfo[I];
129129 if (Info.OperandType == WebAssembly::OPERAND_F32IMM) {
130130 // TODO: MC converts all floating point immediate operands to double.
131131 // This is fine for numeric values, but may cause NaNs to change bits.
132 float f = float(MO.getFPImm());
133 support::endian::write(OS, f, support::little);
132 auto F = float(MO.getFPImm());
133 support::endian::write(OS, F, support::little);
134134 } else {
135135 assert(Info.OperandType == WebAssembly::OPERAND_F64IMM);
136 double d = MO.getFPImm();
137 support::endian::write(OS, d, support::little);
136 double D = MO.getFPImm();
137 support::endian::write(OS, D, support::little);
138138 }
139139
140140 } else if (MO.isExpr()) {
141 const MCOperandInfo &Info = Desc.OpInfo[i];
141 const MCOperandInfo &Info = Desc.OpInfo[I];
142142 llvm::MCFixupKind FixupKind;
143143 size_t PaddedSize = 5;
144144 switch (Info.OperandType) {
3838 }
3939
4040 static MCInstrInfo *createMCInstrInfo() {
41 MCInstrInfo *X = new MCInstrInfo();
41 auto *X = new MCInstrInfo();
4242 InitWebAssemblyMCInstrInfo(X);
4343 return X;
4444 }
4545
4646 static MCRegisterInfo *createMCRegisterInfo(const Triple & /*T*/) {
47 MCRegisterInfo *X = new MCRegisterInfo();
47 auto *X = new MCRegisterInfo();
4848 InitWebAssemblyMCRegisterInfo(X, 0);
4949 return X;
5050 }
4242 : MCWasmObjectTargetWriter(Is64Bit) {}
4343
4444 // Test whether the given expression computes a function address.
45 static bool IsFunctionExpr(const MCExpr *Expr) {
45 static bool isFunctionExpr(const MCExpr *Expr) {
4646 if (auto SyExp = dyn_cast(Expr))
4747 return cast(SyExp->getSymbol()).isFunction();
4848
4949 if (auto BinOp = dyn_cast(Expr))
50 return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS());
50 return isFunctionExpr(BinOp->getLHS()) != isFunctionExpr(BinOp->getRHS());
5151
5252 if (auto UnOp = dyn_cast(Expr))
53 return IsFunctionExpr(UnOp->getSubExpr());
53 return isFunctionExpr(UnOp->getSubExpr());
5454
5555 return false;
5656 }
5757
58 static bool IsFunctionType(const MCValue &Target) {
58 static bool isFunctionType(const MCValue &Target) {
5959 const MCSymbolRefExpr *RefA = Target.getSymA();
6060 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX;
6161 }
6262
63 static const MCSection *GetFixupSection(const MCExpr *Expr) {
63 static const MCSection *getFixupSection(const MCExpr *Expr) {
6464 if (auto SyExp = dyn_cast(Expr)) {
6565 if (SyExp->getSymbol().isInSection())
6666 return &SyExp->getSymbol().getSection();
6868 }
6969
7070 if (auto BinOp = dyn_cast(Expr)) {
71 auto SectionLHS = GetFixupSection(BinOp->getLHS());
72 auto SectionRHS = GetFixupSection(BinOp->getRHS());
71 auto SectionLHS = getFixupSection(BinOp->getLHS());
72 auto SectionRHS = getFixupSection(BinOp->getRHS());
7373 return SectionLHS == SectionRHS ? nullptr : SectionLHS;
7474 }
7575
7676 if (auto UnOp = dyn_cast(Expr))
77 return GetFixupSection(UnOp->getSubExpr());
77 return getFixupSection(UnOp->getSubExpr());
7878
7979 return nullptr;
8080 }
8181
82 static bool IsGlobalType(const MCValue &Target) {
82 static bool isGlobalType(const MCValue &Target) {
8383 const MCSymbolRefExpr *RefA = Target.getSymA();
8484 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
8585 }
8686
87 static bool IsEventType(const MCValue &Target) {
87 static bool isEventType(const MCValue &Target) {
8888 const MCSymbolRefExpr *RefA = Target.getSymA();
8989 return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_EVENT;
9090 }
9393 const MCFixup &Fixup) const {
9494 // WebAssembly functions are not allocated in the data address space. To
9595 // resolve a pointer to a function, we must use a special relocation type.
96 bool IsFunction = IsFunctionExpr(Fixup.getValue());
96 bool IsFunction = isFunctionExpr(Fixup.getValue());
9797
9898 switch (unsigned(Fixup.getKind())) {
9999 case WebAssembly::fixup_code_sleb128_i32:
103103 case WebAssembly::fixup_code_sleb128_i64:
104104 llvm_unreachable("fixup_sleb128_i64 not implemented yet");
105105 case WebAssembly::fixup_code_uleb128_i32:
106 if (IsGlobalType(Target))
106 if (isGlobalType(Target))
107107 return wasm::R_WASM_GLOBAL_INDEX_LEB;
108 if (IsFunctionType(Target))
108 if (isFunctionType(Target))
109109 return wasm::R_WASM_TYPE_INDEX_LEB;
110110 if (IsFunction)
111111 return wasm::R_WASM_FUNCTION_INDEX_LEB;
112 if (IsEventType(Target))
112 if (isEventType(Target))
113113 return wasm::R_WASM_EVENT_INDEX_LEB;
114114 return wasm::R_WASM_MEMORY_ADDR_LEB;
115115 case FK_Data_4:
116116 if (IsFunction)
117117 return wasm::R_WASM_TABLE_INDEX_I32;
118118 if (auto Section = static_cast(
119 GetFixupSection(Fixup.getValue()))) {
119 getFixupSection(Fixup.getValue()))) {
120120 if (Section->getKind().isText())
121121 return wasm::R_WASM_FUNCTION_OFFSET_I32;
122122 else if (!Section->isWasmData())
9494 if (F.isDeclarationForLinker() && !F.isIntrinsic()) {
9595 SmallVector Results;
9696 SmallVector Params;
97 ComputeSignatureVTs(F.getFunctionType(), F, TM, Params, Results);
97 computeSignatureVTs(F.getFunctionType(), F, TM, Params, Results);
9898 auto *Sym = cast(getSymbol(&F));
9999 Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
100100 if (!Sym->getSignature()) {
101 auto Signature = SignatureFromMVTs(Results, Params);
101 auto Signature = signatureFromMVTs(Results, Params);
102102 Sym->setSignature(Signature.get());
103103 addSignature(std::move(Signature));
104104 }
138138
139139 if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
140140 for (const Metadata *MD : Named->operands()) {
141 const MDTuple *Tuple = dyn_cast(MD);
141 const auto *Tuple = dyn_cast(MD);
142142 if (!Tuple || Tuple->getNumOperands() != 2)
143143 continue;
144144 const MDString *Name = dyn_cast(Tuple->getOperand(0));
148148
149149 OutStreamer->PushSection();
150150 std::string SectionName = (".custom_section." + Name->getString()).str();
151 MCSectionWasm *mySection =
151 MCSectionWasm *MySection =
152152 OutContext.getWasmSection(SectionName, SectionKind::getMetadata());
153 OutStreamer->SwitchSection(mySection);
153 OutStreamer->SwitchSection(MySection);
154154 OutStreamer->EmitBytes(Contents->getString());
155155 OutStreamer->PopSection();
156156 }
162162 void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
163163 llvm::SmallVector, 4> Languages;
164164 if (const NamedMDNode *Debug = M.getNamedMetadata("llvm.dbg.cu")) {
165 llvm::SmallSet SeenLanguages;
166 for (size_t i = 0, e = Debug->getNumOperands(); i < e; ++i) {
167 const auto *CU = cast(Debug->getOperand(i));
165 llvm::SmallSet SeenLanguages;
166 for (size_t I = 0, E = Debug->getNumOperands(); I < E; ++I) {
167 const auto *CU = cast(Debug->getOperand(I));
168168 StringRef Language = dwarf::LanguageString(CU->getSourceLanguage());
169169 Language.consume_front("DW_LANG_");
170170 if (SeenLanguages.insert(Language).second)
175175 llvm::SmallVector, 4> Tools;
176176 if (const NamedMDNode *Ident = M.getNamedMetadata("llvm.ident")) {
177177 llvm::SmallSet SeenTools;
178 for (size_t i = 0, e = Ident->getNumOperands(); i < e; ++i) {
179 const auto *S = cast(Ident->getOperand(i)->getOperand(0));
178 for (size_t I = 0, E = Ident->getNumOperands(); I < E; ++I) {
179 const auto *S = cast(Ident->getOperand(I)->getOperand(0));
180180 std::pair Field = S->getString().split("version");
181181 StringRef Name = Field.first.trim();
182182 StringRef Version = Field.second.trim();
223223 const Function &F = MF->getFunction();
224224 SmallVector ResultVTs;
225225 SmallVector ParamVTs;
226 ComputeSignatureVTs(F.getFunctionType(), F, TM, ParamVTs, ResultVTs);
227 auto Signature = SignatureFromMVTs(ResultVTs, ParamVTs);
226 computeSignatureVTs(F.getFunctionType(), F, TM, ParamVTs, ResultVTs);
227 auto Signature = signatureFromMVTs(ResultVTs, ParamVTs);
228228 auto *WasmSym = cast(CurrentFnSym);
229229 WasmSym->setSignature(Signature.get());
230230 addSignature(std::move(Signature));
242242 }
243243
244244 SmallVector Locals;
245 ValTypesFromMVTs(MFI->getLocals(), Locals);
245 valTypesFromMVTs(MFI->getLocals(), Locals);
246246 getTargetStreamer()->emitLocal(Locals);
247247
248248 AsmPrinter::EmitFunctionBodyStart();
323323 default: {
324324 WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
325325 MCInst TmpInst;
326 MCInstLowering.Lower(MI, TmpInst);
326 MCInstLowering.lower(MI, TmpInst);
327327 EmitToStreamer(*OutStreamer, TmpInst);
328328 break;
329329 }
331331 }
332332
333333 const MCExpr *WebAssemblyAsmPrinter::lowerConstant(const Constant *CV) {
334 if (const GlobalValue *GV = dyn_cast(CV))
334 if (const auto *GV = dyn_cast(CV))
335335 if (GV->getValueType()->isFunctionTy()) {
336336 return MCSymbolRefExpr::create(
337337 getSymbol(GV), MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext);
131131 return new WebAssemblyCFGSort();
132132 }
133133
134 static void MaybeUpdateTerminator(MachineBasicBlock *MBB) {
134 static void maybeUpdateTerminator(MachineBasicBlock *MBB) {
135135 #ifndef NDEBUG
136136 bool AnyBarrier = false;
137137 #endif
226226 /// interrupted by blocks not dominated by their header.
227227 /// TODO: There are many opportunities for improving the heuristics here.
228228 /// Explore them.
229 static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
229 static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
230230 const WebAssemblyExceptionInfo &WEI,
231231 const MachineDominatorTree &MDT) {
232232 // Prepare for a topological sort: Record the number of predecessors each
318318 if (!Next) {
319319 // If there are no more blocks to process, we're done.
320320 if (Ready.empty()) {
321 MaybeUpdateTerminator(MBB);
321 maybeUpdateTerminator(MBB);
322322 break;
323323 }
324324 for (;;) {
336336 }
337337 // Move the next block into place and iterate.
338338 Next->moveAfter(MBB);
339 MaybeUpdateTerminator(MBB);
339 maybeUpdateTerminator(MBB);
340340 MBB = Next;
341341 }
342342 assert(Entries.empty() && "Active sort region list not finished");
402402 MF.getRegInfo().invalidateLiveness();
403403
404404 // Sort the blocks, with contiguous sort regions.
405 SortBlocks(MF, MLI, WEI, MDT);
405 sortBlocks(MF, MLI, WEI, MDT);
406406
407407 return true;
408408 }
107107 /// code) for a branch instruction to both branch to a block and fallthrough
108108 /// to it, so we check the actual branch operands to see if there are any
109109 /// explicit mentions.
110 static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred,
110 static bool explicitlyBranchesTo(MachineBasicBlock *Pred,
111111 MachineBasicBlock *MBB) {
112112 for (MachineInstr &MI : Pred->terminators())
113113 for (MachineOperand &MO : MI.explicit_operands())
122122 // ones that should go after the marker. In this function, AfterSet is only
123123 // used for sanity checking.
124124 static MachineBasicBlock::iterator
125 GetEarliestInsertPos(MachineBasicBlock *MBB,
125 getEarliestInsertPos(MachineBasicBlock *MBB,
126126 const SmallPtrSet &BeforeSet,
127127 const SmallPtrSet &AfterSet) {
128128 auto InsertPos = MBB->end();
146146 // ones that should go after the marker. In this function, BeforeSet is only
147147 // used for sanity checking.
148148 static MachineBasicBlock::iterator
149 GetLatestInsertPos(MachineBasicBlock *MBB,
149 getLatestInsertPos(MachineBasicBlock *MBB,
150150 const SmallPtrSet &BeforeSet,
151151 const SmallPtrSet &AfterSet) {
152152 auto InsertPos = MBB->begin();
221221 for (MachineBasicBlock *Pred : MBB.predecessors()) {
222222 if (Pred->getNumber() < MBBNumber) {
223223 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
224 if (ExplicitlyBranchesTo(Pred, &MBB)) {
224 if (explicitlyBranchesTo(Pred, &MBB)) {
225225 IsBranchedTo = true;
226226 if (Pred->getFirstTerminator()->getOpcode() == WebAssembly::BR_ON_EXN) {
227227 IsBrOnExn = true;
321321 ReturnType = WebAssembly::ExprType::I32;
322322 }
323323
324 auto InsertPos = GetLatestInsertPos(Header, BeforeSet, AfterSet);
324 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
325325 MachineInstr *Begin =
326326 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
327327 TII.get(WebAssembly::BLOCK))
354354 }
355355
356356 // Mark the end of the block.
357 InsertPos = GetEarliestInsertPos(&MBB, BeforeSet, AfterSet);
357 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
358358 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
359359 TII.get(WebAssembly::END_BLOCK));
360360 registerScope(Begin, End);
404404 }
405405
406406 // Mark the beginning of the loop.
407 auto InsertPos = GetEarliestInsertPos(&MBB, BeforeSet, AfterSet);
407 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
408408 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
409409 TII.get(WebAssembly::LOOP))
410410 .addImm(int64_t(WebAssembly::ExprType::Void));
421421
422422 // Mark the end of the loop (using arbitrary debug location that branched to
423423 // the loop end as its location).
424 InsertPos = GetEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
424 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
425425 DebugLoc EndDL = (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
426426 MachineInstr *End =
427427 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
450450 for (auto *Pred : MBB.predecessors()) {
451451 if (Pred->getNumber() < MBBNumber) {
452452 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
453 assert(!ExplicitlyBranchesTo(Pred, &MBB) &&
453 assert(!explicitlyBranchesTo(Pred, &MBB) &&
454454 "Explicit branch to an EH pad!");
455455 }
456456 }
558558 }
559559
560560 // Add the TRY.
561 auto InsertPos = GetLatestInsertPos(Header, BeforeSet, AfterSet);
561 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
562562 MachineInstr *Begin =
563563 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
564564 TII.get(WebAssembly::TRY))
594594 }
595595
596596 // Mark the end of the TRY.
597 InsertPos = GetEarliestInsertPos(AfterTry, BeforeSet, AfterSet);
597 InsertPos = getEarliestInsertPos(AfterTry, BeforeSet, AfterSet);
598598 MachineInstr *End =
599599 BuildMI(*AfterTry, InsertPos, Bottom->findBranchDebugLoc(),
600600 TII.get(WebAssembly::END_TRY));
608608 }
609609
610610 static unsigned
611 GetDepth(const SmallVectorImpl &Stack,
611 getDepth(const SmallVectorImpl &Stack,
612612 const MachineBasicBlock *MBB) {
613613 unsigned Depth = 0;
614614 for (auto X : reverse(Stack)) {
634634 if (MFI.getResults().empty())
635635 return;
636636
637 WebAssembly::ExprType retType;
637 WebAssembly::ExprType RetType;
638638 switch (MFI.getResults().front().SimpleTy) {
639639 case MVT::i32:
640 retType = WebAssembly::ExprType::I32;
640 RetType = WebAssembly::ExprType::I32;
641641 break;
642642 case MVT::i64:
643 retType = WebAssembly::ExprType::I64;
643 RetType = WebAssembly::ExprType::I64;
644644 break;
645645 case MVT::f32:
646 retType = WebAssembly::ExprType::F32;
646 RetType = WebAssembly::ExprType::F32;
647647 break;
648648 case MVT::f64:
649 retType = WebAssembly::ExprType::F64;
649 RetType = WebAssembly::ExprType::F64;
650650 break;
651651 case MVT::v16i8:
652652 case MVT::v8i16:
654654 case MVT::v2i64:
655655 case MVT::v4f32:
656656 case MVT::v2f64:
657 retType = WebAssembly::ExprType::V128;
657 RetType = WebAssembly::ExprType::V128;
658658 break;
659659 case MVT::ExceptRef:
660 retType = WebAssembly::ExprType::ExceptRef;
660 RetType = WebAssembly::ExprType::ExceptRef;
661661 break;
662662 default:
663663 llvm_unreachable("unexpected return type");
668668 if (MI.isPosition() || MI.isDebugInstr())
669669 continue;
670670 if (MI.getOpcode() == WebAssembly::END_BLOCK) {
671 EndToBegin[&MI]->getOperand(0).setImm(int32_t(retType));
671 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
672672 continue;
673673 }
674674 if (MI.getOpcode() == WebAssembly::END_LOOP) {
675 EndToBegin[&MI]->getOperand(0).setImm(int32_t(retType));
675 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
676676 continue;
677677 }
678678 // Something other than an `end`. We're done.
683683
684684 // WebAssembly functions end with an end instruction, as if the function body
685685 // were a block.
686 static void AppendEndToFunction(MachineFunction &MF,
686 static void appendEndToFunction(MachineFunction &MF,
687687 const WebAssemblyInstrInfo &TII) {
688688 BuildMI(MF.back(), MF.back().end(),
689689 MF.back().findPrevDebugLoc(MF.back().end()),
752752 MI.RemoveOperand(MI.getNumOperands() - 1);
753753 for (auto MO : Ops) {
754754 if (MO.isMBB())
755 MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB()));
755 MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB()));
756756 MI.addOperand(MF, MO);
757757 }
758758 }
797797 if (!MF.getSubtarget()
798798 .getTargetTriple()
799799 .isOSBinFormatELF())
800 AppendEndToFunction(MF, TII);
800 appendEndToFunction(MF, TII);
801801
802802 return true;
803803 }
5959 return new WebAssemblyCallIndirectFixup();
6060 }
6161
62 static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
62 static unsigned getNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
6363 switch (MI.getOpcode()) {
6464 using namespace WebAssembly;
6565 case PCALL_INDIRECT_VOID:
8989 }
9090 }
9191
92 static bool IsPseudoCallIndirect(const MachineInstr &MI) {
93 return GetNonPseudoCallIndirectOpcode(MI) !=
92 static bool isPseudoCallIndirect(const MachineInstr &MI) {
93 return getNonPseudoCallIndirectOpcode(MI) !=
9494 WebAssembly::INSTRUCTION_LIST_END;
9595 }
9696
104104
105105 for (MachineBasicBlock &MBB : MF) {
106106 for (MachineInstr &MI : MBB) {
107 if (IsPseudoCallIndirect(MI)) {
107 if (isPseudoCallIndirect(MI)) {
108108 LLVM_DEBUG(dbgs() << "Found call_indirect: " << MI << '\n');
109109
110110 // Rewrite pseudo to non-pseudo
111 const MCInstrDesc &Desc = TII->get(GetNonPseudoCallIndirectOpcode(MI));
111 const MCInstrDesc &Desc = TII->get(getNonPseudoCallIndirectOpcode(MI));
112112 MI.setDesc(Desc);
113113
114114 // Rewrite argument order
4848 // All possible address modes.
4949 class Address {
5050 public:
51 typedef enum { RegBase, FrameIndexBase } BaseKind;
51 using BaseKind = enum { RegBase, FrameIndexBase };
5252
5353 private:
54 BaseKind Kind;
54 BaseKind Kind = RegBase;
5555 union {
5656 unsigned Reg;
5757 int FI;
5858 } Base;
5959
60 int64_t Offset;
61
62 const GlobalValue *GV;
60 int64_t Offset = 0;
61
62 const GlobalValue *GV = nullptr;
6363
6464 public:
6565 // Innocuous defaults for our address.
66 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
66 Address() { Base.Reg = 0; }
6767 void setKind(BaseKind K) {
6868 assert(!isSet() && "Can't change kind with non-zero base");
6969 Kind = K;
9090 return Base.FI;
9191 }
9292
93 void setOffset(int64_t Offset_) {
94 assert(Offset_ >= 0 && "Offsets must be non-negative");
95 Offset = Offset_;
93 void setOffset(int64_t NewOffset) {
94 assert(NewOffset >= 0 && "Offsets must be non-negative");
95 Offset = NewOffset;
9696 }
9797 int64_t getOffset() const { return Offset; }
9898 void setGlobalValue(const GlobalValue *G) { GV = G; }
209209
210210 const User *U = nullptr;
211211 unsigned Opcode = Instruction::UserOp1;
212 if (const Instruction *I = dyn_cast(Obj)) {
212 if (const auto *I = dyn_cast(Obj)) {
213213 // Don't walk into other basic blocks unless the object is an alloca from
214214 // another block, otherwise it may not have a virtual register assigned.
215215 if (FuncInfo.StaticAllocaMap.count(static_cast(Obj)) ||
217217 Opcode = I->getOpcode();
218218 U = I;
219219 }
220 } else if (const ConstantExpr *C = dyn_cast(Obj)) {
220 } else if (const auto *C = dyn_cast(Obj)) {
221221 Opcode = C->getOpcode();
222222 U = C;
223223 }
228228 // address spaces.
229229 return false;
230230
231 if (const GlobalValue *GV = dyn_cast(Obj)) {
231 if (const auto *GV = dyn_cast(Obj)) {
232232 if (Addr.getGlobalValue())
233233 return false;
234234 Addr.setGlobalValue(GV);
273273 } else {
274274 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
275275 for (;;) {
276 if (const ConstantInt *CI = dyn_cast(Op)) {
276 if (const auto *CI = dyn_cast(Op)) {
277277 // Constant-offset addressing.
278278 TmpOffset += CI->getSExtValue() * S;
279279 break;
288288 }
289289 if (canFoldAddIntoGEP(U, Op)) {
290290 // A compatible add with a constant operand. Fold the constant.
291 ConstantInt *CI =
292 cast(cast(Op)->getOperand(1));
291 auto *CI = cast(cast(Op)->getOperand(1));
293292 TmpOffset += CI->getSExtValue() * S;
294293 // Iterate on the other operand.
295294 Op = cast(Op)->getOperand(0);
313312 break;
314313 }
315314 case Instruction::Alloca: {
316 const AllocaInst *AI = cast(Obj);
315 const auto *AI = cast(Obj);
317316 DenseMap::iterator SI =
318317 FuncInfo.StaticAllocaMap.find(AI);
319318 if (SI != FuncInfo.StaticAllocaMap.end()) {
334333 if (isa(LHS))
335334 std::swap(LHS, RHS);
336335
337 if (const ConstantInt *CI = dyn_cast(RHS)) {
336 if (const auto *CI = dyn_cast(RHS)) {
338337 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
339338 if (int64_t(TmpOffset) >= 0) {
340339 Addr.setOffset(TmpOffset);
354353 const Value *LHS = U->getOperand(0);
355354 const Value *RHS = U->getOperand(1);
356355
357 if (const ConstantInt *CI = dyn_cast(RHS)) {
356 if (const auto *CI = dyn_cast(RHS)) {
358357 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
359358 if (TmpOffset >= 0) {
360359 Addr.setOffset(TmpOffset);
414413 }
415414
416415 unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
417 if (const ICmpInst *ICmp = dyn_cast(V))
416 if (const auto *ICmp = dyn_cast(V))
418417 if (const ConstantInt *C = dyn_cast(ICmp->getOperand(1)))
419418 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
420419 Not = ICmp->isTrueWhenEqual();
604603 }
605604
606605 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
607 if (const GlobalValue *GV = dyn_cast(C)) {
606 if (const auto *GV = dyn_cast(C)) {
608607 unsigned ResultReg =
609608 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
610609 : &WebAssembly::I32RegClass);
627626 if (F->isVarArg())
628627 return false;
629628
630 unsigned i = 0;
629 unsigned I = 0;
631630 for (auto const &Arg : F->args()) {
632631 const AttributeList &Attrs = F->getAttributes();
633 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
634 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
635 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
636 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
637 Attrs.hasParamAttribute(i, Attribute::Nest))
632 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
633 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
634 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
635 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
636 Attrs.hasParamAttribute(I, Attribute::Nest))
638637 return false;
639638
640639 Type *ArgTy = Arg.getType();
698697 }
699698 unsigned ResultReg = createResultReg(RC);
700699 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
701 .addImm(i);
700 .addImm(I);
702701 updateValueMap(&Arg, ResultReg);
703702
704 ++i;
703 ++I;
705704 }
706705
707706 MRI.addLiveIn(WebAssembly::ARGUMENTS);
730729 }
731730
732731 bool WebAssemblyFastISel::selectCall(const Instruction *I) {
733 const CallInst *Call = cast(I);
732 const auto *Call = cast(I);
734733
735734 if (Call->isMustTailCall() || Call->isInlineAsm() ||
736735 Call->getFunctionType()->isVarArg())
816815 }
817816
818817 SmallVector Args;
819 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
820 Value *V = Call->getArgOperand(i);
818 for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
819 Value *V = Call->getArgOperand(I);
821820 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
822821 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
823822 return false;
824823
825824 const AttributeList &Attrs = Call->getAttributes();
826 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
827 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
828 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
829 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
830 Attrs.hasParamAttribute(i, Attribute::Nest))
825 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
826 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
827 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
828 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
829 Attrs.hasParamAttribute(I, Attribute::Nest))
831830 return false;
832831
833832 unsigned Reg;
834833
835 if (Attrs.hasParamAttribute(i, Attribute::SExt))
834 if (Attrs.hasParamAttribute(I, Attribute::SExt))
836835 Reg = getRegForSignedValue(V);
837 else if (Attrs.hasParamAttribute(i, Attribute::ZExt))
836 else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
838837 Reg = getRegForUnsignedValue(V);
839838 else
840839 Reg = getRegForValue(V);
868867 }
869868
870869 bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
871 const SelectInst *Select = cast(I);
870 const auto *Select = cast(I);
872871
873872 bool Not;
874873 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
927926 }
928927
929928 bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
930 const TruncInst *Trunc = cast(I);
929 const auto *Trunc = cast(I);
931930
932931 unsigned Reg = getRegForValue(Trunc->getOperand(0));
933932 if (Reg == 0)
946945 }
947946
948947 bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
949 const ZExtInst *ZExt = cast(I);
948 const auto *ZExt = cast(I);
950949
951950 const Value *Op = ZExt->getOperand(0);
952951 MVT::SimpleValueType From = getSimpleType(Op->getType());
963962 }
964963
965964 bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
966 const SExtInst *SExt = cast(I);
965 const auto *SExt = cast(I);
967966
968967 const Value *Op = SExt->getOperand(0);
969968 MVT::SimpleValueType From = getSimpleType(Op->getType());
980979 }
981980
982981 bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
983 const ICmpInst *ICmp = cast(I);
982 const auto *ICmp = cast(I);
984983
985984 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
986985 unsigned Opc;
987 bool isSigned = false;
986 bool IsSigned = false;
988987 switch (ICmp->getPredicate()) {
989988 case ICmpInst::ICMP_EQ:
990989 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
10061005 break;
10071006 case ICmpInst::ICMP_SGT:
10081007 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1009 isSigned = true;
1008 IsSigned = true;
10101009 break;
10111010 case ICmpInst::ICMP_SGE:
10121011 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1013 isSigned = true;
1012 IsSigned = true;
10141013 break;
10151014 case ICmpInst::ICMP_SLT:
10161015 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1017 isSigned = true;
1016 IsSigned = true;
10181017 break;
10191018 case ICmpInst::ICMP_SLE:
10201019 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1021 isSigned = true;
1020 IsSigned = true;
10221021 break;
10231022 default:
10241023 return false;
10251024 }
10261025
1027 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
1026 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
10281027 if (LHS == 0)
10291028 return false;
10301029
1031 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
1030 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
10321031 if (RHS == 0)
10331032 return false;
10341033
10411040 }
10421041
10431042 bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1044 const FCmpInst *FCmp = cast(I);
1043 const auto *FCmp = cast(I);
10451044
10461045 unsigned LHS = getRegForValue(FCmp->getOperand(0));
10471046 if (LHS == 0)
11371136 }
11381137
11391138 bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1140 const LoadInst *Load = cast(I);
1139 const auto *Load = cast(I);
11411140 if (Load->isAtomic())
11421141 return false;
11431142 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
11941193 }
11951194
11961195 bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1197 const StoreInst *Store = cast(I);
1196 const auto *Store = cast(I);
11981197 if (Store->isAtomic())
11991198 return false;
12001199 if (!Subtarget->hasSIMD128() &&
12501249 }
12511250
12521251 bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1253 const BranchInst *Br = cast(I);
1252 const auto *Br = cast(I);
12541253 if (Br->isUnconditional()) {
12551254 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
12561255 fastEmitBranch(MSucc, Br->getDebugLoc());
12811280 if (!FuncInfo.CanLowerReturn)
12821281 return false;
12831282
1284 const ReturnInst *Ret = cast(I);
1283 const auto *Ret = cast(I);
12851284
12861285 if (Ret->getNumOperands() == 0) {
12871286 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
6363
6464 // Recursively descend the def-use lists from V to find non-bitcast users of
6565 // bitcasts of V.
66 static void FindUses(Value *V, Function &F,
66 static void findUses(Value *V, Function &F,
6767 SmallVectorImpl> &Uses,
6868 SmallPtrSetImpl &ConstantBCs) {
6969 for (Use &U : V->uses()) {
70 if (BitCastOperator *BC = dyn_cast(U.getUser()))
71 FindUses(BC, F, Uses, ConstantBCs);
70 if (auto *BC = dyn_cast(U.getUser()))
71 findUses(BC, F, Uses, ConstantBCs);
7272 else if (U.get()->getType() != F.getType()) {
7373 CallSite CS(U.getUser());
7474 if (!CS)
8080 continue;
8181 if (isa(U.get())) {
8282 // Only add constant bitcasts to the list once; they get RAUW'd
83 auto c = ConstantBCs.insert(cast(U.get()));
84 if (!c.second)
83 auto C = ConstantBCs.insert(cast(U.get()));
84 if (!C.second)
8585 continue;
8686 }
8787 Uses.push_back(std::make_pair(&U, &F));
112112 // For bitcasts that involve struct types we don't know at this stage if they
113113 // would be equivalent at the wasm level and so we can't know if we need to
114114 // generate a wrapper.
115 static Function *CreateWrapper(Function *F, FunctionType *Ty) {
115 static Function *createWrapper(Function *F, FunctionType *Ty) {
116116 Module *M = F->getParent();
117117
118118 Function *Wrapper = Function::Create(Ty, Function::PrivateLinkage,
150150 BB->getInstList().push_back(PtrCast);
151151 Args.push_back(PtrCast);
152152 } else if (ArgType->isStructTy() || ParamType->isStructTy()) {
153 LLVM_DEBUG(dbgs() << "CreateWrapper: struct param type in bitcast: "
153 LLVM_DEBUG(dbgs() << "createWrapper: struct param type in bitcast: "
154154 << F->getName() << "\n");
155155 WrapperNeeded = false;
156156 } else {
157 LLVM_DEBUG(dbgs() << "CreateWrapper: arg type mismatch calling: "
157 LLVM_DEBUG(dbgs() << "createWrapper: arg type mismatch calling: "
158158 << F->getName() << "\n");
159159 LLVM_DEBUG(dbgs() << "Arg[" << Args.size() << "] Expected: "
160160 << *ParamType << " Got: " << *ArgType << "\n");
190190 BB->getInstList().push_back(Cast);
191191 ReturnInst::Create(M->getContext(), Cast, BB);
192192 } else if (RtnType->isStructTy() || ExpectedRtnType->isStructTy()) {
193 LLVM_DEBUG(dbgs() << "CreateWrapper: struct return type in bitcast: "
193 LLVM_DEBUG(dbgs() << "createWrapper: struct return type in bitcast: "
194194 << F->getName() << "\n");
195195 WrapperNeeded = false;
196196 } else {
197 LLVM_DEBUG(dbgs() << "CreateWrapper: return type mismatch calling: "
197 LLVM_DEBUG(dbgs() << "createWrapper: return type mismatch calling: "
198198 << F->getName() << "\n");
199199 LLVM_DEBUG(dbgs() << "Expected: " << *ExpectedRtnType
200200 << " Got: " << *RtnType << "\n");
211211 new UnreachableInst(M->getContext(), BB);
212212 Wrapper->setName(F->getName() + "_bitcast_invalid");
213213 } else if (!WrapperNeeded) {
214 LLVM_DEBUG(dbgs() << "CreateWrapper: no wrapper needed: " << F->getName()
214 LLVM_DEBUG(dbgs() << "createWrapper: no wrapper needed: " << F->getName()
215215 << "\n");
216216 Wrapper->eraseFromParent();
217217 return nullptr;
218218 }
219 LLVM_DEBUG(dbgs() << "CreateWrapper: " << F->getName() << "\n");
219 LLVM_DEBUG(dbgs() << "createWrapper: " << F->getName() << "\n");
220220 return Wrapper;
221221 }
222222
223223 // Test whether a main function with type FuncTy should be rewritten to have
224224 // type MainTy.
225 bool ShouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) {
225 bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) {
226226 // Only fix the main function if it's the standard zero-arg form. That way,
227227 // the standard cases will work as expected, and users will see signature
228228 // mismatches from the linker for non-standard cases.
241241
242242 // Collect all the places that need wrappers.
243243 for (Function &F : M) {
244 FindUses(&F, F, Uses, ConstantBCs);
244 findUses(&F, F, Uses, ConstantBCs);
245245
246246 // If we have a "main" function, and its type isn't
247247 // "int main(int argc, char *argv[])", create an artificial call with it
254254 PointerType::get(Type::getInt8PtrTy(C), 0)};
255255 FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
256256 /*isVarArg=*/false);
257 if (ShouldFixMainFunction(F.getFunctionType(), MainTy)) {
257 if (shouldFixMainFunction(F.getFunctionType(), MainTy)) {
258258 LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: "
259259 << *F.getFunctionType() << "\n");
260260 Value *Args[] = {UndefValue::get(MainArgTys[0]),
273273 for (auto &UseFunc : Uses) {
274274 Use *U = UseFunc.first;
275275 Function *F = UseFunc.second;
276 PointerType *PTy = cast(U->get()->getType());
277 FunctionType *Ty = dyn_cast(PTy->getElementType());
276 auto *PTy = cast(U->get()->getType());
277 auto *Ty = dyn_cast(PTy->getElementType());
278278
279279 // If the function is casted to something like i8* as a "generic pointer"
280280 // to be later casted to something else, we can't generate a wrapper for it.
284284
285285 auto Pair = Wrappers.insert(std::make_pair(std::make_pair(F, Ty), nullptr));
286286 if (Pair.second)
287 Pair.first->second = CreateWrapper(F, Ty);
287 Pair.first->second = createWrapper(F, Ty);
288288
289289 Function *Wrapper = Pair.first->second;
290290 if (!Wrapper)
300300 // one that gets called from startup.
301301 if (CallMain) {
302302 Main->setName("__original_main");
303 Function *MainWrapper =
303 auto *MainWrapper =
304304 cast(CallMain->getCalledValue()->stripPointerCasts());
305305 delete CallMain;
306306 if (Main->isDeclaration()) {
3636 bool ForCodeSize;
3737
3838 public:
39 WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &tm,
39 WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &TM,
4040 CodeGenOpt::Level OptLevel)
41 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr), ForCodeSize(false) {
41 : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr), ForCodeSize(false) {
4242 }
4343
4444 StringRef getPassName() const override {
318318 auto &Context = BB->getParent()->getFunction().getContext();
319319 Type *Ty = Float64 ? Type::getDoubleTy(Context) : Type::getFloatTy(Context);
320320
321 const BasicBlock *LLVM_BB = BB->getBasicBlock();
321 const BasicBlock *LLVMBB = BB->getBasicBlock();
322322 MachineFunction *F = BB->getParent();
323 MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVM_BB);
324 MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
325 MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVM_BB);
323 MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
324 MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
325 MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);
326326
327327 MachineFunction::iterator It = ++BB->getIterator();
328328 F->insert(It, FalseMBB);
572572 // Lowering Code
573573 //===----------------------------------------------------------------------===//
574574
575 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg) {
575 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
576576 MachineFunction &MF = DAG.getMachineFunction();
577577 DAG.getContext()->diagnose(
578 DiagnosticInfoUnsupported(MF.getFunction(), msg, DL.getDebugLoc()));
578 DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc()));
579579 }
580580
581581 // Test whether the given calling convention is supported.
582 static bool CallingConvSupported(CallingConv::ID CallConv) {
582 static bool callingConvSupported(CallingConv::ID CallConv) {
583583 // We currently support the language-independent target-independent
584584 // conventions. We don't yet have a way to annotate calls with properties like
585585 // "cold", and we don't have any call-clobbered registers, so these are mostly
602602 auto Layout = MF.getDataLayout();
603603
604604 CallingConv::ID CallConv = CLI.CallConv;
605 if (!CallingConvSupported(CallConv))
605 if (!callingConvSupported(CallConv))
606606 fail(DL, DAG,
607607 "WebAssembly doesn't support language-specific or target-specific "
608608 "calling conventions yet");
624624 SmallVectorImpl &Outs = CLI.Outs;
625625 SmallVectorImpl &OutVals = CLI.OutVals;
626626 unsigned NumFixedArgs = 0;
627 for (unsigned i = 0; i < Outs.size(); ++i) {
628 const ISD::OutputArg &Out = Outs[i];
629 SDValue &OutVal = OutVals[i];
627 for (unsigned I = 0; I < Outs.size(); ++I) {
628 const ISD::OutputArg &Out = Outs[I];
629 SDValue &OutVal = OutVals[I];
630630 if (Out.Flags.isNest())
631631 fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
632632 if (Out.Flags.isInAlloca())
762762 const SmallVectorImpl &OutVals, const SDLoc &DL,
763763 SelectionDAG &DAG) const {
764764 assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
765 if (!CallingConvSupported(CallConv))
765 if (!callingConvSupported(CallConv))
766766 fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
767767
768768 SmallVector RetOps(1, Chain);
789789 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
790790 const SmallVectorImpl &Ins, const SDLoc &DL,
791791 SelectionDAG &DAG, SmallVectorImpl &InVals) const {
792 if (!CallingConvSupported(CallConv))
792 if (!callingConvSupported(CallConv))
793793 fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
794794
795795 MachineFunction &MF = DAG.getMachineFunction();
836836 // Record the number and types of arguments and results.
837837 SmallVector Params;
838838 SmallVector Results;
839 ComputeSignatureVTs(MF.getFunction().getFunctionType(), MF.getFunction(),
839 computeSignatureVTs(MF.getFunction().getFunctionType(), MF.getFunction(),
840840 DAG.getTarget(), Params, Results);
841841 for (MVT VT : Results)
842842 MFI->addResult(VT);
10531053
10541054 switch (IntNo) {
10551055 default:
1056 return {}; // Don't custom lower most intrinsics.
1056 return SDValue(); // Don't custom lower most intrinsics.
10571057
10581058 case Intrinsic::wasm_lsda: {
10591059 EVT VT = Op.getValueType();
12221222 Ops[OpIdx++] = Op.getOperand(1);
12231223
12241224 // Expand mask indices to byte indices and materialize them as operands
1225 for (size_t I = 0, Lanes = Mask.size(); I < Lanes; ++I) {
1225 for (int M : Mask) {
12261226 for (size_t J = 0; J < LaneBytes; ++J) {
12271227 // Lower undefs (represented by -1 in mask) to zero
1228 uint64_t ByteIndex =
1229 Mask[I] == -1 ? 0 : (uint64_t)Mask[I] * LaneBytes + J;
1228 uint64_t ByteIndex = M == -1 ? 0 : (uint64_t)M * LaneBytes + J;
12301229 Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
12311230 }
12321231 }
12461245 return SDValue();
12471246 }
12481247
1249 static SDValue UnrollVectorShift(SDValue Op, SelectionDAG &DAG) {
1248 static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG) {
12501249 EVT LaneT = Op.getSimpleValueType().getVectorElementType();
12511250 // 32-bit and 64-bit unrolled shifts will have proper semantics
12521251 if (LaneT.bitsGE(MVT::i32))
12811280 // Expand all vector shifts until V8 fixes its implementation
12821281 // TODO: remove this once V8 is fixed
12831282 if (!Subtarget->hasUnimplementedSIMD128())
1284 return UnrollVectorShift(Op, DAG);
1283 return unrollVectorShift(Op, DAG);
12851284
12861285 // Unroll non-splat vector shifts
12871286 BuildVectorSDNode *ShiftVec;
12881287 SDValue SplatVal;
12891288 if (!(ShiftVec = dyn_cast(Op.getOperand(1).getNode())) ||
12901289 !(SplatVal = ShiftVec->getSplatValue()))
1291 return UnrollVectorShift(Op, DAG);
1290 return unrollVectorShift(Op, DAG);
12921291
12931292 // All splats except i64x2 const splats are handled by patterns
1294 ConstantSDNode *SplatConst = dyn_cast(SplatVal);
1293 auto *SplatConst = dyn_cast(SplatVal);
12951294 if (!SplatConst || Op.getSimpleValueType() != MVT::v2i64)
12961295 return Op;
12971296
238238 bool EnableEH; // Enable exception handling
239239 bool EnableSjLj; // Enable setjmp/longjmp handling
240240
241 GlobalVariable *ThrewGV;
242 GlobalVariable *ThrewValueGV;
243 Function *GetTempRet0Func;
244 Function *SetTempRet0Func;
245 Function *ResumeF;
246 Function *EHTypeIDF;
247 Function *EmLongjmpF;
248 Function *EmLongjmpJmpbufF;
249 Function *SaveSetjmpF;
250 Function *TestSetjmpF;
241 GlobalVariable *ThrewGV = nullptr;
242 GlobalVariable *ThrewValueGV = nullptr;
243 Function *GetTempRet0Func = nullptr;
244 Function *SetTempRet0Func = nullptr;
245 Function *ResumeF = nullptr;
246 Function *EHTypeIDF = nullptr;
247 Function *EmLongjmpF = nullptr;
248 Function *EmLongjmpJmpbufF = nullptr;
249 Function *SaveSetjmpF = nullptr;
250 Function *TestSetjmpF = nullptr;
251251
252252 // __cxa_find_matching_catch_N functions.
253253 // Indexed by the number of clauses in an original landingpad instruction.
280280 static char ID;
281281
282282 WebAssemblyLowerEmscriptenEHSjLj(bool EnableEH = true, bool EnableSjLj = true)
283 : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj),
284 ThrewGV(nullptr), ThrewValueGV(nullptr), GetTempRet0Func(nullptr),
285 SetTempRet0Func(nullptr), ResumeF(nullptr), EHTypeIDF(nullptr),
286 EmLongjmpF(nullptr), EmLongjmpJmpbufF(nullptr), SaveSetjmpF(nullptr),
287 TestSetjmpF(nullptr) {
283 : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj) {
288284 EHWhitelistSet.insert(EHWhitelist.begin(), EHWhitelist.end());
289285 }
290286 bool runOnModule(Module &M) override;
431427 // No attributes for the callee pointer.
432428 ArgAttributes.push_back(AttributeSet());
433429 // Copy the argument attributes from the original
434 for (unsigned i = 0, e = CI->getNumArgOperands(); i < e; ++i)
435 ArgAttributes.push_back(InvokeAL.getParamAttributes(i));
430 for (unsigned I = 0, E = CI->getNumArgOperands(); I < E; ++I)
431 ArgAttributes.push_back(InvokeAL.getParamAttributes(I));
436432
437433 // Reconstruct the AttributesList based on the vector we constructed.
438434 AttributeList NewCallAL =
605601 ++UI;
606602 SSA.Initialize(I.getType(), I.getName());
607603 SSA.AddAvailableValue(&BB, &I);
608 Instruction *User = cast(U.getUser());
604 auto *User = cast(U.getUser());
609605 if (User->getParent() == &BB)
610606 continue;
611607
612 if (PHINode *UserPN = dyn_cast(User))
608 if (auto *UserPN = dyn_cast(User))
613609 if (UserPN->getIncomingBlock(U) == &BB)
614610 continue;
615611
836832 for (LandingPadInst *LPI : LandingPads) {
837833 IRB.SetInsertPoint(LPI);
838834 SmallVector FMCArgs;
839 for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) {
840 Constant *Clause = LPI->getClause(i);
835 for (unsigned I = 0, E = LPI->getNumClauses(); I < E; ++I) {
836 Constant *Clause = LPI->getClause(I);
841837 // As a temporary workaround for the lack of aggregate varargs support
842838 // in the interface between JS and wasm, break out filter operands into
843839 // their component elements.
844 if (LPI->isFilter(i)) {
840 if (LPI->isFilter(I)) {
845841 auto *ATy = cast(Clause->getType());
846 for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) {
847 Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter");
842 for (unsigned J = 0, E = ATy->getNumElements(); J < E; ++J) {
843 Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(J), "filter");
848844 FMCArgs.push_back(EV);
849845 }
850846 } else
954950 BBs.push_back(&BB);
955951
956952 // BBs.size() will change within the loop, so we query it every time
957 for (unsigned i = 0; i < BBs.size(); i++) {
958 BasicBlock *BB = BBs[i];
953 for (unsigned I = 0; I < BBs.size(); I++) {
954 BasicBlock *BB = BBs[I];
959955 for (Instruction &I : *BB) {
960956 assert(!isa(&I));
961957 auto *CI = dyn_cast(&I);
10281024 // switch case). 0 means a longjmp that is not ours to handle, needs a
10291025 // rethrow. Otherwise the index is the same as the index in P+1 (to avoid
10301026 // 0).
1031 for (unsigned i = 0; i < SetjmpRetPHIs.size(); i++) {
1032 SI->addCase(IRB.getInt32(i + 1), SetjmpRetPHIs[i]->getParent());
1033 SetjmpRetPHIs[i]->addIncoming(LongjmpResult, EndBB);
1027 for (unsigned I = 0; I < SetjmpRetPHIs.size(); I++) {
1028 SI->addCase(IRB.getInt32(I + 1), SetjmpRetPHIs[I]->getParent());
1029 SetjmpRetPHIs[I]->addIncoming(LongjmpResult, EndBB);
10341030 }
10351031
10361032 // We are splitting the block here, and must continue to find other calls
10771073 Use &U = *UI;
10781074 // Increment the iterator before removing the use from the list.
10791075 ++UI;
1080 if (Instruction *I = dyn_cast(U.getUser()))
1076 if (auto *I = dyn_cast(U.getUser()))
10811077 if (I->getParent() != &EntryBB)
10821078 SetjmpTableSSA.RewriteUse(U);
10831079 }
10851081 UI != UE;) {
10861082 Use &U = *UI;
10871083 ++UI;
1088 if (Instruction *I = dyn_cast(U.getUser()))
1084 if (auto *I = dyn_cast(U.getUser()))
10891085 if (I->getParent() != &EntryBB)
10901086 SetjmpTableSizeSSA.RewriteUse(U);
10911087 }
6868 return false;
6969
7070 // Sanity-check @llvm.global_dtor's type.
71 StructType *ETy = dyn_cast(InitList->getType()->getElementType());
71 auto *ETy = dyn_cast(InitList->getType()->getElementType());
7272 if (!ETy || ETy->getNumElements() != 3 ||
7373 !ETy->getTypeAtIndex(0U)->isIntegerTy() ||
7474 !ETy->getTypeAtIndex(1U)->isPointerTy() ||
7979 // associated symbol.
8080 std::map>> DtorFuncs;
8181 for (Value *O : InitList->operands()) {
82 ConstantStruct *CS = dyn_cast(O);
82 auto *CS = dyn_cast(O);
8383 if (!CS)
8484 continue; // Malformed.
8585
86 ConstantInt *Priority = dyn_cast(CS->getOperand(0));
86 auto *Priority = dyn_cast(CS->getOperand(0));
8787 if (!Priority)
8888 continue; // Malformed.
8989 uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX);
4646 MCSymbol *
4747 WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
4848 const GlobalValue *Global = MO.getGlobal();
49 MCSymbolWasm *WasmSym = cast(Printer.getSymbol(Global));
49 auto *WasmSym = cast(Printer.getSymbol(Global));
5050
5151 if (const auto *FuncTy = dyn_cast(Global->getValueType())) {
5252 const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
5555
5656 SmallVector ResultMVTs;
5757 SmallVector ParamMVTs;
58 ComputeSignatureVTs(FuncTy, CurrentFunc, TM, ParamMVTs, ResultMVTs);
59
60 auto Signature = SignatureFromMVTs(ResultMVTs, ParamMVTs);
58 computeSignatureVTs(FuncTy, CurrentFunc, TM, ParamMVTs, ResultMVTs);
59
60 auto Signature = signatureFromMVTs(ResultMVTs, ParamMVTs);
6161 WasmSym->setSignature(Signature.get());
6262 Printer.addSignature(std::move(Signature));
6363 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
6969 MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
7070 const MachineOperand &MO) const {
7171 const char *Name = MO.getSymbolName();
72 MCSymbolWasm *WasmSym =
73 cast(Printer.GetExternalSymbolSymbol(Name));
72 auto *WasmSym = cast(Printer.GetExternalSymbolSymbol(Name));
7473 const WebAssemblySubtarget &Subtarget = Printer.getSubtarget();
7574
7675 // Except for the two exceptions (__stack_pointer and __cpp_exception), all
108107 : wasm::ValType::I32);
109108 } else { // Function symbols
110109 WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
111 GetLibcallSignature(Subtarget, Name, Returns, Params);
110 getLibcallSignature(Subtarget, Name, Returns, Params);
112111 }
113112 auto Signature =
114113 make_unique(std::move(Returns), std::move(Params));
118117 return WasmSym;
119118 }
120119
121 MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
120 MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(MCSymbol *Sym,
122121 int64_t Offset,
123122 bool IsFunc, bool IsGlob,
124123 bool IsEvent) const {
159158 llvm_unreachable("Unexpected register class");
160159 }
161160
162 void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
161 void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
163162 MCInst &OutMI) const {
164163 OutMI.setOpcode(MI->getOpcode());
165164
166165 const MCInstrDesc &Desc = MI->getDesc();
167 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
168 const MachineOperand &MO = MI->getOperand(i);
166 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
167 const MachineOperand &MO = MI->getOperand(I);
169168
170169 MCOperand MCOp;
171170 switch (MO.getType()) {
186185 break;
187186 }
188187 case MachineOperand::MO_Immediate:
189 if (i < Desc.NumOperands) {
190 const MCOperandInfo &Info = Desc.OpInfo[i];
188 if (I < Desc.NumOperands) {
189 const MCOperandInfo &Info = Desc.OpInfo[I];
191190 if (Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
192191 MCSymbol *Sym = Printer.createTempSymbol("typeindex");
193192
207206 if (WebAssembly::isCallIndirect(*MI))
208207 Params.pop_back();
209208
210 MCSymbolWasm *WasmSym = cast(Sym);
209 auto *WasmSym = cast(Sym);
211210 auto Signature = make_unique(std::move(Returns),
212211 std::move(Params));
213212 WasmSym->setSignature(Signature.get());
237236 case MachineOperand::MO_GlobalAddress:
238237 assert(MO.getTargetFlags() == WebAssemblyII::MO_NO_FLAG &&
239238 "WebAssembly does not use target flags on GlobalAddresses");
240 MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
239 MCOp = lowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
241240 MO.getGlobal()->getValueType()->isFunctionTy(),
242241 false, false);
243242 break;
246245 // variable or a function.
247246 assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 &&
248247 "WebAssembly uses only symbol flags on ExternalSymbols");
249 MCOp = LowerSymbolOperand(
248 MCOp = lowerSymbolOperand(
250249 GetExternalSymbolSymbol(MO), /*Offset=*/0,
251250 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_FUNCTION) != 0,
252251 (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0,
257256 // because global addresses or other external symbols are handled above.
258257 assert(MO.getTargetFlags() == 0 &&
259258 "WebAssembly does not use target flags on MCSymbol");
260 MCOp = LowerSymbolOperand(MO.getMCSymbol(), /*Offset=*/0, false, false,
259 MCOp = lowerSymbolOperand(MO.getMCSymbol(), /*Offset=*/0, false, false,
261260 false);
262261 break;
263262 }
3131
3232 MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
3333 MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
34 MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
34 MCOperand lowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
3535 bool IsGlob, bool IsEvent) const;
3636
3737 public:
3838 WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)
3939 : Ctx(ctx), Printer(printer) {}
40 void Lower(const MachineInstr *MI, MCInst &OutMI) const;
40 void lower(const MachineInstr *MI, MCInst &OutMI) const;
4141 };
4242 } // end namespace llvm
4343
1717 #include "llvm/CodeGen/Analysis.h"
1818 using namespace llvm;
1919
20 WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() {}
20 WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
2121
2222 void WebAssemblyFunctionInfo::initWARegs() {
2323 assert(WARegs.empty());
2525 WARegs.resize(MF.getRegInfo().getNumVirtRegs(), Reg);
2626 }
2727
28 void llvm::ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
28 void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
2929 Type *Ty, SmallVectorImpl &ValueVTs) {
3030 const DataLayout &DL(F.getParent()->getDataLayout());
3131 const WebAssemblyTargetLowering &TLI =
3636 for (EVT VT : VTs) {
3737 unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
3838 MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
39 for (unsigned i = 0; i != NumRegs; ++i)
39 for (unsigned I = 0; I != NumRegs; ++I)
4040 ValueVTs.push_back(RegisterVT);
4141 }
4242 }
4343
44 void llvm::ComputeSignatureVTs(const FunctionType *Ty, const Function &F,
44 void llvm::computeSignatureVTs(const FunctionType *Ty, const Function &F,
4545 const TargetMachine &TM,
4646 SmallVectorImpl &Params,
4747 SmallVectorImpl &Results) {
48 ComputeLegalValueVTs(F, TM, Ty->getReturnType(), Results);
48 computeLegalValueVTs(F, TM, Ty->getReturnType(), Results);
4949
5050 MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
5151 if (Results.size() > 1) {
5757 }
5858
5959 for (auto *Param : Ty->params())
60 ComputeLegalValueVTs(F, TM, Param, Params);
60 computeLegalValueVTs(F, TM, Param, Params);
6161 if (Ty->isVarArg())
6262 Params.push_back(PtrVT);
6363 }
6464
65 void llvm::ValTypesFromMVTs(const ArrayRef &In,
65 void llvm::valTypesFromMVTs(const ArrayRef &In,
6666 SmallVectorImpl &Out) {
6767 for (MVT Ty : In)
6868 Out.push_back(WebAssembly::toValType(Ty));
6969 }
7070
7171 std::unique_ptr
72 llvm::SignatureFromMVTs(const SmallVectorImpl &Results,
72 llvm::signatureFromMVTs(const SmallVectorImpl &Results,
7373 const SmallVectorImpl &Params) {
7474 auto Sig = make_unique();
75 ValTypesFromMVTs(Results, Sig->Returns);
76 ValTypesFromMVTs(Params, Sig->Params);
75 valTypesFromMVTs(Results, Sig->Returns);
76 valTypesFromMVTs(Params, Sig->Params);
7777 return Sig;
7878 }
118118 }
119119 };
120120
121 void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
121 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
122122 SmallVectorImpl &ValueVTs);
123123
124124 // Compute the signature for a given FunctionType (Ty). Note that it's not the
125125 // signature for F (F is just used to get varous context)
126 void ComputeSignatureVTs(const FunctionType *Ty, const Function &F,
126 void computeSignatureVTs(const FunctionType *Ty, const Function &F,
127127 const TargetMachine &TM, SmallVectorImpl &Params,
128128 SmallVectorImpl &Results);
129129
130 void ValTypesFromMVTs(const ArrayRef &In,
130 void valTypesFromMVTs(const ArrayRef &In,
131131 SmallVectorImpl &Out);
132132
133133 std::unique_ptr
134 SignatureFromMVTs(const SmallVectorImpl &Results,
134 signatureFromMVTs(const SmallVectorImpl &Results,
135135 const SmallVectorImpl &Params);
136136
137137 } // end namespace llvm
8080 }
8181
8282 // Replace uses of FromReg with ToReg if they are dominated by MI.
83 static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
83 static bool replaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
8484 unsigned FromReg, unsigned ToReg,
8585 const MachineRegisterInfo &MRI,
8686 MachineDominatorTree &MDT,
155155 return false;
156156
157157 StringRef Name(Op1.getSymbolName());
158 bool callReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
158 bool CallReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
159159 Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
160160 Name == TLI.getLibcallName(RTLIB::MEMSET);
161 if (!callReturnsInput)
161 if (!CallReturnsInput)
162162 return false;
163163
164164 LibFunc Func;
170170 if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
171171 report_fatal_error("Memory Intrinsic results: call to builtin function "
172172 "with wrong signature, from/to mismatch");
173 return ReplaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
173 return replaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
174174 }
175175
176176 bool WebAssemblyMemIntrinsicResults::runOnMachineFunction(MachineFunction &MF) {
180180 });
181181
182182 MachineRegisterInfo &MRI = MF.getRegInfo();
183 MachineDominatorTree &MDT = getAnalysis();
183 auto &MDT = getAnalysis();
184184 const WebAssemblyTargetLowering &TLI =
185185 *MF.getSubtarget().getTargetLowering();
186186 const auto &LibInfo = getAnalysis().getTLI();
187 LiveIntervals &LIS = getAnalysis();
187 auto &LIS = getAnalysis();
188188 bool Changed = false;
189189
190190 // We don't preserve SSA form.
7070 << MF.getName() << '\n');
7171
7272 MachineRegisterInfo &MRI = MF.getRegInfo();
73 LiveIntervals &LIS = getAnalysis();
73 auto &LIS = getAnalysis();
7474
7575 // We don't preserve SSA form.
7676 MRI.leaveSSA();
7979
8080 // Split multiple-VN LiveIntervals into multiple LiveIntervals.
8181 SmallVector SplitLIs;
82 for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
83 unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
82 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
83 unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
8484 if (MRI.reg_nodbg_empty(Reg))
8585 continue;
8686
3535
3636 bool runOnFunction(Function &F) override;
3737
38 DominatorTree *DT;
38 DominatorTree *DT = nullptr;
3939
4040 public:
4141 static char ID;
42 OptimizeReturned() : FunctionPass(ID), DT(nullptr) {}
42 OptimizeReturned() : FunctionPass(ID) {}
4343
4444 void visitCallSite(CallSite CS);
4545 };
5555 }
5656
5757 void OptimizeReturned::visitCallSite(CallSite CS) {
58 for (unsigned i = 0, e = CS.getNumArgOperands(); i < e; ++i)
59 if (CS.paramHasAttr(i, Attribute::Returned)) {
58 for (unsigned I = 0, E = CS.getNumArgOperands(); I < E; ++I)
59 if (CS.paramHasAttr(I, Attribute::Returned)) {
6060 Instruction *Inst = CS.getInstruction();
61 Value *Arg = CS.getArgOperand(i);
61 Value *Arg = CS.getArgOperand(I);
6262 // Ignore constants, globals, undef, etc.
6363 if (isa(Arg))
6464 continue;
5656 }
5757
5858 /// If desirable, rewrite NewReg to a drop register.
59 static bool MaybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
59 static bool maybeRewriteToDrop(unsigned OldReg, unsigned NewReg,
6060 MachineOperand &MO, WebAssemblyFunctionInfo &MFI,
6161 MachineRegisterInfo &MRI) {
6262 bool Changed = false;
7070 return Changed;
7171 }
7272
73 static bool MaybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB,
73 static bool maybeRewriteToFallthrough(MachineInstr &MI, MachineBasicBlock &MBB,
7474 const MachineFunction &MF,
7575 WebAssemblyFunctionInfo &MFI,
7676 MachineRegisterInfo &MRI,
148148 if (MRI.getRegClass(NewReg) != MRI.getRegClass(OldReg))
149149 report_fatal_error("Peephole: call to builtin function with "
150150 "wrong signature, from/to mismatch");
151 Changed |= MaybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
151 Changed |= maybeRewriteToDrop(OldReg, NewReg, MO, MFI, MRI);
152152 }
153153 }
154154 }
156156 }
157157 // Optimize away an explicit void return at the end of the function.
158158 case WebAssembly::RETURN_I32:
159 Changed |= MaybeRewriteToFallthrough(
159 Changed |= maybeRewriteToFallthrough(
160160 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I32,
161161 WebAssembly::COPY_I32);
162162 break;
163163 case WebAssembly::RETURN_I64:
164 Changed |= MaybeRewriteToFallthrough(
164 Changed |= maybeRewriteToFallthrough(
165165 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_I64,
166166 WebAssembly::COPY_I64);
167167 break;
168168 case WebAssembly::RETURN_F32:
169 Changed |= MaybeRewriteToFallthrough(
169 Changed |= maybeRewriteToFallthrough(
170170 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F32,
171171 WebAssembly::COPY_F32);
172172 break;
173173 case WebAssembly::RETURN_F64:
174 Changed |= MaybeRewriteToFallthrough(
174 Changed |= maybeRewriteToFallthrough(
175175 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_F64,
176176 WebAssembly::COPY_F64);
177177 break;
178178 case WebAssembly::RETURN_v16i8:
179 Changed |= MaybeRewriteToFallthrough(
179 Changed |= maybeRewriteToFallthrough(
180180 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v16i8,
181181 WebAssembly::COPY_V128);
182182 break;
183183 case WebAssembly::RETURN_v8i16:
184 Changed |= MaybeRewriteToFallthrough(
184 Changed |= maybeRewriteToFallthrough(
185185 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v8i16,
186186 WebAssembly::COPY_V128);
187187 break;
188188 case WebAssembly::RETURN_v4i32:
189 Changed |= MaybeRewriteToFallthrough(
189 Changed |= maybeRewriteToFallthrough(
190190 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4i32,
191191 WebAssembly::COPY_V128);
192192 break;
193193 case WebAssembly::RETURN_v2i64:
194 Changed |= MaybeRewriteToFallthrough(
194 Changed |= maybeRewriteToFallthrough(
195195 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2i64,
196196 WebAssembly::COPY_V128);
197197 break;
198198 case WebAssembly::RETURN_v4f32:
199 Changed |= MaybeRewriteToFallthrough(
199 Changed |= maybeRewriteToFallthrough(
200200 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4f32,
201201 WebAssembly::COPY_V128);
202202 break;
203203 case WebAssembly::RETURN_v2f64:
204 Changed |= MaybeRewriteToFallthrough(
204 Changed |= maybeRewriteToFallthrough(
205205 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2f64,
206206 WebAssembly::COPY_V128);
207207 break;
208208 case WebAssembly::RETURN_VOID:
209 Changed |= MaybeRewriteToFallthrough(
209 Changed |= maybeRewriteToFallthrough(
210210 MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_VOID,
211211 WebAssembly::INSTRUCTION_LIST_END);
212212 break;
6161 }
6262
6363 // Test whether the given register has an ARGUMENT def.
64 static bool HasArgumentDef(unsigned Reg, const MachineRegisterInfo &MRI) {
64 static bool hasArgumentDef(unsigned Reg, const MachineRegisterInfo &MRI) {
6565 for (const auto &Def : MRI.def_instructions(Reg))
6666 if (WebAssembly::isArgument(Def))
6767 return true;
9393 //
9494 // TODO: This is fairly heavy-handed; find a better approach.
9595 //
96 for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
97 unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
96 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
97 unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
9898
9999 // Skip unused registers.
100100 if (MRI.use_nodbg_empty(Reg))
101101 continue;
102102
103103 // Skip registers that have an ARGUMENT definition.
104 if (HasArgumentDef(Reg, MRI))
104 if (hasArgumentDef(Reg, MRI))
105105 continue;
106106
107107 BuildMI(Entry, Entry.begin(), DebugLoc(),
6464 static float computeWeight(const MachineRegisterInfo *MRI,
6565 const MachineBlockFrequencyInfo *MBFI,
6666 unsigned VReg) {
67 float weight = 0.0f;
67 float Weight = 0.0f;
6868 for (MachineOperand &MO : MRI->reg_nodbg_operands(VReg))
69 weight += LiveIntervals::getSpillWeight(MO.isDef(), MO.isUse(), MBFI,
69 Weight += LiveIntervals::getSpillWeight(MO.isDef(), MO.isUse(), MBFI,
7070 *MO.getParent());
71 return weight;
71 return Weight;
7272 }
7373
7474 bool WebAssemblyRegColoring::runOnMachineFunction(MachineFunction &MF) {
9696 SortedIntervals.reserve(NumVRegs);
9797
9898 LLVM_DEBUG(dbgs() << "Interesting register intervals:\n");
99 for (unsigned i = 0; i < NumVRegs; ++i) {
100 unsigned VReg = TargetRegisterInfo::index2VirtReg(i);
99 for (unsigned I = 0; I < NumVRegs; ++I) {
100 unsigned VReg = TargetRegisterInfo::index2VirtReg(I);
101101 if (MFI.isVRegStackified(VReg))
102102 continue;
103103 // Skip unused registers, which can use $drop.
132132 SortedIntervals.size());
133133 BitVector UsedColors(SortedIntervals.size());
134134 bool Changed = false;
135 for (size_t i = 0, e = SortedIntervals.size(); i < e; ++i) {
136 LiveInterval *LI = SortedIntervals[i];
135 for (size_t I = 0, E = SortedIntervals.size(); I < E; ++I) {
136 LiveInterval *LI = SortedIntervals[I];
137137 unsigned Old = LI->reg;
138 size_t Color = i;
138 size_t Color = I;
139139 const TargetRegisterClass *RC = MRI->getRegClass(Old);
140140
141141 // Check if it's possible to reuse any of the used colors.
152152 }
153153
154154 unsigned New = SortedIntervals[Color]->reg;
155 SlotMapping[i] = New;
155 SlotMapping[I] = New;
156156 Changed |= Old != New;
157157 UsedColors.set(Color);
158158 Assignments[Color].push_back(LI);
164164 return false;
165165
166166 // Rewrite register operands.
167 for (size_t i = 0, e = SortedIntervals.size(); i < e; ++i) {
168 unsigned Old = SortedIntervals[i]->reg;
169 unsigned New = SlotMapping[i];
167 for (size_t I = 0, E = SortedIntervals.size(); I < E; ++I) {
168 unsigned Old = SortedIntervals[I]->reg;
169 unsigned New = SlotMapping[I];
170170 if (Old != New)
171171 MRI->replaceRegWith(Old, New);
172172 }
7878 // Decorate the given instruction with implicit operands that enforce the
7979 // expression stack ordering constraints for an instruction which is on
8080 // the expression stack.
81 static void ImposeStackOrdering(MachineInstr *MI) {
81 static void imposeStackOrdering(MachineInstr *MI) {
8282 // Write the opaque VALUE_STACK register.
8383 if (!MI->definesRegister(WebAssembly::VALUE_STACK))
8484 MI->addOperand(MachineOperand::CreateReg(WebAssembly::VALUE_STACK,
9494
9595 // Convert an IMPLICIT_DEF instruction into an instruction which defines
9696 // a constant zero value.
97 static void ConvertImplicitDefToConstZero(MachineInstr *MI,
97 static void convertImplicitDefToConstZero(MachineInstr *MI,
9898 MachineRegisterInfo &MRI,
9999 const TargetInstrInfo *TII,
100100 MachineFunction &MF,
110110 MI->addOperand(MachineOperand::CreateImm(0));
111111 } else if (RegClass == &WebAssembly::F32RegClass) {
112112 MI->setDesc(TII->get(WebAssembly::CONST_F32));
113 ConstantFP *Val = cast(Constant::getNullValue(
113 auto *Val = cast(Constant::getNullValue(
114114 Type::getFloatTy(MF.getFunction().getContext())));
115115 MI->addOperand(MachineOperand::CreateFPImm(Val));
116116 } else if (RegClass == &WebAssembly::F64RegClass) {
117117 MI->setDesc(TII->get(WebAssembly::CONST_F64));
118 ConstantFP *Val = cast(Constant::getNullValue(
118 auto *Val = cast(Constant::getNullValue(
119119 Type::getDoubleTy(MF.getFunction().getContext())));
120120 MI->addOperand(MachineOperand::CreateFPImm(Val));
121121 } else if (RegClass == &WebAssembly::V128RegClass) {
134134 // Determine whether a call to the callee referenced by
135135 // MI->getOperand(CalleeOpNo) reads memory, writes memory, and/or has side
136136 // effects.
137 static void QueryCallee(const MachineInstr &MI, unsigned CalleeOpNo, bool &Read,
137 static void queryCallee(const MachineInstr &MI, unsigned CalleeOpNo, bool &Read,
138138 bool &Write, bool &Effects, bool &StackPointer) {
139139 // All calls can use the stack pointer.
140140 StackPointer = true;
142142 const MachineOperand &MO = MI.getOperand(CalleeOpNo);
143143 if (MO.isGlobal()) {
144144 const Constant *GV = MO.getGlobal();
145 if (const GlobalAlias *GA = dyn_cast(GV))
145 if (const auto *GA = dyn_cast(GV))
146146 if (!GA->isInterposable())
147147 GV = GA->getAliasee();
148148
149 if (const Function *F = dyn_cast(GV)) {
149 if (const auto *F = dyn_cast(GV)) {
150150 if (!F->doesNotThrow())
151151 Effects = true;
152152 if (F->doesNotAccessMemory())
166166
167167 // Determine whether MI reads memory, writes memory, has side effects,
168168 // and/or uses the stack pointer value.
169 static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
169 static void query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
170170 bool &Write, bool &Effects, bool &StackPointer) {
171171 assert(!MI.isTerminator());
172172
252252 // Analyze calls.
253253 if (MI.isCall()) {
254254 unsigned CalleeOpNo = WebAssembly::getCalleeOpNo(MI);
255 QueryCallee(MI, CalleeOpNo, Read, Write, Effects, StackPointer);
255 queryCallee(MI, CalleeOpNo, Read, Write, Effects, StackPointer);
256256 }
257257 }
258258
259259 // Test whether Def is safe and profitable to rematerialize.
260 static bool ShouldRematerialize(const MachineInstr &Def, AliasAnalysis &AA,
260 static bool shouldRematerialize(const MachineInstr &Def, AliasAnalysis &AA,
261261 const WebAssemblyInstrInfo *TII) {
262262 return Def.isAsCheapAsAMove() && TII->isTriviallyReMaterializable(Def, &AA);
263263 }
265265 // Identify the definition for this register at this point. This is a
266266 // generalization of MachineRegisterInfo::getUniqueVRegDef that uses
267267 // LiveIntervals to handle complex cases.
268 static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert,
268 static MachineInstr *getVRegDef(unsigned Reg, const MachineInstr *Insert,
269269 const MachineRegisterInfo &MRI,
270270 const LiveIntervals &LIS) {
271271 // Most registers are in SSA form here so we try a quick MRI query first.
283283 // Test whether Reg, as defined at Def, has exactly one use. This is a
284284 // generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals
285285 // to handle complex cases.
286 static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
286 static bool hasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
287287 MachineDominatorTree &MDT, LiveIntervals &LIS) {
288288 // Most registers are in SSA form here so we try a quick MRI query first.
289289 if (MRI.hasOneUse(Reg))
312312 // walking the block.
313313 // TODO: Compute memory dependencies in a way that uses AliasAnalysis to be
314314 // more precise.
315 static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
315 static bool isSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
316316 AliasAnalysis &AA, const MachineRegisterInfo &MRI) {
317317 assert(Def->getParent() == Insert->getParent());
318318
360360 }
361361
362362 bool Read = false, Write = false, Effects = false, StackPointer = false;
363 Query(*Def, AA, Read, Write, Effects, StackPointer);
363 query(*Def, AA, Read, Write, Effects, StackPointer);
364364
365365 // If the instruction does not access memory and has no side effects, it has
366366 // no additional dependencies.
375375 bool InterveningWrite = false;
376376 bool InterveningEffects = false;
377377 bool InterveningStackPointer = false;
378 Query(*I, AA, InterveningRead, InterveningWrite, InterveningEffects,
378 query(*I, AA, InterveningRead, InterveningWrite, InterveningEffects,
379379 InterveningStackPointer);
380380 if (Effects && InterveningEffects)
381381 return false;
396396 }
397397
398398 /// Test whether OneUse, a use of Reg, dominates all of Reg's other uses.
399 static bool OneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse,
399 static bool oneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse,
400400 const MachineBasicBlock &MBB,
401401 const MachineRegisterInfo &MRI,
402402 const MachineDominatorTree &MDT,
455455 }
456456
457457 /// Get the appropriate tee opcode for the given register class.
458 static unsigned GetTeeOpcode(const TargetRegisterClass *RC) {
458 static unsigned getTeeOpcode(const TargetRegisterClass *RC) {
459459 if (RC == &WebAssembly::I32RegClass)
460460 return WebAssembly::TEE_I32;
461461 if (RC == &WebAssembly::I64RegClass)
470470 }
471471
472472 // Shrink LI to its uses, cleaning up LI.
473 static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
473 static void shrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
474474 if (LIS.shrinkToUses(&LI)) {
475475 SmallVector SplitLIs;
476476 LIS.splitSeparateComponents(LI, SplitLIs);
479479
480480 /// A single-use def in the same block with no intervening memory or register
481481 /// dependencies; move the def down and nest it with the current instruction.
482 static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand &Op,
482 static MachineInstr *moveForSingleUse(unsigned Reg, MachineOperand &Op,
483483 MachineInstr *Def, MachineBasicBlock &MBB,
484484 MachineInstr *Insert, LiveIntervals &LIS,
485485 WebAssemblyFunctionInfo &MFI,
518518 LLVM_DEBUG(dbgs() << " - Replaced register: "; Def->dump());
519519 }
520520
521 ImposeStackOrdering(Def);
521 imposeStackOrdering(Def);
522522 return Def;
523523 }
524524
525525 /// A trivially cloneable instruction; clone it and nest the new copy with the
526526 /// current instruction.
527 static MachineInstr *RematerializeCheapDef(
527 static MachineInstr *rematerializeCheapDef(
528528 unsigned Reg, MachineOperand &Op, MachineInstr &Def, MachineBasicBlock &MBB,
529529 MachineBasicBlock::instr_iterator Insert, LiveIntervals &LIS,
530530 WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI,
541541 LIS.InsertMachineInstrInMaps(*Clone);
542542 LIS.createAndComputeVirtRegInterval(NewReg);
543543 MFI.stackifyVReg(NewReg);
544 ImposeStackOrdering(Clone);
544 imposeStackOrdering(Clone);
545545
546546 LLVM_DEBUG(dbgs() << " - Cloned to "; Clone->dump());
547547
549549 bool IsDead = MRI.use_empty(Reg);
550550 if (!IsDead) {
551551 LiveInterval &LI = LIS.getInterval(Reg);
552 ShrinkToUses(LI, LIS);
552 shrinkToUses(LI, LIS);
553553 IsDead = !LI.liveAt(LIS.getInstructionIndex(Def).getDeadSlot());
554554 }
555555
592592 ///
593593 /// with DefReg and TeeReg stackified. This eliminates a local.get from the
594594 /// resulting code.
595 static MachineInstr *MoveAndTeeForMultiUse(
595 static MachineInstr *moveAndTeeForMultiUse(
596596 unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB,
597597 MachineInstr *Insert, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI,
598598 MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII) {
610610 unsigned DefReg = MRI.createVirtualRegister(RegClass);
611611 MachineOperand &DefMO = Def->getOperand(0);
612612 MachineInstr *Tee = BuildMI(MBB, Insert, Insert->getDebugLoc(),
613 TII->get(GetTeeOpcode(RegClass)), TeeReg)
613 TII->get(getTeeOpcode(RegClass)), TeeReg)
614614 .addReg(Reg, RegState::Define)
615615 .addReg(DefReg, getUndefRegState(DefMO.isDead()));
616616 Op.setReg(TeeReg);
626626 VNInfo *ValNo = LI.getVNInfoAt(DefIdx);
627627 I->start = TeeIdx;
628628 ValNo->def = TeeIdx;
629 ShrinkToUses(LI, LIS);
629 shrinkToUses(LI, LIS);
630630
631631 // Finish stackifying the new regs.
632632 LIS.createAndComputeVirtRegInterval(TeeReg);
633633 LIS.createAndComputeVirtRegInterval(DefReg);
634634 MFI.stackifyVReg(DefReg);
635635 MFI.stackifyVReg(TeeReg);
636 ImposeStackOrdering(Def);
637 ImposeStackOrdering(Tee);
636 imposeStackOrdering(Def);
637 imposeStackOrdering(Tee);
638638
639639 DefDIs.clone(Tee, DefReg);
640640 DefDIs.clone(Insert, TeeReg);
648648 /// A stack for walking the tree of instructions being built, visiting the
649649 /// MachineOperands in DFS order.
650650 class TreeWalkerState {
651 typedef MachineInstr::mop_iterator mop_iterator;
652 typedef std::reverse_iterator mop_reverse_iterator;
653 typedef iterator_range RangeTy;
651 using mop_iterator = MachineInstr::mop_iterator;
652 using mop_reverse_iterator = std::reverse_iterator;
653 using RangeTy = iterator_range;
654654 SmallVector Worklist;
655655
656656 public:
660660 Worklist.push_back(reverse(Range));
661661 }
662662
663 bool Done() const { return Worklist.empty(); }
664
665 MachineOperand &Pop() {
663 bool done() const { return Worklist.empty(); }
664
665 MachineOperand &pop() {
666666 RangeTy &Range = Worklist.back();
667667 MachineOperand &Op = *Range.begin();
668668 Range = drop_begin(Range, 1);
675675 }
676676
677677 /// Push Instr's operands onto the stack to be visited.
678 void PushOperands(MachineInstr *Instr) {
678 void pushOperands(MachineInstr *Instr) {
679679 const iterator_range &Range(Instr->explicit_uses());
680680 if (Range.begin() != Range.end())
681681 Worklist.push_back(reverse(Range));
683683
684684 /// Some of Instr's operands are on the top of the stack; remove them and
685685 /// re-insert them starting from the beginning (because we've commuted them).
686 void ResetTopOperands(MachineInstr *Instr) {
687 assert(HasRemainingOperands(Instr) &&
686 void resetTopOperands(MachineInstr *Instr) {
687 assert(hasRemainingOperands(Instr) &&
688688 "Reseting operands should only be done when the instruction has "
689689 "an operand still on the stack");
690690 Worklist.back() = reverse(Instr->explicit_uses());
692692
693693 /// Test whether Instr has operands remaining to be visited at the top of
694694 /// the stack.
695 bool HasRemainingOperands(const MachineInstr *Instr) const {
695 bool hasRemainingOperands(const MachineInstr *Instr) const {
696696 if (Worklist.empty())
697697 return false;
698698 const RangeTy &Range = Worklist.back();
705705 ///
706706 /// This is needed as a consequence of using implicit local.gets for
707707 /// uses and implicit local.sets for defs.
708 bool IsOnStack(unsigned Reg) const {
708 bool isOnStack(unsigned Reg) const {
709709 for (const RangeTy &Range : Worklist)
710710 for (const MachineOperand &MO : Range)
711711 if (MO.isReg() && MO.getReg() == Reg)
722722 /// state where we've commuted the operands of the current instruction and are
723723 /// revisiting it, and the declined state where we've reverted the operands
724724 /// back to their original order and will no longer commute it further.
725 bool TentativelyCommuting;
726 bool Declined;
725 bool TentativelyCommuting = false;
726 bool Declined = false;
727727
728728 /// During the tentative state, these hold the operand indices of the commuted
729729 /// operands.
730730 unsigned Operand0, Operand1;
731731
732732 public:
733 CommutingState() : TentativelyCommuting(false), Declined(false) {}
734
735733 /// Stackification for an operand was not successful due to ordering
736734 /// constraints. If possible, and if we haven't already tried it and declined
737735 /// it, commute Insert's operands and prepare to revisit it.
738 void MaybeCommute(MachineInstr *Insert, TreeWalkerState &TreeWalker,
736 void maybeCommute(MachineInstr *Insert, TreeWalkerState &TreeWalker,
739737 const WebAssemblyInstrInfo *TII) {
740738 if (TentativelyCommuting) {
741739 assert(!Declined &&
744742 TII->commuteInstruction(*Insert, /*NewMI=*/false, Operand0, Operand1);
745743 TentativelyCommuting = false;
746744 Declined = true;
747 } else if (!Declined && TreeWalker.HasRemainingOperands(Insert)) {
745 } else if (!Declined && TreeWalker.hasRemainingOperands(Insert)) {
748746 Operand0 = TargetInstrInfo::CommuteAnyOperandIndex;
749747 Operand1 = TargetInstrInfo::CommuteAnyOperandIndex;
750748 if (TII->findCommutedOpIndices(*Insert, Operand0, Operand1)) {
751749 // Tentatively commute the operands and try again.
752750 TII->commuteInstruction(*Insert, /*NewMI=*/false, Operand0, Operand1);
753 TreeWalker.ResetTopOperands(Insert);
751 TreeWalker.resetTopOperands(Insert);
754752 TentativelyCommuting = true;
755753 Declined = false;
756754 }
759757
760758 /// Stackification for some operand was successful. Reset to the default
761759 /// state.
762 void Reset() {
760 void reset() {
763761 TentativelyCommuting = false;
764762 Declined = false;
765763 }
777775 const auto *TII = MF.getSubtarget().getInstrInfo();
778776 const auto *TRI = MF.getSubtarget().getRegisterInfo();
779777 AliasAnalysis &AA = getAnalysis().getAAResults();
780 MachineDominatorTree &MDT = getAnalysis();
781 LiveIntervals &LIS = getAnalysis>();
778 auto &MDT = getAnalysis>();
779 auto &LIS = getAnalysis();
782780
783781 // Walk the instructions from the bottom up. Currently we don't look past
784782 // block boundaries, and the blocks aren't ordered so the block visitation
801799 // operands off the stack in LIFO order.
802800 CommutingState Commuting;
803801 TreeWalkerState TreeWalker(Insert);
804 while (!TreeWalker.Done()) {
805 MachineOperand &Op = TreeWalker.Pop();
802 while (!TreeWalker.done()) {
803 MachineOperand &Op = TreeWalker.pop();
806804
807805 // We're only interested in explicit virtual register operands.
808806 if (!Op.isReg())
816814 continue;
817815
818816 // Identify the definition for this register at this point.
819 MachineInstr *Def = GetVRegDef(Reg, Insert, MRI, LIS);
817 MachineInstr *Def = getVRegDef(Reg, Insert, MRI, LIS);
820818 if (!Def)
821819 continue;
822820
855853 // supports intra-block moves) and it's MachineSink's job to catch all
856854 // the sinking opportunities anyway.
857855 bool SameBlock = Def->getParent() == &MBB;
858 bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, MRI) &&
859 !TreeWalker.IsOnStack(Reg);
860 if (CanMove && HasOneUse(Reg, Def, MRI, MDT, LIS)) {
861 Insert = MoveForSingleUse(Reg, Op, Def, MBB, Insert, LIS, MFI, MRI);
862 } else if (ShouldRematerialize(*Def, AA, TII)) {
856 bool CanMove = SameBlock && isSafeToMove(Def, Insert, AA, MRI) &&
857 !TreeWalker.isOnStack(Reg);
858 if (CanMove && hasOneUse(Reg, Def, MRI, MDT, LIS)) {
859 Insert = moveForSingleUse(Reg, Op, Def, MBB, Insert, LIS, MFI, MRI);
860 } else if (shouldRematerialize(*Def, AA, TII)) {
863861 Insert =
864 RematerializeCheapDef(Reg, Op, *Def, MBB, Insert->getIterator(),
862 rematerializeCheapDef(Reg, Op, *Def, MBB, Insert->getIterator(),
865863 LIS, MFI, MRI, TII, TRI);
866864 } else if (CanMove &&
867 OneUseDominatesOtherUses(Reg, Op, MBB, MRI, MDT, LIS, MFI)) {
868 Insert = MoveAndTeeForMultiUse(Reg, Op, Def, MBB, Insert, LIS, MFI,
865 oneUseDominatesOtherUses(Reg, Op, MBB, MRI, MDT, LIS, MFI)) {
866 Insert = moveAndTeeForMultiUse(Reg, Op, Def, MBB, Insert, LIS, MFI,
869867 MRI, TII);
870868 } else {
871869 // We failed to stackify the operand. If the problem was ordering
872870 // constraints, Commuting may be able to help.
873871 if (!CanMove && SameBlock)
874 Commuting.MaybeCommute(Insert, TreeWalker, TII);
872 Commuting.maybeCommute(Insert, TreeWalker, TII);
875873 // Proceed to the next operand.
876874 continue;
877875 }
880878 // to a constant 0 so that the def is explicit, and the push/pop
881879 // correspondence is maintained.
882880 if (Insert->getOpcode() == TargetOpcode::IMPLICIT_DEF)
883 ConvertImplicitDefToConstZero(Insert, MRI, TII, MF, LIS);
881 convertImplicitDefToConstZero(Insert, MRI, TII, MF, LIS);
884882
885883 // We stackified an operand. Add the defining instruction's operands to
886884 // the worklist stack now to continue to build an ever deeper tree.
887 Commuting.Reset();
888 TreeWalker.PushOperands(Insert);
885 Commuting.reset();
886 TreeWalker.pushOperands(Insert);
889887 }
890888
891889 // If we stackified any operands, skip over the tree to start looking for
892890 // the next instruction we can build a tree on.
893891 if (Insert != &*MII) {
894 ImposeStackOrdering(&*MII);
892 imposeStackOrdering(&*MII);
895893 MII = MachineBasicBlock::iterator(Insert).getReverse();
896894 Changed = true;
897895 }
483483
484484 } // end anonymous namespace
485485
486 void llvm::GetLibcallSignature(const WebAssemblySubtarget &Subtarget,
486 void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget,
487487 RTLIB::Libcall LC,
488488 SmallVectorImpl &Rets,
489489 SmallVectorImpl &Params) {
490490 assert(Rets.empty());
491491 assert(Params.empty());
492492
493 wasm::ValType iPTR =
493 wasm::ValType PtrTy =
494494 Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
495495
496496 auto &Table = RuntimeLibcallSignatures->Table;
598598 break;
599599 case func_f32_iPTR_iPTR:
600600 Params.push_back(wasm::ValType::F32);
601 Params.push_back(iPTR);
602 Params.push_back(iPTR);
601 Params.push_back(PtrTy);
602 Params.push_back(PtrTy);
603603 break;
604604 case func_f64_iPTR_iPTR:
605605 Params.push_back(wasm::ValType::F64);
606 Params.push_back(iPTR);
607 Params.push_back(iPTR);
606 Params.push_back(PtrTy);
607 Params.push_back(PtrTy);
608608 break;
609609 case i16_func_i16_i16:
610610 Rets.push_back(wasm::ValType::I32);
630630 Rets.push_back(wasm::ValType::I32);
631631 Params.push_back(wasm::ValType::I32);
632632 Params.push_back(wasm::ValType::I32);
633 Params.push_back(iPTR);
633 Params.push_back(PtrTy);
634634 break;
635635 case i64_func_i64_i64:
636636 Rets.push_back(wasm::ValType::I64);
641641 Rets.push_back(wasm::ValType::I64);
642642 Params.push_back(wasm::ValType::I64);
643643 Params.push_back(wasm::ValType::I64);
644 Params.push_back(iPTR);
644 Params.push_back(PtrTy);
645645 break;
646646 case i64_i64_func_f32:
647647 #if 0 // TODO: Enable this when wasm gets multiple-return-value support.
648648 Rets.push_back(wasm::ValType::I64);
649649 Rets.push_back(wasm::ValType::I64);
650650 #else
651 Params.push_back(iPTR);
651 Params.push_back(PtrTy);
652652 #endif
653653 Params.push_back(wasm::ValType::F32);
654654 break;
657657 Rets.push_back(wasm::ValType::I64);
658658 Rets.push_back(wasm::ValType::I64);
659659 #else
660 Params.push_back(iPTR);
660 Params.push_back(PtrTy);
661661 #endif
662662 Params.push_back(wasm::ValType::F64);
663663 break;
666666 Rets.push_back(wasm::ValType::I32);
667667 Rets.push_back(wasm::ValType::I32);
668668 #else
669 Params.push_back(iPTR);
669 Params.push_back(PtrTy);
670670 #endif
671671 Params.push_back(wasm::ValType::I32);
672672 Params.push_back(wasm::ValType::I32);
676676 Rets.push_back(wasm::ValType::I32);
677677 Rets.push_back(wasm::ValType::I32);
678678 #else
679 Params.push_back(iPTR);
679 Params.push_back(PtrTy);
680680 #endif
681681 Params.push_back(wasm::ValType::I32);
682682 Params.push_back(wasm::ValType::I32);
686686 Rets.push_back(wasm::ValType::I64);
687687 Rets.push_back(wasm::ValType::I64);
688688 #else
689 Params.push_back(iPTR);
689 Params.push_back(PtrTy);
690690 #endif
691691 Params.push_back(wasm::ValType::I64);
692692 Params.push_back(wasm::ValType::I64);
696696 Rets.push_back(wasm::ValType::I64);
697697 Rets.push_back(wasm::ValType::I64);
698698 #else
699 Params.push_back(iPTR);
699 Params.push_back(PtrTy);
700700 #endif
701701 Params.push_back(wasm::ValType::I64);
702702 Params.push_back(wasm::ValType::I64);
708708 Rets.push_back(wasm::ValType::I64);
709709 Rets.push_back(wasm::ValType::I64);
710710 #else
711 Params.push_back(iPTR);
711 Params.push_back(PtrTy);
712712 #endif
713713 Params.push_back(wasm::ValType::I64);
714714 Params.push_back(wasm::ValType::I64);
715715 Params.push_back(wasm::ValType::I64);
716716 Params.push_back(wasm::ValType::I64);
717 Params.push_back(iPTR);
717 Params.push_back(PtrTy);
718718 break;
719719 case i64_i64_i64_i64_func_i64_i64_i64_i64:
720720 #if 0 // TODO: Enable this when wasm gets multiple-return-value support.
723723 Rets.push_back(wasm::ValType::I64);
724724 Rets.push_back(wasm::ValType::I64);
725725 #else
726 Params.push_back(iPTR);
726 Params.push_back(PtrTy);
727727 #endif
728728 Params.push_back(wasm::ValType::I64);
729729 Params.push_back(wasm::ValType::I64);
737737 Rets.push_back(wasm::ValType::I64);
738738 Rets.push_back(wasm::ValType::I64);
739739 #else
740 Params.push_back(iPTR);
740 Params.push_back(PtrTy);
741741 #endif
742742 Params.push_back(wasm::ValType::I64);
743743 Params.push_back(wasm::ValType::I64);
744744 Params.push_back(wasm::ValType::I32);
745745 break;
746746 case iPTR_func_iPTR_i32_iPTR:
747 Rets.push_back(iPTR);
748 Params.push_back(iPTR);
749 Params.push_back(wasm::ValType::I32);
750 Params.push_back(iPTR);
747 Rets.push_back(PtrTy);
748 Params.push_back(PtrTy);
749 Params.push_back(wasm::ValType::I32);
750 Params.push_back(PtrTy);
751751 break;
752752 case iPTR_func_iPTR_iPTR_iPTR:
753 Rets.push_back(iPTR);
754 Params.push_back(iPTR);
755 Params.push_back(iPTR);
756 Params.push_back(iPTR);
753 Rets.push_back(PtrTy);
754 Params.push_back(PtrTy);
755 Params.push_back(PtrTy);
756 Params.push_back(PtrTy);
757757 break;
758758 case f32_func_f32_f32_f32:
759759 Rets.push_back(wasm::ValType::F32);
770770 case func_i64_i64_iPTR_iPTR:
771771 Params.push_back(wasm::ValType::I64);
772772 Params.push_back(wasm::ValType::I64);
773 Params.push_back(iPTR);
774 Params.push_back(iPTR);
773 Params.push_back(PtrTy);
774 Params.push_back(PtrTy);
775775 break;
776776 case func_iPTR_f32:
777 Params.push_back(iPTR);
777 Params.push_back(PtrTy);
778778 Params.push_back(wasm::ValType::F32);
779779 break;
780780 case func_iPTR_f64:
781 Params.push_back(iPTR);
781 Params.push_back(PtrTy);
782782 Params.push_back(wasm::ValType::F64);
783783 break;
784784 case func_iPTR_i32:
785 Params.push_back(iPTR);
785 Params.push_back(PtrTy);
786786 Params.push_back(wasm::ValType::I32);
787787 break;
788788 case func_iPTR_i64:
789 Params.push_back(iPTR);
789 Params.push_back(PtrTy);
790790 Params.push_back(wasm::ValType::I64);
791791 break;
792792 case func_iPTR_i64_i64:
793 Params.push_back(iPTR);
793 Params.push_back(PtrTy);
794794 Params.push_back(wasm::ValType::I64);
795795 Params.push_back(wasm::ValType::I64);
796796 break;
797797 case func_iPTR_i64_i64_i64_i64:
798 Params.push_back(iPTR);
798 Params.push_back(PtrTy);
799799 Params.push_back(wasm::ValType::I64);
800800 Params.push_back(wasm::ValType::I64);
801801 Params.push_back(wasm::ValType::I64);
802802 Params.push_back(wasm::ValType::I64);
803803 break;
804804 case func_iPTR_i64_i64_i64_i64_i64_i64:
805 Params.push_back(iPTR);
805 Params.push_back(PtrTy);
806806 Params.push_back(wasm::ValType::I64);
807807 Params.push_back(wasm::ValType::I64);
808808 Params.push_back(wasm::ValType::I64);
830830 static ManagedStatic LibcallNameMap;
831831 // TODO: If the RTLIB::Libcall-taking flavor of GetSignature remains unsed
832832 // other than here, just roll its logic into this version.
833 void llvm::GetLibcallSignature(const WebAssemblySubtarget &Subtarget,
833 void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget,
834834 const char *Name,
835835 SmallVectorImpl &Rets,
836836 SmallVectorImpl &Params) {
837837 auto &Map = LibcallNameMap->Map;
838 auto val = Map.find(Name);
839 assert(val != Map.end() && "unexpected runtime library name");
840 return GetLibcallSignature(Subtarget, val->second, Rets, Params);
838 auto Val = Map.find(Name);
839 assert(Val != Map.end() && "unexpected runtime library name");
840 return getLibcallSignature(Subtarget, Val->second, Rets, Params);
841841 }
2121
2222 class WebAssemblySubtarget;
2323
24 extern void GetLibcallSignature(const WebAssemblySubtarget &Subtarget,
24 extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget,
2525 RTLIB::Libcall LC,
2626 SmallVectorImpl &Rets,
2727 SmallVectorImpl &Params);
2828
29 extern void GetLibcallSignature(const WebAssemblySubtarget &Subtarget,
29 extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget,
3030 const char *Name,
3131 SmallVectorImpl &Rets,
3232 SmallVectorImpl &Params);
1515
1616 #define DEBUG_TYPE "wasm-selectiondag-info"
1717
18 WebAssemblySelectionDAGInfo::~WebAssemblySelectionDAGInfo() {}
18 WebAssemblySelectionDAGInfo::~WebAssemblySelectionDAGInfo() = default; // anchor
5252 return new WebAssemblySetP2AlignOperands();
5353 }
5454
55 static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
55 static void rewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
5656 assert(MI.getOperand(OperandNo).getImm() == 0 &&
5757 "ISel should set p2align operands to 0");
5858 assert(MI.hasOneMemOperand() &&
162162 case WebAssembly::ATOMIC_NOTIFY:
163163 case WebAssembly::ATOMIC_WAIT_I32:
164164 case WebAssembly::ATOMIC_WAIT_I64:
165 RewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo);
165 rewriteP2Align(MI, WebAssembly::LoadP2AlignOperandNo);
166166 break;
167167 case WebAssembly::STORE_I32:
168168 case WebAssembly::STORE_I64:
186186 case WebAssembly::ATOMIC_STORE8_I64:
187187 case WebAssembly::ATOMIC_STORE16_I64:
188188 case WebAssembly::ATOMIC_STORE32_I64:
189 RewriteP2Align(MI, WebAssembly::StoreP2AlignOperandNo);
189 rewriteP2Align(MI, WebAssembly::StoreP2AlignOperandNo);
190190 break;
191191 default:
192192 break;
119119 // splitting and tail merging.
120120 }
121121
122 WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}
122 WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.
123123
124124 const WebAssemblySubtarget *
125125 WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
4949 unsigned Cost = BasicTTIImplBase::getArithmeticInstrCost(
5050 Opcode, Ty, Opd1Info, Opd2Info, Opd1PropInfo, Opd2PropInfo);
5151
52 if (VectorType *VTy = dyn_cast(Ty)) {
52 if (auto *VTy = dyn_cast(Ty)) {
5353 switch (Opcode) {
5454 case Instruction::LShr:
5555 case Instruction::AShr:
1717 using namespace object;
1818
1919 void llvm::printWasmFileHeader(const object::ObjectFile *Obj) {
20 const WasmObjectFile *File = dyn_cast(Obj);
20 const auto *File = dyn_cast(Obj);
2121
2222 outs() << "Program Header:\n";
2323 outs() << "Version: 0x";
218218 std::error_code createWasmDumper(const object::ObjectFile *Obj,
219219 ScopedPrinter &Writer,
220220 std::unique_ptr &Result) {
221 const WasmObjectFile *WasmObj = dyn_cast(Obj);
221 const auto *WasmObj = dyn_cast(Obj);
222222 assert(WasmObj && "createWasmDumper called with non-wasm object");
223223
224224 Result.reset(new WasmDumper(WasmObj, Writer));
+7
-7