[WebAssembly] clang-format (NFC)

Summary: This patch runs clang-format on all wasm-only files.

Reviewers: aardappel, dschuff, sunfish, tlively

Subscribers: MatzeB, sbc100, jgravelle-google, llvm-commits

Differential Revision: https://reviews.llvm.org/D51447

llvm-svn: 341439
This commit is contained in:
Heejin Ahn 2018-09-05 01:27:38 +00:00
parent 5d05be84b7
commit f208f6311b
51 changed files with 818 additions and 722 deletions

View File

@ -104,8 +104,8 @@ struct WasmFunction {
uint32_t Size; uint32_t Size;
uint32_t CodeOffset; // start of Locals and Body uint32_t CodeOffset; // start of Locals and Body
StringRef SymbolName; // from the "linking" section StringRef SymbolName; // from the "linking" section
StringRef DebugName; // from the "name" section StringRef DebugName; // from the "name" section
uint32_t Comdat; // from the "comdat info" section uint32_t Comdat; // from the "comdat info" section
}; };
struct WasmDataSegment { struct WasmDataSegment {
@ -231,21 +231,21 @@ enum class ValType {
// Kind codes used in the custom "name" section // Kind codes used in the custom "name" section
enum : unsigned { enum : unsigned {
WASM_NAMES_FUNCTION = 0x1, WASM_NAMES_FUNCTION = 0x1,
WASM_NAMES_LOCAL = 0x2, WASM_NAMES_LOCAL = 0x2,
}; };
// Kind codes used in the custom "linking" section // Kind codes used in the custom "linking" section
enum : unsigned { enum : unsigned {
WASM_SEGMENT_INFO = 0x5, WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6, WASM_INIT_FUNCS = 0x6,
WASM_COMDAT_INFO = 0x7, WASM_COMDAT_INFO = 0x7,
WASM_SYMBOL_TABLE = 0x8, WASM_SYMBOL_TABLE = 0x8,
}; };
// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
enum : unsigned { enum : unsigned {
WASM_COMDAT_DATA = 0x0, WASM_COMDAT_DATA = 0x0,
WASM_COMDAT_FUNCTION = 0x1, WASM_COMDAT_FUNCTION = 0x1,
}; };
// Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
@ -256,15 +256,15 @@ enum WasmSymbolType : unsigned {
WASM_SYMBOL_TYPE_SECTION = 0x3, WASM_SYMBOL_TYPE_SECTION = 0x3,
}; };
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
const unsigned WASM_SYMBOL_UNDEFINED = 0x10; const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
#define WASM_RELOC(name, value) name = value, #define WASM_RELOC(name, value) name = value,

View File

@ -14,8 +14,8 @@
#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H #ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
#define LLVM_CODEGEN_WASMEHFUNCINFO_H #define LLVM_CODEGEN_WASMEHFUNCINFO_H
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"

View File

@ -19,6 +19,6 @@ class MCAsmInfoWasm : public MCAsmInfo {
protected: protected:
MCAsmInfoWasm(); MCAsmInfoWasm();
}; };
} } // namespace llvm
#endif #endif

View File

@ -35,8 +35,7 @@ public:
// Use a module name of "env" for now, for compatibility with existing tools. // Use a module name of "env" for now, for compatibility with existing tools.
// This is temporary, and may change, as the ABI is not yet stable. // This is temporary, and may change, as the ABI is not yet stable.
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary) MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindWasm, Name, isTemporary), : MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {}
ModuleName("env") {}
static bool classof(const MCSymbol *S) { return S->isWasm(); } static bool classof(const MCSymbol *S) { return S->isWasm(); }
const MCExpr *getSize() const { return SymbolSize; } const MCExpr *getSize() const { return SymbolSize; }
@ -92,6 +91,6 @@ public:
} }
}; };
} // end namespace llvm } // end namespace llvm
#endif // LLVM_MC_MCSYMBOLWASM_H #endif // LLVM_MC_MCSYMBOLWASM_H

View File

@ -51,6 +51,6 @@ std::unique_ptr<MCObjectWriter>
createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
raw_pwrite_stream &OS); raw_pwrite_stream &OS);
} // End llvm namespace } // namespace llvm
#endif #endif

View File

@ -18,8 +18,8 @@
#define LLVM_OBJECT_WASM_H #define LLVM_OBJECT_WASM_H
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Wasm.h" #include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
#include "llvm/Object/Binary.h" #include "llvm/Object/Binary.h"
@ -98,9 +98,9 @@ public:
struct WasmSection { struct WasmSection {
WasmSection() = default; WasmSection() = default;
uint32_t Type = 0; // Section type (See below) uint32_t Type = 0; // Section type (See below)
uint32_t Offset = 0; // Offset with in the file uint32_t Offset = 0; // Offset with in the file
StringRef Name; // Section name (User-defined sections only) StringRef Name; // Section name (User-defined sections only)
ArrayRef<uint8_t> Content; // Section content ArrayRef<uint8_t> Content; // Section content
std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
}; };
@ -119,7 +119,7 @@ public:
const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const; const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const; const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
const WasmSection &getWasmSection(const SectionRef &Section) const; const WasmSection &getWasmSection(const SectionRef &Section) const;
const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const; const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
static bool classof(const Binary *v) { return v->isWasm(); } static bool classof(const Binary *v) { return v->isWasm(); }
@ -131,7 +131,7 @@ public:
ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
ArrayRef<wasm::WasmExport> exports() const { return Exports; } ArrayRef<wasm::WasmExport> exports() const { return Exports; }
ArrayRef<WasmSymbol> syms() const { return Symbols; } ArrayRef<WasmSymbol> syms() const { return Symbols; }
const wasm::WasmLinkingData& linkingData() const { return LinkingData; } const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
uint32_t getNumberOfSymbols() const { return Symbols.size(); } uint32_t getNumberOfSymbols() const { return Symbols.size(); }
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
@ -151,7 +151,7 @@ public:
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const; uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
@ -264,8 +264,7 @@ private:
} // end namespace object } // end namespace object
inline raw_ostream &operator<<(raw_ostream &OS, inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
const object::WasmSymbol &Sym) {
Sym.print(OS); Sym.print(OS);
return OS; return OS;
} }

View File

@ -25,7 +25,9 @@ std::string llvm::wasm::toString(wasm::WasmSymbolType type) {
std::string llvm::wasm::relocTypetoString(uint32_t type) { std::string llvm::wasm::relocTypetoString(uint32_t type) {
switch (type) { switch (type) {
#define WASM_RELOC(NAME, VALUE) case VALUE: return #NAME; #define WASM_RELOC(NAME, VALUE) \
case VALUE: \
return #NAME;
#include "llvm/BinaryFormat/WasmRelocs.def" #include "llvm/BinaryFormat/WasmRelocs.def"
#undef WASM_RELOC #undef WASM_RELOC
default: default:

View File

@ -15,7 +15,7 @@
#include "llvm/MC/MCAsmInfoWasm.h" #include "llvm/MC/MCAsmInfoWasm.h"
using namespace llvm; using namespace llvm;
void MCAsmInfoWasm::anchor() { } void MCAsmInfoWasm::anchor() {}
MCAsmInfoWasm::MCAsmInfoWasm() { MCAsmInfoWasm::MCAsmInfoWasm() {
HasIdentDirective = true; HasIdentDirective = true;

View File

@ -137,11 +137,11 @@ struct WasmComdatEntry {
// Information about a single relocation. // Information about a single relocation.
struct WasmRelocationEntry { struct WasmRelocationEntry {
uint64_t Offset; // Where is the relocation. uint64_t Offset; // Where is the relocation.
const MCSymbolWasm *Symbol; // The symbol to relocate with. const MCSymbolWasm *Symbol; // The symbol to relocate with.
int64_t Addend; // A value to add to the symbol. int64_t Addend; // A value to add to the symbol.
unsigned Type; // The type of the relocation. unsigned Type; // The type of the relocation.
const MCSectionWasm *FixupSection;// The section the relocation is targeting. const MCSectionWasm *FixupSection; // The section the relocation is targeting.
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
int64_t Addend, unsigned Type, int64_t Addend, unsigned Type,
@ -163,8 +163,8 @@ struct WasmRelocationEntry {
} }
void print(raw_ostream &Out) const { void print(raw_ostream &Out) const {
Out << wasm::relocTypetoString(Type) Out << wasm::relocTypetoString(Type) << " Off=" << Offset
<< " Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend << ", Sym=" << *Symbol << ", Addend=" << Addend
<< ", FixupSection=" << FixupSection->getSectionName(); << ", FixupSection=" << FixupSection->getSectionName();
} }
@ -291,9 +291,7 @@ private:
W.OS << Str; W.OS << Str;
} }
void writeValueType(wasm::ValType Ty) { void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
W.OS << static_cast<char>(Ty);
}
void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes); void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize, void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
@ -306,7 +304,7 @@ private:
ArrayRef<WasmFunction> Functions); ArrayRef<WasmFunction> Functions);
void writeDataSection(); void writeDataSection();
void writeRelocSection(uint32_t SectionIndex, StringRef Name, void writeRelocSection(uint32_t SectionIndex, StringRef Name,
std::vector<WasmRelocationEntry>& Relocations); std::vector<WasmRelocationEntry> &Relocations);
void writeLinkingMetaDataSection( void writeLinkingMetaDataSection(
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
@ -529,8 +527,8 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
// to allow patching. // to allow patching.
static void static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { uint64_t Offset) {
uint8_t Buffer[5]; uint8_t Buffer[5];
unsigned SizeLen = encodeULEB128(X, Buffer, 5); unsigned SizeLen = encodeULEB128(X, Buffer, 5);
assert(SizeLen == 5); assert(SizeLen == 5);
@ -539,8 +537,8 @@ WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
// Write X as an signed LEB value at offset Offset in Stream, padded // Write X as an signed LEB value at offset Offset in Stream, padded
// to allow patching. // to allow patching.
static void static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) { uint64_t Offset) {
uint8_t Buffer[5]; uint8_t Buffer[5];
unsigned SizeLen = encodeSLEB128(X, Buffer, 5); unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
assert(SizeLen == 5); assert(SizeLen == 5);
@ -554,7 +552,7 @@ static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
} }
static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) { static const MCSymbolWasm *ResolveSymbol(const MCSymbolWasm &Symbol) {
if (Symbol.isVariable()) { if (Symbol.isVariable()) {
const MCExpr *Expr = Symbol.getVariableValue(); const MCExpr *Expr = Symbol.getVariableValue();
auto *Inner = cast<MCSymbolRefExpr>(Expr); auto *Inner = cast<MCSymbolRefExpr>(Expr);
@ -626,10 +624,9 @@ static void addData(SmallVectorImpl<char> &DataBytes,
report_fatal_error("only byte values supported for alignment"); report_fatal_error("only byte values supported for alignment");
// If nops are requested, use zeros, as this is the data section. // If nops are requested, use zeros, as this is the data section.
uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(), uint64_t Size =
Align->getAlignment()), std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
DataBytes.size() + DataBytes.size() + Align->getMaxBytesToEmit());
Align->getMaxBytesToEmit());
DataBytes.resize(Size, Value); DataBytes.resize(Size, Value);
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
int64_t NumValues; int64_t NumValues;
@ -745,12 +742,12 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
W.OS << char(Import.Global.Mutable ? 1 : 0); W.OS << char(Import.Global.Mutable ? 1 : 0);
break; break;
case wasm::WASM_EXTERNAL_MEMORY: case wasm::WASM_EXTERNAL_MEMORY:
encodeULEB128(0, W.OS); // flags encodeULEB128(0, W.OS); // flags
encodeULEB128(NumPages, W.OS); // initial encodeULEB128(NumPages, W.OS); // initial
break; break;
case wasm::WASM_EXTERNAL_TABLE: case wasm::WASM_EXTERNAL_TABLE:
W.OS << char(Import.Table.ElemType); W.OS << char(Import.Table.ElemType);
encodeULEB128(0, W.OS); // flags encodeULEB128(0, W.OS); // flags
encodeULEB128(NumElements, W.OS); // initial encodeULEB128(NumElements, W.OS); // initial
break; break;
default: default:
@ -892,7 +889,7 @@ void WasmObjectWriter::writeDataSection() {
void WasmObjectWriter::writeRelocSection( void WasmObjectWriter::writeRelocSection(
uint32_t SectionIndex, StringRef Name, uint32_t SectionIndex, StringRef Name,
std::vector<WasmRelocationEntry>& Relocs) { std::vector<WasmRelocationEntry> &Relocs) {
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
// for descriptions of the reloc sections. // for descriptions of the reloc sections.
@ -916,9 +913,9 @@ void WasmObjectWriter::writeRelocSection(
encodeULEB128(SectionIndex, W.OS); encodeULEB128(SectionIndex, W.OS);
encodeULEB128(Relocs.size(), W.OS); encodeULEB128(Relocs.size(), W.OS);
for (const WasmRelocationEntry& RelEntry : Relocs) { for (const WasmRelocationEntry &RelEntry : Relocs) {
uint64_t Offset = RelEntry.Offset + uint64_t Offset =
RelEntry.FixupSection->getSectionOffset(); RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
uint32_t Index = getRelocationIndexValue(RelEntry); uint32_t Index = getRelocationIndexValue(RelEntry);
W.OS << char(RelEntry.Type); W.OS << char(RelEntry.Type);
@ -996,7 +993,7 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
startSection(SubSection, wasm::WASM_INIT_FUNCS); startSection(SubSection, wasm::WASM_INIT_FUNCS);
encodeULEB128(InitFuncs.size(), W.OS); encodeULEB128(InitFuncs.size(), W.OS);
for (auto &StartFunc : InitFuncs) { for (auto &StartFunc : InitFuncs) {
encodeULEB128(StartFunc.first, W.OS); // priority encodeULEB128(StartFunc.first, W.OS); // priority
encodeULEB128(StartFunc.second, W.OS); // function index encodeULEB128(StartFunc.second, W.OS); // function index
} }
endSection(SubSection); endSection(SubSection);
@ -1041,17 +1038,17 @@ void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
} }
} }
uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) { uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
assert(Symbol.isFunction()); assert(Symbol.isFunction());
assert(TypeIndices.count(&Symbol)); assert(TypeIndices.count(&Symbol));
return TypeIndices[&Symbol]; return TypeIndices[&Symbol];
} }
uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) { uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
assert(Symbol.isFunction()); assert(Symbol.isFunction());
WasmFunctionType F; WasmFunctionType F;
const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol); const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
F.Returns = ResolvedSym->getReturns(); F.Returns = ResolvedSym->getReturns();
F.Params = ResolvedSym->getParams(); F.Params = ResolvedSym->getParams();
@ -1207,7 +1204,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
if (Name.startswith(".custom_section.")) if (Name.startswith(".custom_section."))
Name = Name.substr(strlen(".custom_section.")); Name = Name.substr(strlen(".custom_section."));
MCSymbol* Begin = Sec.getBeginSymbol(); MCSymbol *Begin = Sec.getBeginSymbol();
if (Begin) { if (Begin) {
WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size(); WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
if (SectionName != Begin->getName()) if (SectionName != Begin->getName())
@ -1436,7 +1433,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
unsigned PrefixLength = strlen(".init_array"); unsigned PrefixLength = strlen(".init_array");
if (WS.getSectionName().size() > PrefixLength) { if (WS.getSectionName().size() > PrefixLength) {
if (WS.getSectionName()[PrefixLength] != '.') if (WS.getSectionName()[PrefixLength] != '.')
report_fatal_error(".init_array section priority should start with '.'"); report_fatal_error(
".init_array section priority should start with '.'");
if (WS.getSectionName() if (WS.getSectionName()
.substr(PrefixLength + 1) .substr(PrefixLength + 1)
.getAsInteger(10, Priority)) .getAsInteger(10, Priority))
@ -1444,14 +1442,16 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
} }
const auto &DataFrag = cast<MCDataFragment>(Frag); const auto &DataFrag = cast<MCDataFragment>(Frag);
const SmallVectorImpl<char> &Contents = DataFrag.getContents(); const SmallVectorImpl<char> &Contents = DataFrag.getContents();
for (const uint8_t *p = (const uint8_t *)Contents.data(), for (const uint8_t *
*end = (const uint8_t *)Contents.data() + Contents.size(); p = (const uint8_t *)Contents.data(),
*end = (const uint8_t *)Contents.data() + Contents.size();
p != end; ++p) { p != end; ++p) {
if (*p != 0) if (*p != 0)
report_fatal_error("non-symbolic data in .init_array section"); report_fatal_error("non-symbolic data in .init_array section");
} }
for (const MCFixup &Fixup : DataFrag.getFixups()) { for (const MCFixup &Fixup : DataFrag.getFixups()) {
assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); assert(Fixup.getKind() ==
MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
const MCExpr *Expr = Fixup.getValue(); const MCExpr *Expr = Fixup.getValue();
auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr); auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
if (!Sym) if (!Sym)

View File

@ -37,8 +37,8 @@ using namespace object;
void WasmSymbol::print(raw_ostream &Out) const { void WasmSymbol::print(raw_ostream &Out) const {
Out << "Name=" << Info.Name Out << "Name=" << Info.Name
<< ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
<< ", Flags=" << Info.Flags; << ", Flags=" << Info.Flags;
if (!isTypeData()) { if (!isTypeData()) {
Out << ", ElemIndex=" << Info.ElementIndex; Out << ", ElemIndex=" << Info.ElementIndex;
} else if (isDefined()) { } else if (isDefined()) {
@ -62,9 +62,9 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
return std::move(ObjectFile); return std::move(ObjectFile);
} }
#define VARINT7_MAX ((1<<7)-1) #define VARINT7_MAX ((1 << 7) - 1)
#define VARINT7_MIN (-(1<<7)) #define VARINT7_MIN (-(1 << 7))
#define VARUINT7_MAX (1<<7) #define VARUINT7_MAX (1 << 7)
#define VARUINT1_MAX (1) #define VARUINT1_MAX (1)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
@ -101,7 +101,7 @@ static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
unsigned Count; unsigned Count;
const char* Error = nullptr; const char *Error = nullptr;
uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
if (Error) if (Error)
report_fatal_error(Error); report_fatal_error(Error);
@ -121,7 +121,7 @@ static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
unsigned Count; unsigned Count;
const char* Error = nullptr; const char *Error = nullptr;
uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
if (Error) if (Error)
report_fatal_error(Error); report_fatal_error(Error);
@ -241,8 +241,8 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
ErrorAsOutParameter ErrAsOutParam(&Err); ErrorAsOutParameter ErrAsOutParam(&Err);
Header.Magic = getData().substr(0, 4); Header.Magic = getData().substr(0, 4);
if (Header.Magic != StringRef("\0asm", 4)) { if (Header.Magic != StringRef("\0asm", 4)) {
Err = make_error<StringError>("Bad magic number", Err =
object_error::parse_failed); make_error<StringError>("Bad magic number", object_error::parse_failed);
return; return;
} }
@ -347,8 +347,8 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
break; break;
} }
if (Ctx.Ptr != SubSectionEnd) if (Ctx.Ptr != SubSectionEnd)
return make_error<GenericBinaryError>("Name sub-section ended prematurely", return make_error<GenericBinaryError>(
object_error::parse_failed); "Name sub-section ended prematurely", object_error::parse_failed);
} }
if (Ctx.Ptr != Ctx.End) if (Ctx.Ptr != Ctx.End)
@ -361,7 +361,8 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
HasLinkingSection = true; HasLinkingSection = true;
if (Functions.size() != FunctionTypes.size()) { if (Functions.size() != FunctionTypes.size()) {
return make_error<GenericBinaryError>( return make_error<GenericBinaryError>(
"Linking data must come after code section", object_error::parse_failed); "Linking data must come after code section",
object_error::parse_failed);
} }
LinkingData.Version = readVaruint32(Ctx); LinkingData.Version = readVaruint32(Ctx);
@ -484,9 +485,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
return make_error<GenericBinaryError>("invalid global symbol index", return make_error<GenericBinaryError>("invalid global symbol index",
object_error::parse_failed); object_error::parse_failed);
if (!IsDefined && if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
(Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == wasm::WASM_SYMBOL_BINDING_WEAK)
wasm::WASM_SYMBOL_BINDING_WEAK)
return make_error<GenericBinaryError>("undefined weak global symbol", return make_error<GenericBinaryError>("undefined weak global symbol",
object_error::parse_failed); object_error::parse_failed);
if (IsDefined) { if (IsDefined) {
@ -558,7 +558,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
StringRef Name = readString(Ctx); StringRef Name = readString(Ctx);
if (Name.empty() || !ComdatSet.insert(Name).second) if (Name.empty() || !ComdatSet.insert(Name).second)
return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name), return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
Twine(Name),
object_error::parse_failed); object_error::parse_failed);
LinkingData.Comdats.emplace_back(Name); LinkingData.Comdats.emplace_back(Name);
uint32_t Flags = readVaruint32(Ctx); uint32_t Flags = readVaruint32(Ctx);
@ -576,8 +577,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
object_error::parse_failed); object_error::parse_failed);
case wasm::WASM_COMDAT_DATA: case wasm::WASM_COMDAT_DATA:
if (Index >= DataSegments.size()) if (Index >= DataSegments.size())
return make_error<GenericBinaryError>("COMDAT data index out of range", return make_error<GenericBinaryError>(
object_error::parse_failed); "COMDAT data index out of range", object_error::parse_failed);
if (DataSegments[Index].Data.Comdat != UINT32_MAX) if (DataSegments[Index].Data.Comdat != UINT32_MAX)
return make_error<GenericBinaryError>("Data segment in two COMDATs", return make_error<GenericBinaryError>("Data segment in two COMDATs",
object_error::parse_failed); object_error::parse_failed);
@ -585,8 +586,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
break; break;
case wasm::WASM_COMDAT_FUNCTION: case wasm::WASM_COMDAT_FUNCTION:
if (!isDefinedFunctionIndex(Index)) if (!isDefinedFunctionIndex(Index))
return make_error<GenericBinaryError>("COMDAT function index out of range", return make_error<GenericBinaryError>(
object_error::parse_failed); "COMDAT function index out of range", object_error::parse_failed);
if (getDefinedFunction(Index).Comdat != UINT32_MAX) if (getDefinedFunction(Index).Comdat != UINT32_MAX)
return make_error<GenericBinaryError>("Function in two COMDATs", return make_error<GenericBinaryError>("Function in two COMDATs",
object_error::parse_failed); object_error::parse_failed);
@ -603,7 +604,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (SectionIndex >= Sections.size()) if (SectionIndex >= Sections.size())
return make_error<GenericBinaryError>("Invalid section index", return make_error<GenericBinaryError>("Invalid section index",
object_error::parse_failed); object_error::parse_failed);
WasmSection& Section = Sections[SectionIndex]; WasmSection &Section = Sections[SectionIndex];
uint32_t RelocCount = readVaruint32(Ctx); uint32_t RelocCount = readVaruint32(Ctx);
uint32_t EndOffset = Section.Content.size(); uint32_t EndOffset = Section.Content.size();
uint32_t PreviousOffset = 0; uint32_t PreviousOffset = 0;
@ -756,8 +757,8 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
object_error::parse_failed); object_error::parse_failed);
break; break;
default: default:
return make_error<GenericBinaryError>( return make_error<GenericBinaryError>("Unexpected import kind",
"Unexpected import kind", object_error::parse_failed); object_error::parse_failed);
} }
Imports.push_back(Im); Imports.push_back(Im);
} }
@ -854,8 +855,8 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
case wasm::WASM_EXTERNAL_TABLE: case wasm::WASM_EXTERNAL_TABLE:
break; break;
default: default:
return make_error<GenericBinaryError>( return make_error<GenericBinaryError>("Unexpected export kind",
"Unexpected export kind", object_error::parse_failed); object_error::parse_failed);
} }
Exports.push_back(Ex); Exports.push_back(Ex);
} }
@ -1066,7 +1067,7 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
return getSymbolValue(Symb); return getSymbolValue(Symb);
} }
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const { uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
switch (Sym.Info.Kind) { switch (Sym.Info.Kind) {
case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_FUNCTION:
case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_GLOBAL:
@ -1120,7 +1121,7 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
Expected<section_iterator> Expected<section_iterator>
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
const WasmSymbol& Sym = getWasmSymbol(Symb); const WasmSymbol &Sym = getWasmSymbol(Symb);
if (Sym.isUndefined()) if (Sym.isUndefined())
return section_end(); return section_end();
@ -1234,9 +1235,7 @@ relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
return relocation_iterator(RelocationRef(RelocRef, this)); return relocation_iterator(RelocationRef(RelocRef, this));
} }
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
Rel.d.b++;
}
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
@ -1260,12 +1259,12 @@ uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
void WasmObjectFile::getRelocationTypeName( void WasmObjectFile::getRelocationTypeName(
DataRefImpl Ref, SmallVectorImpl<char> &Result) const { DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
StringRef Res = "Unknown"; StringRef Res = "Unknown";
#define WASM_RELOC(name, value) \ #define WASM_RELOC(name, value) \
case wasm::name: \ case wasm::name: \
Res = #name; \ Res = #name; \
break; break;
switch (Rel.Type) { switch (Rel.Type) {
@ -1299,9 +1298,7 @@ SubtargetFeatures WasmObjectFile::getFeatures() const {
return SubtargetFeatures(); return SubtargetFeatures();
} }
bool WasmObjectFile::isRelocatableObject() const { bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
return HasLinkingSection;
}
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
assert(Ref.d.a < Sections.size()); assert(Ref.d.a < Sections.size());
@ -1321,7 +1318,7 @@ WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
const wasm::WasmRelocation & const wasm::WasmRelocation &
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
assert(Ref.d.a < Sections.size()); assert(Ref.d.a < Sections.size());
const WasmSection& Sec = Sections[Ref.d.a]; const WasmSection &Sec = Sections[Ref.d.a];
assert(Ref.d.b < Sec.Relocations.size()); assert(Ref.d.b < Sec.Relocations.size());
return Sec.Relocations[Ref.d.b]; return Sec.Relocations[Ref.d.b];
} }

View File

@ -309,7 +309,7 @@ void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable); IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
} else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) { } else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
IO.mapRequired("Table", Import.TableImport); IO.mapRequired("Table", Import.TableImport);
} else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY ) { } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY) {
IO.mapRequired("Memory", Import.Memory); IO.mapRequired("Memory", Import.Memory);
} else { } else {
llvm_unreachable("unhandled import type"); llvm_unreachable("unhandled import type");
@ -383,8 +383,8 @@ void MappingTraits<WasmYAML::ComdatEntry>::mapping(
IO.mapRequired("Index", ComdatEntry.Index); IO.mapRequired("Index", ComdatEntry.Index);
} }
void MappingTraits<WasmYAML::Comdat>::mapping( void MappingTraits<WasmYAML::Comdat>::mapping(IO &IO,
IO &IO, WasmYAML::Comdat &Comdat) { WasmYAML::Comdat &Comdat) {
IO.mapRequired("Name", Comdat.Name); IO.mapRequired("Name", Comdat.Name);
IO.mapRequired("Entries", Comdat.Entries); IO.mapRequired("Entries", Comdat.Entries);
} }
@ -420,16 +420,16 @@ void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(
} }
void ScalarBitSetTraits<WasmYAML::SegmentFlags>::bitset( void ScalarBitSetTraits<WasmYAML::SegmentFlags>::bitset(
IO &IO, WasmYAML::SegmentFlags &Value) { IO &IO, WasmYAML::SegmentFlags &Value) {}
}
void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset( void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset(
IO &IO, WasmYAML::SymbolFlags &Value) { IO &IO, WasmYAML::SymbolFlags &Value) {
#define BCaseMask(M, X) IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M) #define BCaseMask(M, X) \
//BCaseMask(BINDING_MASK, BINDING_GLOBAL); IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M)
// BCaseMask(BINDING_MASK, BINDING_GLOBAL);
BCaseMask(BINDING_MASK, BINDING_WEAK); BCaseMask(BINDING_MASK, BINDING_WEAK);
BCaseMask(BINDING_MASK, BINDING_LOCAL); BCaseMask(BINDING_MASK, BINDING_LOCAL);
//BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT); // BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN); BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN);
BCaseMask(UNDEFINED, UNDEFINED); BCaseMask(UNDEFINED, UNDEFINED);
#undef BCaseMask #undef BCaseMask

View File

@ -18,13 +18,13 @@
#include "MCTargetDesc/WebAssemblyTargetStreamer.h" #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
#include "WebAssembly.h" #include "WebAssembly.h"
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetRegistry.h"
@ -65,18 +65,18 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
}; };
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T) WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
: Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {} : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I) WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
: Kind(K), StartLoc(Start), EndLoc(End), Int(I) {} : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F) WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
: Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {} : Kind(K), StartLoc(Start), EndLoc(End), Flt(F) {}
WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, SymOp S) WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, SymOp S)
: Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {} : Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
bool isToken() const override { return Kind == Token; } bool isToken() const override { return Kind == Token; }
bool isImm() const override { return Kind == Integer || bool isImm() const override {
Kind == Float || return Kind == Integer || Kind == Float || Kind == Symbol;
Kind == Symbol; } }
bool isMem() const override { return false; } bool isMem() const override { return false; }
bool isReg() const override { return false; } bool isReg() const override { return false; }
@ -145,8 +145,8 @@ public:
#include "WebAssemblyGenAsmMatcher.inc" #include "WebAssemblyGenAsmMatcher.inc"
// TODO: This is required to be implemented, but appears unused. // TODO: This is required to be implemented, but appears unused.
bool ParseRegister(unsigned &/*RegNo*/, SMLoc &/*StartLoc*/, bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
SMLoc &/*EndLoc*/) override { SMLoc & /*EndLoc*/) override {
llvm_unreachable("ParseRegister is not implemented."); llvm_unreachable("ParseRegister is not implemented.");
} }
@ -156,7 +156,8 @@ public:
bool IsNext(AsmToken::TokenKind Kind) { bool IsNext(AsmToken::TokenKind Kind) {
auto ok = Lexer.is(Kind); auto ok = Lexer.is(Kind);
if (ok) Parser.Lex(); if (ok)
Parser.Lex();
return ok; return ok;
} }
@ -190,15 +191,15 @@ public:
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) { void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
auto &Int = Lexer.getTok(); auto &Int = Lexer.getTok();
int64_t Val = Int.getIntVal(); int64_t Val = Int.getIntVal();
if (IsNegative) Val = -Val; if (IsNegative)
Val = -Val;
Operands.push_back(make_unique<WebAssemblyOperand>( Operands.push_back(make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, Int.getLoc(), WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val})); WebAssemblyOperand::IntOp{Val}));
Parser.Lex(); Parser.Lex();
} }
bool ParseOperandStartingWithInteger(bool IsNegative, bool ParseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands,
OperandVector &Operands,
StringRef InstName) { StringRef InstName) {
ParseSingleInteger(IsNegative, Operands); ParseSingleInteger(IsNegative, Operands);
// FIXME: there is probably a cleaner way to do this. // FIXME: there is probably a cleaner way to do this.
@ -217,25 +218,24 @@ public:
// We can't just call WebAssembly::GetDefaultP2Align since we don't have // We can't just call WebAssembly::GetDefaultP2Align since we don't have
// an opcode until after the assembly matcher. // an opcode until after the assembly matcher.
Operands.push_back(make_unique<WebAssemblyOperand>( Operands.push_back(make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, Offset.getLoc(), WebAssemblyOperand::Integer, Offset.getLoc(), Offset.getEndLoc(),
Offset.getEndLoc(), WebAssemblyOperand::IntOp{0})); WebAssemblyOperand::IntOp{0}));
} }
} }
return false; return false;
} }
bool ParseInstruction(ParseInstructionInfo &/*Info*/, StringRef Name, bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override { SMLoc NameLoc, OperandVector &Operands) override {
Operands.push_back( Operands.push_back(make_unique<WebAssemblyOperand>(
make_unique<WebAssemblyOperand>(WebAssemblyOperand::Token, NameLoc, WebAssemblyOperand::Token, NameLoc,
SMLoc::getFromPointer( SMLoc::getFromPointer(NameLoc.getPointer() + Name.size()),
NameLoc.getPointer() + Name.size()), WebAssemblyOperand::TokOp{
WebAssemblyOperand::TokOp{ StringRef(NameLoc.getPointer(), Name.size())}));
StringRef(NameLoc.getPointer(),
Name.size())}));
auto NamePair = Name.split('.'); auto NamePair = Name.split('.');
// If no '.', there is no type prefix. // If no '.', there is no type prefix.
if (NamePair.second.empty()) std::swap(NamePair.first, NamePair.second); if (NamePair.second.empty())
std::swap(NamePair.first, NamePair.second);
while (Lexer.isNot(AsmToken::EndOfStatement)) { while (Lexer.isNot(AsmToken::EndOfStatement)) {
auto &Tok = Lexer.getTok(); auto &Tok = Lexer.getTok();
switch (Tok.getKind()) { switch (Tok.getKind()) {
@ -246,8 +246,8 @@ public:
if (Parser.parsePrimaryExpr(Val, End)) if (Parser.parsePrimaryExpr(Val, End))
return Error("Cannot parse symbol: ", Lexer.getTok()); return Error("Cannot parse symbol: ", Lexer.getTok());
Operands.push_back(make_unique<WebAssemblyOperand>( Operands.push_back(make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Symbol, Id.getLoc(), WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
Id.getEndLoc(), WebAssemblyOperand::SymOp{Val})); WebAssemblyOperand::SymOp{Val}));
break; break;
} }
case AsmToken::Minus: case AsmToken::Minus:
@ -266,8 +266,8 @@ public:
if (Tok.getString().getAsDouble(Val, false)) if (Tok.getString().getAsDouble(Val, false))
return Error("Cannot parse real: ", Tok); return Error("Cannot parse real: ", Tok);
Operands.push_back(make_unique<WebAssemblyOperand>( Operands.push_back(make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Float, Tok.getLoc(), WebAssemblyOperand::Float, Tok.getLoc(), Tok.getEndLoc(),
Tok.getEndLoc(), WebAssemblyOperand::FltOp{Val})); WebAssemblyOperand::FltOp{Val}));
Parser.Lex(); Parser.Lex();
break; break;
} }
@ -275,7 +275,8 @@ public:
return Error("Unexpected token in operand: ", Tok); return Error("Unexpected token in operand: ", Tok);
} }
if (Lexer.isNot(AsmToken::EndOfStatement)) { if (Lexer.isNot(AsmToken::EndOfStatement)) {
if (Expect(AsmToken::Comma, ",")) return true; if (Expect(AsmToken::Comma, ","))
return true;
} }
} }
Parser.Lex(); Parser.Lex();
@ -285,34 +286,30 @@ public:
// the wasm module is generated). // the wasm module is generated).
if (NamePair.second == "block" || NamePair.second == "loop") { if (NamePair.second == "block" || NamePair.second == "loop") {
Operands.push_back(make_unique<WebAssemblyOperand>( Operands.push_back(make_unique<WebAssemblyOperand>(
WebAssemblyOperand::Integer, NameLoc, WebAssemblyOperand::Integer, NameLoc, NameLoc,
NameLoc, WebAssemblyOperand::IntOp{-1})); WebAssemblyOperand::IntOp{-1}));
} }
return false; return false;
} }
void onLabelParsed(MCSymbol *Symbol) override { void onLabelParsed(MCSymbol *Symbol) override { LastLabel = Symbol; }
LastLabel = Symbol;
}
bool ParseDirective(AsmToken DirectiveID) override { bool ParseDirective(AsmToken DirectiveID) override {
assert(DirectiveID.getKind() == AsmToken::Identifier); assert(DirectiveID.getKind() == AsmToken::Identifier);
auto &Out = getStreamer(); auto &Out = getStreamer();
auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>( auto &TOut =
*Out.getTargetStreamer()); reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
// TODO: we're just parsing the subset of directives we're interested in, // TODO: we're just parsing the subset of directives we're interested in,
// and ignoring ones we don't recognise. We should ideally verify // and ignoring ones we don't recognise. We should ideally verify
// all directives here. // all directives here.
if (DirectiveID.getString() == ".type") { if (DirectiveID.getString() == ".type") {
// This could be the start of a function, check if followed by // This could be the start of a function, check if followed by
// "label,@function" // "label,@function"
if (!(IsNext(AsmToken::Identifier) && if (!(IsNext(AsmToken::Identifier) && IsNext(AsmToken::Comma) &&
IsNext(AsmToken::Comma) && IsNext(AsmToken::At) && Lexer.is(AsmToken::Identifier)))
IsNext(AsmToken::At) &&
Lexer.is(AsmToken::Identifier)))
return Error("Expected label,@type declaration, got: ", Lexer.getTok()); return Error("Expected label,@type declaration, got: ", Lexer.getTok());
Parser.Lex(); Parser.Lex();
//Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction); // Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
} else if (DirectiveID.getString() == ".param" || } else if (DirectiveID.getString() == ".param" ||
DirectiveID.getString() == ".local") { DirectiveID.getString() == ".local") {
// Track the number of locals, needed for correct virtual register // Track the number of locals, needed for correct virtual register
@ -322,28 +319,31 @@ public:
std::vector<MVT> Locals; std::vector<MVT> Locals;
while (Lexer.is(AsmToken::Identifier)) { while (Lexer.is(AsmToken::Identifier)) {
auto RegType = ParseRegType(Lexer.getTok().getString()); auto RegType = ParseRegType(Lexer.getTok().getString());
if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE) return true; if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE)
return true;
if (DirectiveID.getString() == ".param") { if (DirectiveID.getString() == ".param") {
Params.push_back(RegType); Params.push_back(RegType);
} else { } else {
Locals.push_back(RegType); Locals.push_back(RegType);
} }
Parser.Lex(); Parser.Lex();
if (!IsNext(AsmToken::Comma)) break; if (!IsNext(AsmToken::Comma))
break;
} }
assert(LastLabel); assert(LastLabel);
TOut.emitParam(LastLabel, Params); TOut.emitParam(LastLabel, Params);
TOut.emitLocal(Locals); TOut.emitLocal(Locals);
} else { } else {
// For now, ignore anydirective we don't recognize: // For now, ignore anydirective we don't recognize:
while (Lexer.isNot(AsmToken::EndOfStatement)) Parser.Lex(); while (Lexer.isNot(AsmToken::EndOfStatement))
Parser.Lex();
} }
return Expect(AsmToken::EndOfStatement, "EOL"); return Expect(AsmToken::EndOfStatement, "EOL");
} }
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &/*Opcode*/, bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
OperandVector &Operands, OperandVector &Operands, MCStreamer &Out,
MCStreamer &Out, uint64_t &ErrorInfo, uint64_t &ErrorInfo,
bool MatchingInlineAsm) override { bool MatchingInlineAsm) override {
MCInst Inst; MCInst Inst;
unsigned MatchResult = unsigned MatchResult =
@ -354,8 +354,8 @@ public:
return false; return false;
} }
case Match_MissingFeature: case Match_MissingFeature:
return Parser.Error(IDLoc, return Parser.Error(
"instruction requires a WASM feature not currently enabled"); IDLoc, "instruction requires a WASM feature not currently enabled");
case Match_MnemonicFail: case Match_MnemonicFail:
return Parser.Error(IDLoc, "invalid instruction"); return Parser.Error(IDLoc, "invalid instruction");
case Match_NearMisses: case Match_NearMisses:

View File

@ -57,10 +57,9 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
// FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because // FIXME: For CALL_INDIRECT_VOID, don't print a leading comma, because
// we have an extra flags operand which is not currently printed, for // we have an extra flags operand which is not currently printed, for
// compatiblity reasons. // compatiblity reasons.
if (i != 0 && if (i != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID && MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) || i != Desc.getNumOperands()))
i != Desc.getNumOperands()))
OS << ", "; OS << ", ";
printOperand(MI, i, OS); printOperand(MI, i, OS);
} }
@ -88,12 +87,14 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
case WebAssembly::END_LOOP_S: case WebAssembly::END_LOOP_S:
// Have to guard against an empty stack, in case of mismatched pairs // Have to guard against an empty stack, in case of mismatched pairs
// in assembly parsing. // in assembly parsing.
if (!ControlFlowStack.empty()) ControlFlowStack.pop_back(); if (!ControlFlowStack.empty())
ControlFlowStack.pop_back();
break; break;
case WebAssembly::END_BLOCK: case WebAssembly::END_BLOCK:
case WebAssembly::END_BLOCK_S: case WebAssembly::END_BLOCK_S:
if (!ControlFlowStack.empty()) printAnnotation( if (!ControlFlowStack.empty())
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':'); printAnnotation(
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
break; break;
} }
@ -118,17 +119,15 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
static std::string toString(const APFloat &FP) { static std::string toString(const APFloat &FP) {
// Print NaNs with custom payloads specially. // Print NaNs with custom payloads specially.
if (FP.isNaN() && if (FP.isNaN() && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
!FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
!FP.bitwiseIsEqual( !FP.bitwiseIsEqual(
APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) { APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) {
APInt AI = FP.bitcastToAPInt(); APInt AI = FP.bitcastToAPInt();
return return std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
std::string(AI.isNegative() ? "-" : "") + "nan:0x" + utohexstr(AI.getZExtValue() &
utohexstr(AI.getZExtValue() & (AI.getBitWidth() == 32 ? INT64_C(0x007fffff)
(AI.getBitWidth() == 32 ? INT64_C(0x007fffff) : : INT64_C(0x000fffffffffffff)),
INT64_C(0x000fffffffffffff)), /*LowerCase=*/true);
/*LowerCase=*/true);
} }
// Use C99's hexadecimal floating-point representation. // Use C99's hexadecimal floating-point representation.
@ -199,25 +198,40 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
} }
} }
void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand( void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI,
const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned OpNo,
raw_ostream &O) {
int64_t Imm = MI->getOperand(OpNo).getImm(); int64_t Imm = MI->getOperand(OpNo).getImm();
if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode())) if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode()))
return; return;
O << ":p2align=" << Imm; O << ":p2align=" << Imm;
} }
void WebAssemblyInstPrinter::printWebAssemblySignatureOperand( void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
const MCInst *MI, unsigned OpNo, raw_ostream &O) { unsigned OpNo,
raw_ostream &O) {
int64_t Imm = MI->getOperand(OpNo).getImm(); int64_t Imm = MI->getOperand(OpNo).getImm();
switch (WebAssembly::ExprType(Imm)) { switch (WebAssembly::ExprType(Imm)) {
case WebAssembly::ExprType::Void: break; case WebAssembly::ExprType::Void:
case WebAssembly::ExprType::I32: O << "i32"; break; break;
case WebAssembly::ExprType::I64: O << "i64"; break; case WebAssembly::ExprType::I32:
case WebAssembly::ExprType::F32: O << "f32"; break; O << "i32";
case WebAssembly::ExprType::F64: O << "f64"; break; break;
case WebAssembly::ExprType::V128: O << "v128"; break; case WebAssembly::ExprType::I64:
case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break; O << "i64";
break;
case WebAssembly::ExprType::F32:
O << "f32";
break;
case WebAssembly::ExprType::F64:
O << "f64";
break;
case WebAssembly::ExprType::V128:
O << "v128";
break;
case WebAssembly::ExprType::ExceptRef:
O << "except_ref";
break;
} }
} }

View File

@ -73,13 +73,13 @@ public:
const MCFixupKindInfo & const MCFixupKindInfo &
WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = { const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
// This table *must* be in the order that the fixup_* kinds are defined in // This table *must* be in the order that the fixup_* kinds are defined in
// WebAssemblyFixupKinds.h. // WebAssemblyFixupKinds.h.
// //
// Name Offset (bits) Size (bits) Flags // Name Offset (bits) Size (bits) Flags
{ "fixup_code_sleb128_i32", 0, 5*8, 0 }, {"fixup_code_sleb128_i32", 0, 5 * 8, 0},
{ "fixup_code_sleb128_i64", 0, 10*8, 0 }, {"fixup_code_sleb128_i64", 0, 10 * 8, 0},
{ "fixup_code_uleb128_i32", 0, 5*8, 0 }, {"fixup_code_uleb128_i32", 0, 5 * 8, 0},
}; };
if (Kind < FirstTargetFixupKind) if (Kind < FirstTargetFixupKind)

View File

@ -15,9 +15,9 @@
namespace llvm { namespace llvm {
namespace WebAssembly { namespace WebAssembly {
enum Fixups { enum Fixups {
fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed
fixup_code_sleb128_i64, // 64-bit signed fixup_code_sleb128_i64, // 64-bit signed
fixup_code_uleb128_i32, // 32-bit unsigned fixup_code_uleb128_i32, // 32-bit unsigned
// Marker // Marker
LastTargetFixupKind, LastTargetFixupKind,

View File

@ -67,8 +67,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
OS << uint8_t(Binary); OS << uint8_t(Binary);
} else { } else {
assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet"); assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet");
OS << uint8_t(Binary >> 8) OS << uint8_t(Binary >> 8) << uint8_t(Binary);
<< uint8_t(Binary);
} }
// For br_table instructions, encode the size of the table. In the MCInst, // For br_table instructions, encode the size of the table. In the MCInst,
@ -162,9 +161,8 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
} else { } else {
llvm_unreachable("unexpected symbolic operand kind"); llvm_unreachable("unexpected symbolic operand kind");
} }
Fixups.push_back(MCFixup::create( Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
OS.tell() - Start, MO.getExpr(), FixupKind, MI.getLoc()));
FixupKind, MI.getLoc()));
++MCNumFixups; ++MCNumFixups;
encodeULEB128(0, OS, PaddedSize); encodeULEB128(0, OS, PaddedSize);
} else { } else {

View File

@ -125,11 +125,17 @@ extern "C" void LLVMInitializeWebAssemblyTargetMC() {
wasm::ValType WebAssembly::toValType(const MVT &Ty) { wasm::ValType WebAssembly::toValType(const MVT &Ty) {
switch (Ty.SimpleTy) { switch (Ty.SimpleTy) {
case MVT::i32: return wasm::ValType::I32; case MVT::i32:
case MVT::i64: return wasm::ValType::I64; return wasm::ValType::I32;
case MVT::f32: return wasm::ValType::F32; case MVT::i64:
case MVT::f64: return wasm::ValType::F64; return wasm::ValType::I64;
case MVT::ExceptRef: return wasm::ValType::EXCEPT_REF; case MVT::f32:
default: llvm_unreachable("unexpected type"); return wasm::ValType::F32;
case MVT::f64:
return wasm::ValType::F64;
case MVT::ExceptRef:
return wasm::ValType::EXCEPT_REF;
default:
llvm_unreachable("unexpected type");
} }
} }

View File

@ -96,8 +96,8 @@ enum TOF {
// Flags to indicate the type of the symbol being referenced // Flags to indicate the type of the symbol being referenced
MO_SYMBOL_FUNCTION = 0x1, MO_SYMBOL_FUNCTION = 0x1,
MO_SYMBOL_GLOBAL = 0x2, MO_SYMBOL_GLOBAL = 0x2,
MO_SYMBOL_MASK = 0x3, MO_SYMBOL_MASK = 0x3,
}; };
} // end namespace WebAssemblyII } // end namespace WebAssemblyII

View File

@ -85,7 +85,8 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; } void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType( void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
MCSymbol *Symbol, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results) { MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Results) {
OS << "\t.functype\t" << Symbol->getName(); OS << "\t.functype\t" << Symbol->getName();
if (Results.empty()) if (Results.empty())
OS << ", void"; OS << ", void";

View File

@ -65,8 +65,7 @@ public:
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override; void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
void emitLocal(ArrayRef<MVT> Types) override; void emitLocal(ArrayRef<MVT> Types) override;
void emitEndFunc() override; void emitEndFunc() override;
void emitIndirectFunctionType(MCSymbol *Symbol, void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Results) override; SmallVectorImpl<MVT> &Results) override;
void emitIndIdx(const MCExpr *Value) override; void emitIndIdx(const MCExpr *Value) override;
void emitGlobalImport(StringRef name) override; void emitGlobalImport(StringRef name) override;
@ -82,8 +81,7 @@ public:
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override; void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
void emitLocal(ArrayRef<MVT> Types) override; void emitLocal(ArrayRef<MVT> Types) override;
void emitEndFunc() override; void emitEndFunc() override;
void emitIndirectFunctionType(MCSymbol *Symbol, void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Results) override; SmallVectorImpl<MVT> &Results) override;
void emitIndIdx(const MCExpr *Value) override; void emitIndIdx(const MCExpr *Value) override;
void emitGlobalImport(StringRef name) override; void emitGlobalImport(StringRef name) override;

View File

@ -86,9 +86,8 @@ static bool IsGlobalType(const MCValue &Target) {
return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL; return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
} }
unsigned unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
const MCFixup &Fixup) const {
// WebAssembly functions are not allocated in the data address space. To // WebAssembly functions are not allocated in the data address space. To
// resolve a pointer to a function, we must use a special relocation type. // resolve a pointer to a function, we must use a special relocation type.
bool IsFunction = IsFunctionExpr(Fixup.getValue()); bool IsFunction = IsFunctionExpr(Fixup.getValue());

View File

@ -24,10 +24,10 @@
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h" #include "llvm/IR/Operator.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm; using namespace llvm;
#define DEBUG_TYPE "wasm-add-missing-prototypes" #define DEBUG_TYPE "wasm-add-missing-prototypes"
@ -62,14 +62,15 @@ ModulePass *llvm::createWebAssemblyAddMissingPrototypes() {
bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) { bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n"); LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n");
std::vector<std::pair<Function*, Function*>> Replacements; std::vector<std::pair<Function *, Function *>> Replacements;
// Find all the prototype-less function declarations // Find all the prototype-less function declarations
for (Function &F : M) { for (Function &F : M) {
if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype")) if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
continue; continue;
LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName() << "\n"); LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName()
<< "\n");
// When clang emits prototype-less C functions it uses (...), i.e. varargs // When clang emits prototype-less C functions it uses (...), i.e. varargs
// function that take no arguments (have no sentinel). When we see a // function that take no arguments (have no sentinel). When we see a
@ -83,11 +84,10 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
"Functions with 'no-prototype' attribute should not have params: " + "Functions with 'no-prototype' attribute should not have params: " +
F.getName()); F.getName());
// Create a function prototype based on the first call site (first bitcast) // Create a function prototype based on the first call site (first bitcast)
// that we find. // that we find.
FunctionType *NewType = nullptr; FunctionType *NewType = nullptr;
Function* NewF = nullptr; Function *NewF = nullptr;
for (Use &U : F.uses()) { for (Use &U : F.uses()) {
LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n"); LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) { if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
@ -134,8 +134,8 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
// Finally replace the old function declarations with the new ones // Finally replace the old function declarations with the new ones
for (auto &Pair : Replacements) { for (auto &Pair : Replacements) {
Function* Old = Pair.first; Function *Old = Pair.first;
Function* New = Pair.second; Function *New = Pair.second;
Old->eraseFromParent(); Old->eraseFromParent();
M.getFunctionList().push_back(New); M.getFunctionList().push_back(New);
} }

View File

@ -90,8 +90,8 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (TM.getTargetTriple().isOSBinFormatWasm() && if (TM.getTargetTriple().isOSBinFormatWasm() &&
F.hasFnAttribute("wasm-import-module")) { F.hasFnAttribute("wasm-import-module")) {
MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym); MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
StringRef Name = F.getFnAttribute("wasm-import-module") StringRef Name =
.getValueAsString(); F.getFnAttribute("wasm-import-module").getValueAsString();
getTargetStreamer()->emitImportModule(WasmSym, Name); getTargetStreamer()->emitImportModule(WasmSym, Name);
} }
} }

View File

@ -29,8 +29,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
public: public:
explicit WebAssemblyAsmPrinter(TargetMachine &TM, explicit WebAssemblyAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer) std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)), : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), MRI(nullptr),
Subtarget(nullptr), MRI(nullptr), MFI(nullptr) {} MFI(nullptr) {}
StringRef getPassName() const override { StringRef getPassName() const override {
return "WebAssembly Assembly Printer"; return "WebAssembly Assembly Printer";

View File

@ -97,8 +97,8 @@ public:
char WebAssemblyCFGStackify::ID = 0; char WebAssemblyCFGStackify::ID = 0;
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE, INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
"Insert BLOCK and LOOP markers for WebAssembly scopes", "Insert BLOCK and LOOP markers for WebAssembly scopes", false,
false, false) false)
FunctionPass *llvm::createWebAssemblyCFGStackify() { FunctionPass *llvm::createWebAssemblyCFGStackify() {
return new WebAssemblyCFGStackify(); return new WebAssemblyCFGStackify();
@ -633,10 +633,18 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
WebAssembly::ExprType retType; WebAssembly::ExprType retType;
switch (MFI.getResults().front().SimpleTy) { switch (MFI.getResults().front().SimpleTy) {
case MVT::i32: retType = WebAssembly::ExprType::I32; break; case MVT::i32:
case MVT::i64: retType = WebAssembly::ExprType::I64; break; retType = WebAssembly::ExprType::I32;
case MVT::f32: retType = WebAssembly::ExprType::F32; break; break;
case MVT::f64: retType = WebAssembly::ExprType::F64; break; case MVT::i64:
retType = WebAssembly::ExprType::I64;
break;
case MVT::f32:
retType = WebAssembly::ExprType::F32;
break;
case MVT::f64:
retType = WebAssembly::ExprType::F64;
break;
case MVT::v16i8: case MVT::v16i8:
case MVT::v8i16: case MVT::v8i16:
case MVT::v4i32: case MVT::v4i32:
@ -645,8 +653,11 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
case MVT::v2f64: case MVT::v2f64:
retType = WebAssembly::ExprType::V128; retType = WebAssembly::ExprType::V128;
break; break;
case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break; case MVT::ExceptRef:
default: llvm_unreachable("unexpected return type"); retType = WebAssembly::ExprType::ExceptRef;
break;
default:
llvm_unreachable("unexpected return type");
} }
for (MachineBasicBlock &MBB : reverse(MF)) { for (MachineBasicBlock &MBB : reverse(MF)) {
@ -669,9 +680,8 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
// WebAssembly functions end with an end instruction, as if the function body // WebAssembly functions end with an end instruction, as if the function body
// were a block. // were a block.
static void AppendEndToFunction( static void AppendEndToFunction(MachineFunction &MF,
MachineFunction &MF, const WebAssemblyInstrInfo &TII) {
const WebAssemblyInstrInfo &TII) {
BuildMI(MF.back(), MF.back().end(), BuildMI(MF.back(), MF.back().end(),
MF.back().findPrevDebugLoc(MF.back().end()), MF.back().findPrevDebugLoc(MF.back().end()),
TII.get(WebAssembly::END_FUNCTION)); TII.get(WebAssembly::END_FUNCTION));

View File

@ -64,18 +64,30 @@ FunctionPass *llvm::createWebAssemblyCallIndirectFixup() {
static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) { static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
switch (MI.getOpcode()) { switch (MI.getOpcode()) {
using namespace WebAssembly; using namespace WebAssembly;
case PCALL_INDIRECT_VOID: return CALL_INDIRECT_VOID; case PCALL_INDIRECT_VOID:
case PCALL_INDIRECT_I32: return CALL_INDIRECT_I32; return CALL_INDIRECT_VOID;
case PCALL_INDIRECT_I64: return CALL_INDIRECT_I64; case PCALL_INDIRECT_I32:
case PCALL_INDIRECT_F32: return CALL_INDIRECT_F32; return CALL_INDIRECT_I32;
case PCALL_INDIRECT_F64: return CALL_INDIRECT_F64; case PCALL_INDIRECT_I64:
case PCALL_INDIRECT_v16i8: return CALL_INDIRECT_v16i8; return CALL_INDIRECT_I64;
case PCALL_INDIRECT_v8i16: return CALL_INDIRECT_v8i16; case PCALL_INDIRECT_F32:
case PCALL_INDIRECT_v4i32: return CALL_INDIRECT_v4i32; return CALL_INDIRECT_F32;
case PCALL_INDIRECT_v2i64: return CALL_INDIRECT_v2i64; case PCALL_INDIRECT_F64:
case PCALL_INDIRECT_v4f32: return CALL_INDIRECT_v4f32; return CALL_INDIRECT_F64;
case PCALL_INDIRECT_v2f64: return CALL_INDIRECT_v2f64; case PCALL_INDIRECT_v16i8:
default: return INSTRUCTION_LIST_END; return CALL_INDIRECT_v16i8;
case PCALL_INDIRECT_v8i16:
return CALL_INDIRECT_v8i16;
case PCALL_INDIRECT_v4i32:
return CALL_INDIRECT_v4i32;
case PCALL_INDIRECT_v2i64:
return CALL_INDIRECT_v2i64;
case PCALL_INDIRECT_v4f32:
return CALL_INDIRECT_v4f32;
case PCALL_INDIRECT_v2f64:
return CALL_INDIRECT_v2f64;
default:
return INSTRUCTION_LIST_END;
} }
} }
@ -112,10 +124,8 @@ bool WebAssemblyCallIndirectFixup::runOnMachineFunction(MachineFunction &MF) {
Ops.push_back(MachineOperand::CreateImm(0)); Ops.push_back(MachineOperand::CreateImm(0));
for (const MachineOperand &MO : for (const MachineOperand &MO :
make_range(MI.operands_begin() + make_range(MI.operands_begin() + MI.getDesc().getNumDefs() + 1,
MI.getDesc().getNumDefs() + 1, MI.operands_begin() + MI.getNumExplicitOperands()))
MI.operands_begin() +
MI.getNumExplicitOperands()))
Ops.push_back(MO); Ops.push_back(MO);
Ops.push_back(MI.getOperand(MI.getDesc().getNumDefs())); Ops.push_back(MI.getOperand(MI.getDesc().getNumDefs()));

View File

@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "WebAssemblyExceptionInfo.h" #include "WebAssemblyExceptionInfo.h"
#include "WebAssemblyUtilities.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "WebAssemblyUtilities.h"
#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/PostOrderIterator.h"
#include "llvm/CodeGen/MachineDominanceFrontier.h" #include "llvm/CodeGen/MachineDominanceFrontier.h"
#include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineDominators.h"

View File

@ -114,8 +114,8 @@ private:
// Utility helper routines // Utility helper routines
MVT::SimpleValueType getSimpleType(Type *Ty) { MVT::SimpleValueType getSimpleType(Type *Ty) {
EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true); EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
return VT.isSimple() ? VT.getSimpleVT().SimpleTy : return VT.isSimple() ? VT.getSimpleVT().SimpleTy
MVT::INVALID_SIMPLE_VALUE_TYPE; : MVT::INVALID_SIMPLE_VALUE_TYPE;
} }
MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) { MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
switch (VT) { switch (VT) {
@ -155,11 +155,9 @@ private:
MVT::SimpleValueType From); MVT::SimpleValueType From);
unsigned signExtendToI32(unsigned Reg, const Value *V, unsigned signExtendToI32(unsigned Reg, const Value *V,
MVT::SimpleValueType From); MVT::SimpleValueType From);
unsigned zeroExtend(unsigned Reg, const Value *V, unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
MVT::SimpleValueType From,
MVT::SimpleValueType To); MVT::SimpleValueType To);
unsigned signExtend(unsigned Reg, const Value *V, unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
MVT::SimpleValueType From,
MVT::SimpleValueType To); MVT::SimpleValueType To);
unsigned getRegForUnsignedValue(const Value *V); unsigned getRegForUnsignedValue(const Value *V);
unsigned getRegForSignedValue(const Value *V); unsigned getRegForSignedValue(const Value *V);
@ -376,14 +374,12 @@ void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
if (Addr.isRegBase()) { if (Addr.isRegBase()) {
unsigned Reg = Addr.getReg(); unsigned Reg = Addr.getReg();
if (Reg == 0) { if (Reg == 0) {
Reg = createResultReg(Subtarget->hasAddr64() ? Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
&WebAssembly::I64RegClass : : &WebAssembly::I32RegClass);
&WebAssembly::I32RegClass); unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
unsigned Opc = Subtarget->hasAddr64() ? : WebAssembly::CONST_I32;
WebAssembly::CONST_I64 :
WebAssembly::CONST_I32;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
.addImm(0); .addImm(0);
Addr.setReg(Reg); Addr.setReg(Reg);
} }
} }
@ -459,13 +455,13 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
unsigned Imm = createResultReg(&WebAssembly::I32RegClass); unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::CONST_I32), Imm) TII.get(WebAssembly::CONST_I32), Imm)
.addImm(~(~uint64_t(0) << MVT(From).getSizeInBits())); .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
unsigned Result = createResultReg(&WebAssembly::I32RegClass); unsigned Result = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::AND_I32), Result) TII.get(WebAssembly::AND_I32), Result)
.addReg(Reg) .addReg(Reg)
.addReg(Imm); .addReg(Imm);
return Result; return Result;
} }
@ -489,19 +485,19 @@ unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
unsigned Imm = createResultReg(&WebAssembly::I32RegClass); unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::CONST_I32), Imm) TII.get(WebAssembly::CONST_I32), Imm)
.addImm(32 - MVT(From).getSizeInBits()); .addImm(32 - MVT(From).getSizeInBits());
unsigned Left = createResultReg(&WebAssembly::I32RegClass); unsigned Left = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::SHL_I32), Left) TII.get(WebAssembly::SHL_I32), Left)
.addReg(Reg) .addReg(Reg)
.addReg(Imm); .addReg(Imm);
unsigned Right = createResultReg(&WebAssembly::I32RegClass); unsigned Right = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::SHR_S_I32), Right) TII.get(WebAssembly::SHR_S_I32), Right)
.addReg(Left) .addReg(Left)
.addReg(Imm); .addReg(Imm);
return Right; return Right;
} }
@ -564,8 +560,7 @@ unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V, unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
bool IsSigned) { bool IsSigned) {
return IsSigned ? getRegForSignedValue(V) : return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
getRegForUnsignedValue(V);
} }
unsigned WebAssemblyFastISel::notValue(unsigned Reg) { unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
@ -574,15 +569,15 @@ unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
unsigned NotReg = createResultReg(&WebAssembly::I32RegClass); unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::EQZ_I32), NotReg) TII.get(WebAssembly::EQZ_I32), NotReg)
.addReg(Reg); .addReg(Reg);
return NotReg; return NotReg;
} }
unsigned WebAssemblyFastISel::copyValue(unsigned Reg) { unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
unsigned ResultReg = createResultReg(MRI.getRegClass(Reg)); unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
TII.get(WebAssembly::COPY), ResultReg) ResultReg)
.addReg(Reg); .addReg(Reg);
return ResultReg; return ResultReg;
} }
@ -591,12 +586,11 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
FuncInfo.StaticAllocaMap.find(AI); FuncInfo.StaticAllocaMap.find(AI);
if (SI != FuncInfo.StaticAllocaMap.end()) { if (SI != FuncInfo.StaticAllocaMap.end()) {
unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ? unsigned ResultReg =
&WebAssembly::I64RegClass : createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
&WebAssembly::I32RegClass); : &WebAssembly::I32RegClass);
unsigned Opc = Subtarget->hasAddr64() ? unsigned Opc =
WebAssembly::COPY_I64 : Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
WebAssembly::COPY_I32;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
.addFrameIndex(SI->second); .addFrameIndex(SI->second);
return ResultReg; return ResultReg;
@ -607,14 +601,13 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) { unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) { if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ? unsigned ResultReg =
&WebAssembly::I64RegClass : createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
&WebAssembly::I32RegClass); : &WebAssembly::I32RegClass);
unsigned Opc = Subtarget->hasAddr64() ? unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
WebAssembly::CONST_I64 : : WebAssembly::CONST_I32;
WebAssembly::CONST_I32;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
.addGlobalAddress(GV); .addGlobalAddress(GV);
return ResultReg; return ResultReg;
} }
@ -701,7 +694,7 @@ bool WebAssemblyFastISel::fastLowerArguments() {
} }
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
.addImm(i); .addImm(i);
updateValueMap(&Arg, ResultReg); updateValueMap(&Arg, ResultReg);
++i; ++i;
@ -720,7 +713,8 @@ bool WebAssemblyFastISel::fastLowerArguments() {
} }
if (!F->getReturnType()->isVoidTy()) { if (!F->getReturnType()->isVoidTy()) {
MVT::SimpleValueType RetTy = getLegalType(getSimpleType(F->getReturnType())); MVT::SimpleValueType RetTy =
getLegalType(getSimpleType(F->getReturnType()));
if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) { if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
MFI->clearParamsAndResults(); MFI->clearParamsAndResults();
return false; return false;
@ -778,33 +772,33 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
ResultReg = createResultReg(&WebAssembly::F64RegClass); ResultReg = createResultReg(&WebAssembly::F64RegClass);
break; break;
case MVT::v16i8: case MVT::v16i8:
Opc = Opc = IsDirect ? WebAssembly::CALL_v16i8
IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8; : WebAssembly::PCALL_INDIRECT_v16i8;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::v8i16: case MVT::v8i16:
Opc = Opc = IsDirect ? WebAssembly::CALL_v8i16
IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16; : WebAssembly::PCALL_INDIRECT_v8i16;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::v4i32: case MVT::v4i32:
Opc = Opc = IsDirect ? WebAssembly::CALL_v4i32
IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32; : WebAssembly::PCALL_INDIRECT_v4i32;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::v2i64: case MVT::v2i64:
Opc = Opc = IsDirect ? WebAssembly::CALL_v2i64
IsDirect ? WebAssembly::CALL_v2i64 : WebAssembly::PCALL_INDIRECT_v2i64; : WebAssembly::PCALL_INDIRECT_v2i64;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::v4f32: case MVT::v4f32:
Opc = Opc = IsDirect ? WebAssembly::CALL_v4f32
IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32; : WebAssembly::PCALL_INDIRECT_v4f32;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::v2f64: case MVT::v2f64:
Opc = Opc = IsDirect ? WebAssembly::CALL_v2f64
IsDirect ? WebAssembly::CALL_v2f64 : WebAssembly::PCALL_INDIRECT_v2f64; : WebAssembly::PCALL_INDIRECT_v2f64;
ResultReg = createResultReg(&WebAssembly::V128RegClass); ResultReg = createResultReg(&WebAssembly::V128RegClass);
break; break;
case MVT::ExceptRef: case MVT::ExceptRef:
@ -873,11 +867,11 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
const SelectInst *Select = cast<SelectInst>(I); const SelectInst *Select = cast<SelectInst>(I);
bool Not; bool Not;
unsigned CondReg = getRegForI1Value(Select->getCondition(), Not); unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
if (CondReg == 0) if (CondReg == 0)
return false; return false;
unsigned TrueReg = getRegForValue(Select->getTrueValue()); unsigned TrueReg = getRegForValue(Select->getTrueValue());
if (TrueReg == 0) if (TrueReg == 0)
return false; return false;
@ -920,9 +914,9 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
unsigned ResultReg = createResultReg(RC); unsigned ResultReg = createResultReg(RC);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
.addReg(TrueReg) .addReg(TrueReg)
.addReg(FalseReg) .addReg(FalseReg)
.addReg(CondReg); .addReg(CondReg);
updateValueMap(Select, ResultReg); updateValueMap(Select, ResultReg);
return true; return true;
@ -1022,7 +1016,8 @@ bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64; Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
isSigned = true; isSigned = true;
break; break;
default: return false; default:
return false;
} }
unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned); unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
@ -1230,7 +1225,8 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {
case MVT::f64: case MVT::f64:
Opc = WebAssembly::STORE_F64; Opc = WebAssembly::STORE_F64;
break; break;
default: return false; default:
return false;
} }
materializeLoadStoreOperands(Addr); materializeLoadStoreOperands(Addr);
@ -1295,8 +1291,10 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
unsigned Opc; unsigned Opc;
switch (getSimpleType(RV->getType())) { switch (getSimpleType(RV->getType())) {
case MVT::i1: case MVT::i8: case MVT::i1:
case MVT::i16: case MVT::i32: case MVT::i8:
case MVT::i16:
case MVT::i32:
Opc = WebAssembly::RETURN_I32; Opc = WebAssembly::RETURN_I32;
break; break;
case MVT::i64: case MVT::i64:
@ -1329,7 +1327,8 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
case MVT::ExceptRef: case MVT::ExceptRef:
Opc = WebAssembly::RETURN_EXCEPT_REF; Opc = WebAssembly::RETURN_EXCEPT_REF;
break; break;
default: return false; default:
return false;
} }
unsigned Reg; unsigned Reg;
@ -1359,19 +1358,32 @@ bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
if (selectCall(I)) if (selectCall(I))
return true; return true;
break; break;
case Instruction::Select: return selectSelect(I); case Instruction::Select:
case Instruction::Trunc: return selectTrunc(I); return selectSelect(I);
case Instruction::ZExt: return selectZExt(I); case Instruction::Trunc:
case Instruction::SExt: return selectSExt(I); return selectTrunc(I);
case Instruction::ICmp: return selectICmp(I); case Instruction::ZExt:
case Instruction::FCmp: return selectFCmp(I); return selectZExt(I);
case Instruction::BitCast: return selectBitCast(I); case Instruction::SExt:
case Instruction::Load: return selectLoad(I); return selectSExt(I);
case Instruction::Store: return selectStore(I); case Instruction::ICmp:
case Instruction::Br: return selectBr(I); return selectICmp(I);
case Instruction::Ret: return selectRet(I); case Instruction::FCmp:
case Instruction::Unreachable: return selectUnreachable(I); return selectFCmp(I);
default: break; case Instruction::BitCast:
return selectBitCast(I);
case Instruction::Load:
return selectLoad(I);
case Instruction::Store:
return selectStore(I);
case Instruction::Br:
return selectBr(I);
case Instruction::Ret:
return selectRet(I);
case Instruction::Unreachable:
return selectUnreachable(I);
default:
break;
} }
// Fall back to target-independent instruction selection. // Fall back to target-independent instruction selection.

View File

@ -36,10 +36,10 @@ using namespace llvm;
#define DEBUG_TYPE "wasm-fix-function-bitcasts" #define DEBUG_TYPE "wasm-fix-function-bitcasts"
static cl::opt<bool> TemporaryWorkarounds( static cl::opt<bool>
"wasm-temporary-workarounds", TemporaryWorkarounds("wasm-temporary-workarounds",
cl::desc("Apply certain temporary workarounds"), cl::desc("Apply certain temporary workarounds"),
cl::init(true), cl::Hidden); cl::init(true), cl::Hidden);
namespace { namespace {
class FixFunctionBitcasts final : public ModulePass { class FixFunctionBitcasts final : public ModulePass {
@ -108,7 +108,7 @@ static void FindUses(Value *V, Function &F,
// instead). // instead).
// //
// If there is a type mismatch that we know would result in an invalid wasm // If there is a type mismatch that we know would result in an invalid wasm
// module then generate wrapper that contains unreachable (i.e. abort at // module then generate wrapper that contains unreachable (i.e. abort at
// runtime). Such programs are deep into undefined behaviour territory, // runtime). Such programs are deep into undefined behaviour territory,
// but we choose to fail at runtime rather than generate and invalid module // but we choose to fail at runtime rather than generate and invalid module
// or fail at compiler time. The reason we delay the error is that we want // or fail at compiler time. The reason we delay the error is that we want
@ -117,7 +117,7 @@ static void FindUses(Value *V, Function &F,
// CMake detects the existence of a function in a toolchain). // CMake detects the existence of a function in a toolchain).
// //
// For bitcasts that involve struct types we don't know at this stage if they // For bitcasts that involve struct types we don't know at this stage if they
// would be equivalent at the wasm level and so we can't know if we need to // would be equivalent at the wasm level and so we can't know if we need to
// generate a wrapper. // generate a wrapper.
static Function *CreateWrapper(Function *F, FunctionType *Ty) { static Function *CreateWrapper(Function *F, FunctionType *Ty) {
Module *M = F->getParent(); Module *M = F->getParent();
@ -212,7 +212,8 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
if (TypeMismatch) { if (TypeMismatch) {
// Create a new wrapper that simply contains `unreachable`. // Create a new wrapper that simply contains `unreachable`.
Wrapper->eraseFromParent(); Wrapper->eraseFromParent();
Wrapper = Function::Create(Ty, Function::PrivateLinkage, F->getName() + "_bitcast_invalid", M); Wrapper = Function::Create(Ty, Function::PrivateLinkage,
F->getName() + "_bitcast_invalid", M);
BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper); BasicBlock *BB = BasicBlock::Create(M->getContext(), "body", Wrapper);
new UnreachableInst(M->getContext(), BB); new UnreachableInst(M->getContext(), BB);
Wrapper->setName(F->getName() + "_bitcast_invalid"); Wrapper->setName(F->getName() + "_bitcast_invalid");
@ -243,19 +244,15 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") { if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") {
Main = &F; Main = &F;
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
Type *MainArgTys[] = { Type *MainArgTys[] = {PointerType::get(Type::getInt8PtrTy(C), 0),
PointerType::get(Type::getInt8PtrTy(C), 0), Type::getInt32Ty(C)};
Type::getInt32Ty(C)
};
FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys, FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
/*isVarArg=*/false); /*isVarArg=*/false);
if (F.getFunctionType() != MainTy) { if (F.getFunctionType() != MainTy) {
Value *Args[] = { Value *Args[] = {UndefValue::get(MainArgTys[0]),
UndefValue::get(MainArgTys[0]), UndefValue::get(MainArgTys[1])};
UndefValue::get(MainArgTys[1]) Value *Casted =
}; ConstantExpr::getBitCast(Main, PointerType::get(MainTy, 0));
Value *Casted = ConstantExpr::getBitCast(Main,
PointerType::get(MainTy, 0));
CallMain = CallInst::Create(Casted, Args, "call_main"); CallMain = CallInst::Create(Casted, Args, "call_main");
Use *UseMain = &CallMain->getOperandUse(2); Use *UseMain = &CallMain->getOperandUse(2);
Uses.push_back(std::make_pair(UseMain, &F)); Uses.push_back(std::make_pair(UseMain, &F));

View File

@ -43,8 +43,7 @@ using namespace llvm;
/// require stricter alignment than the stack pointer itself. Because we need /// require stricter alignment than the stack pointer itself. Because we need
/// to shift the stack pointer by some unknown amount to force the alignment, /// to shift the stack pointer by some unknown amount to force the alignment,
/// we need to record the value of the stack pointer on entry to the function. /// we need to record the value of the stack pointer on entry to the function.
bool WebAssemblyFrameLowering::hasBP( bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const {
const MachineFunction &MF) const {
const auto *RegInfo = const auto *RegInfo =
MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo(); MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
return RegInfo->needsStackRealignment(MF); return RegInfo->needsStackRealignment(MF);
@ -158,7 +157,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
assert(MFI.getCalleeSavedInfo().empty() && assert(MFI.getCalleeSavedInfo().empty() &&
"WebAssembly should not have callee-saved registers"); "WebAssembly should not have callee-saved registers");
if (!needsSP(MF)) return; if (!needsSP(MF))
return;
uint64_t StackSize = MFI.getStackSize(); uint64_t StackSize = MFI.getStackSize();
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
@ -202,7 +202,7 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC); unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC);
unsigned Alignment = MFI.getMaxAlignment(); unsigned Alignment = MFI.getMaxAlignment();
assert((1u << countTrailingZeros(Alignment)) == Alignment && assert((1u << countTrailingZeros(Alignment)) == Alignment &&
"Alignment must be a power of 2"); "Alignment must be a power of 2");
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg) BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg)
.addImm((int)~(Alignment - 1)); .addImm((int)~(Alignment - 1));
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32), BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32),
@ -214,8 +214,7 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
// Unlike most conventional targets (where FP points to the saved FP), // Unlike most conventional targets (where FP points to the saved FP),
// FP points to the bottom of the fixed-size locals, so we can use positive // FP points to the bottom of the fixed-size locals, so we can use positive
// offsets in load/store instructions. // offsets in load/store instructions.
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32)
WebAssembly::FP32)
.addReg(WebAssembly::SP32); .addReg(WebAssembly::SP32);
} }
if (StackSize && needsSPWriteback(MF)) { if (StackSize && needsSPWriteback(MF)) {
@ -226,7 +225,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const { MachineBasicBlock &MBB) const {
uint64_t StackSize = MF.getFrameInfo().getStackSize(); uint64_t StackSize = MF.getFrameInfo().getStackSize();
if (!needsSP(MF) || !needsSPWriteback(MF)) return; if (!needsSP(MF) || !needsSPWriteback(MF))
return;
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
auto &MRI = MF.getRegInfo(); auto &MRI = MF.getRegInfo();
auto InsertPt = MBB.getFirstTerminator(); auto InsertPt = MBB.getFirstTerminator();

View File

@ -22,7 +22,7 @@ namespace llvm {
class MachineFrameInfo; class MachineFrameInfo;
class WebAssemblyFrameLowering final : public TargetFrameLowering { class WebAssemblyFrameLowering final : public TargetFrameLowering {
public: public:
/// Size of the red zone for the user stack (leaf functions can use this much /// Size of the red zone for the user stack (leaf functions can use this much
/// space below the stack pointer without writing it back to __stack_pointer /// space below the stack pointer without writing it back to __stack_pointer
/// global). /// global).
@ -35,9 +35,9 @@ class WebAssemblyFrameLowering final : public TargetFrameLowering {
/*TransientStackAlignment=*/16, /*TransientStackAlignment=*/16,
/*StackRealignable=*/true) {} /*StackRealignable=*/true) {}
MachineBasicBlock::iterator eliminateCallFramePseudoInstr( MachineBasicBlock::iterator
MachineFunction &MF, MachineBasicBlock &MBB, eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override; MachineBasicBlock::iterator I) const override;
/// These methods insert prolog and epilog code into the function. /// These methods insert prolog and epilog code into the function.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
@ -61,6 +61,6 @@ private:
bool needsSPWriteback(const MachineFunction &MF) const; bool needsSPWriteback(const MachineFunction &MF) const;
}; };
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -95,8 +95,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE}) ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
setCondCodeAction(CC, T, Expand); setCondCodeAction(CC, T, Expand);
// Expand floating-point library function operators. // Expand floating-point library function operators.
for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, for (auto Op :
ISD::FMA}) {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FMA})
setOperationAction(Op, T, Expand); setOperationAction(Op, T, Expand);
// Note supported floating-point library function operators that otherwise // Note supported floating-point library function operators that otherwise
// default to expand. // default to expand.
@ -116,10 +116,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
for (auto T : {MVT::i32, MVT::i64}) { for (auto T : {MVT::i32, MVT::i64}) {
// Expand unavailable integer operations. // Expand unavailable integer operations.
for (auto Op : for (auto Op :
{ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
ISD::SRA_PARTS, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
ISD::SUBE}) {
setOperationAction(Op, T, Expand); setOperationAction(Op, T, Expand);
} }
} }
@ -201,7 +200,8 @@ bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/, MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
EVT VT) const { EVT VT) const {
unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1); unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
if (BitWidth > 1 && BitWidth < 8) BitWidth = 8; if (BitWidth > 1 && BitWidth < 8)
BitWidth = 8;
if (BitWidth > 64) { if (BitWidth > 64) {
// The shift will be lowered to a libcall, and compiler-rt libcalls expect // The shift will be lowered to a libcall, and compiler-rt libcalls expect
@ -220,17 +220,11 @@ MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
// Lower an fp-to-int conversion operator from the LLVM opcode, which has an // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
// undefined result on invalid/overflow, to the WebAssembly opcode, which // undefined result on invalid/overflow, to the WebAssembly opcode, which
// traps on invalid/overflow. // traps on invalid/overflow.
static MachineBasicBlock * static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
LowerFPToInt( MachineBasicBlock *BB,
MachineInstr &MI, const TargetInstrInfo &TII,
DebugLoc DL, bool IsUnsigned, bool Int64,
MachineBasicBlock *BB, bool Float64, unsigned LoweredOpcode) {
const TargetInstrInfo &TII,
bool IsUnsigned,
bool Int64,
bool Float64,
unsigned LoweredOpcode
) {
MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
unsigned OutReg = MI.getOperand(0).getReg(); unsigned OutReg = MI.getOperand(0).getReg();
@ -262,8 +256,7 @@ LowerFPToInt(
// Transfer the remainder of BB and its successor edges to DoneMBB. // Transfer the remainder of BB and its successor edges to DoneMBB.
DoneMBB->splice(DoneMBB->begin(), BB, DoneMBB->splice(DoneMBB->begin(), BB,
std::next(MachineBasicBlock::iterator(MI)), std::next(MachineBasicBlock::iterator(MI)), BB->end());
BB->end());
DoneMBB->transferSuccessorsAndUpdatePHIs(BB); DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
BB->addSuccessor(TrueMBB); BB->addSuccessor(TrueMBB);
@ -285,45 +278,33 @@ LowerFPToInt(
if (IsUnsigned) { if (IsUnsigned) {
Tmp0 = InReg; Tmp0 = InReg;
} else { } else {
BuildMI(BB, DL, TII.get(Abs), Tmp0) BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
.addReg(InReg);
} }
BuildMI(BB, DL, TII.get(FConst), Tmp1) BuildMI(BB, DL, TII.get(FConst), Tmp1)
.addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal))); .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
BuildMI(BB, DL, TII.get(LT), CmpReg) BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
.addReg(Tmp0)
.addReg(Tmp1);
// For unsigned numbers, we have to do a separate comparison with zero. // For unsigned numbers, we have to do a separate comparison with zero.
if (IsUnsigned) { if (IsUnsigned) {
Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg)); Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
unsigned SecondCmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); unsigned SecondCmpReg =
MRI.createVirtualRegister(&WebAssembly::I32RegClass);
unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
BuildMI(BB, DL, TII.get(FConst), Tmp1) BuildMI(BB, DL, TII.get(FConst), Tmp1)
.addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0))); .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
BuildMI(BB, DL, TII.get(GE), SecondCmpReg) BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
.addReg(Tmp0) BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
.addReg(Tmp1);
BuildMI(BB, DL, TII.get(And), AndReg)
.addReg(CmpReg)
.addReg(SecondCmpReg);
CmpReg = AndReg; CmpReg = AndReg;
} }
BuildMI(BB, DL, TII.get(Eqz), EqzReg) BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
.addReg(CmpReg);
// Create the CFG diamond to select between doing the conversion or using // Create the CFG diamond to select between doing the conversion or using
// the substitute value. // the substitute value.
BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)) BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
.addMBB(TrueMBB) BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
.addReg(EqzReg); BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg) BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
.addReg(InReg);
BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR))
.addMBB(DoneMBB);
BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg)
.addImm(Substitute);
BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg) BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
.addReg(FalseReg) .addReg(FalseReg)
.addMBB(FalseMBB) .addMBB(FalseMBB)
@ -333,16 +314,14 @@ LowerFPToInt(
return DoneMBB; return DoneMBB;
} }
MachineBasicBlock * MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
WebAssemblyTargetLowering::EmitInstrWithCustomInserter( MachineInstr &MI, MachineBasicBlock *BB) const {
MachineInstr &MI,
MachineBasicBlock *BB
) const {
const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
DebugLoc DL = MI.getDebugLoc(); DebugLoc DL = MI.getDebugLoc();
switch (MI.getOpcode()) { switch (MI.getOpcode()) {
default: llvm_unreachable("Unexpected instr type to insert"); default:
llvm_unreachable("Unexpected instr type to insert");
case WebAssembly::FP_TO_SINT_I32_F32: case WebAssembly::FP_TO_SINT_I32_F32:
return LowerFPToInt(MI, DL, BB, TII, false, false, false, return LowerFPToInt(MI, DL, BB, TII, false, false, false,
WebAssembly::I32_TRUNC_S_F32); WebAssembly::I32_TRUNC_S_F32);
@ -367,17 +346,17 @@ WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
case WebAssembly::FP_TO_UINT_I64_F64: case WebAssembly::FP_TO_UINT_I64_F64:
return LowerFPToInt(MI, DL, BB, TII, true, true, true, return LowerFPToInt(MI, DL, BB, TII, true, true, true,
WebAssembly::I64_TRUNC_U_F64); WebAssembly::I64_TRUNC_U_F64);
llvm_unreachable("Unexpected instruction to emit with custom inserter"); llvm_unreachable("Unexpected instruction to emit with custom inserter");
} }
} }
const char *WebAssemblyTargetLowering::getTargetNodeName( const char *
unsigned Opcode) const { WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) { switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
case WebAssemblyISD::FIRST_NUMBER: case WebAssemblyISD::FIRST_NUMBER:
break; break;
#define HANDLE_NODETYPE(NODE) \ #define HANDLE_NODETYPE(NODE) \
case WebAssemblyISD::NODE: \ case WebAssemblyISD::NODE: \
return "WebAssemblyISD::" #NODE; return "WebAssemblyISD::" #NODE;
#include "WebAssemblyISD.def" #include "WebAssemblyISD.def"
#undef HANDLE_NODETYPE #undef HANDLE_NODETYPE
@ -392,21 +371,21 @@ WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
// WebAssembly register class. // WebAssembly register class.
if (Constraint.size() == 1) { if (Constraint.size() == 1) {
switch (Constraint[0]) { switch (Constraint[0]) {
case 'r': case 'r':
assert(VT != MVT::iPTR && "Pointer MVT not expected here"); assert(VT != MVT::iPTR && "Pointer MVT not expected here");
if (Subtarget->hasSIMD128() && VT.isVector()) { if (Subtarget->hasSIMD128() && VT.isVector()) {
if (VT.getSizeInBits() == 128) if (VT.getSizeInBits() == 128)
return std::make_pair(0U, &WebAssembly::V128RegClass); return std::make_pair(0U, &WebAssembly::V128RegClass);
} }
if (VT.isInteger() && !VT.isVector()) { if (VT.isInteger() && !VT.isVector()) {
if (VT.getSizeInBits() <= 32) if (VT.getSizeInBits() <= 32)
return std::make_pair(0U, &WebAssembly::I32RegClass); return std::make_pair(0U, &WebAssembly::I32RegClass);
if (VT.getSizeInBits() <= 64) if (VT.getSizeInBits() <= 64)
return std::make_pair(0U, &WebAssembly::I64RegClass); return std::make_pair(0U, &WebAssembly::I64RegClass);
} }
break; break;
default: default:
break; break;
} }
} }
@ -425,16 +404,17 @@ bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL, bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
const AddrMode &AM, const AddrMode &AM,
Type *Ty, Type *Ty, unsigned AS,
unsigned AS,
Instruction *I) const { Instruction *I) const {
// WebAssembly offsets are added as unsigned without wrapping. The // WebAssembly offsets are added as unsigned without wrapping. The
// isLegalAddressingMode gives us no way to determine if wrapping could be // isLegalAddressingMode gives us no way to determine if wrapping could be
// happening, so we approximate this by accepting only non-negative offsets. // happening, so we approximate this by accepting only non-negative offsets.
if (AM.BaseOffs < 0) return false; if (AM.BaseOffs < 0)
return false;
// WebAssembly has no scale register operands. // WebAssembly has no scale register operands.
if (AM.Scale != 0) return false; if (AM.Scale != 0)
return false;
// Everything else is legal. // Everything else is legal.
return true; return true;
@ -448,7 +428,8 @@ bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
// for the kinds of things that LLVM uses this for (merging adjacent stores // for the kinds of things that LLVM uses this for (merging adjacent stores
// of constants, etc.), WebAssembly implementations will either want the // of constants, etc.), WebAssembly implementations will either want the
// unaligned access or they'll split anyway. // unaligned access or they'll split anyway.
if (Fast) *Fast = true; if (Fast)
*Fast = true;
return true; return true;
} }
@ -535,8 +516,9 @@ static bool CallingConvSupported(CallingConv::ID CallConv) {
CallConv == CallingConv::CXX_FAST_TLS; CallConv == CallingConv::CXX_FAST_TLS;
} }
SDValue WebAssemblyTargetLowering::LowerCall( SDValue
CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const { WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const {
SelectionDAG &DAG = CLI.DAG; SelectionDAG &DAG = CLI.DAG;
SDLoc DL = CLI.DL; SDLoc DL = CLI.DL;
SDValue Chain = CLI.Chain; SDValue Chain = CLI.Chain;
@ -638,9 +620,9 @@ SDValue WebAssemblyTargetLowering::LowerCall(
FINode = DAG.getFrameIndex(FI, getPointerTy(Layout)); FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode, SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
DAG.getConstant(Offset, DL, PtrVT)); DAG.getConstant(Offset, DL, PtrVT));
Chains.push_back(DAG.getStore( Chains.push_back(
Chain, DL, Arg, Add, DAG.getStore(Chain, DL, Arg, Add,
MachinePointerInfo::getFixedStack(MF, FI, Offset), 0)); MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
} }
if (!Chains.empty()) if (!Chains.empty())
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains); Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
@ -658,7 +640,8 @@ SDValue WebAssemblyTargetLowering::LowerCall(
Ops.append(OutVals.begin(), Ops.append(OutVals.begin(),
IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end()); IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
// Add a pointer to the vararg buffer. // Add a pointer to the vararg buffer.
if (IsVarArg) Ops.push_back(FINode); if (IsVarArg)
Ops.push_back(FINode);
SmallVector<EVT, 8> InTys; SmallVector<EVT, 8> InTys;
for (const auto &In : Ins) { for (const auto &In : Ins) {
@ -752,11 +735,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments"); fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
// Ignore In.getOrigAlign() because all our arguments are passed in // Ignore In.getOrigAlign() because all our arguments are passed in
// registers. // registers.
InVals.push_back( InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
In.Used DAG.getTargetConstant(InVals.size(),
? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT, DL, MVT::i32))
DAG.getTargetConstant(InVals.size(), DL, MVT::i32)) : DAG.getUNDEF(In.VT));
: DAG.getUNDEF(In.VT));
// Record the number and types of arguments. // Record the number and types of arguments.
MFI->addParam(In.VT); MFI->addParam(In.VT);
@ -794,34 +776,34 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const { SelectionDAG &DAG) const {
SDLoc DL(Op); SDLoc DL(Op);
switch (Op.getOpcode()) { switch (Op.getOpcode()) {
default: default:
llvm_unreachable("unimplemented operation lowering"); llvm_unreachable("unimplemented operation lowering");
return SDValue(); return SDValue();
case ISD::FrameIndex: case ISD::FrameIndex:
return LowerFrameIndex(Op, DAG); return LowerFrameIndex(Op, DAG);
case ISD::GlobalAddress: case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG); return LowerGlobalAddress(Op, DAG);
case ISD::ExternalSymbol: case ISD::ExternalSymbol:
return LowerExternalSymbol(Op, DAG); return LowerExternalSymbol(Op, DAG);
case ISD::JumpTable: case ISD::JumpTable:
return LowerJumpTable(Op, DAG); return LowerJumpTable(Op, DAG);
case ISD::BR_JT: case ISD::BR_JT:
return LowerBR_JT(Op, DAG); return LowerBR_JT(Op, DAG);
case ISD::VASTART: case ISD::VASTART:
return LowerVASTART(Op, DAG); return LowerVASTART(Op, DAG);
case ISD::BlockAddress: case ISD::BlockAddress:
case ISD::BRIND: case ISD::BRIND:
fail(DL, DAG, "WebAssembly hasn't implemented computed gotos"); fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
return SDValue(); return SDValue();
case ISD::RETURNADDR: // Probably nothing meaningful can be returned here. case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address"); fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
return SDValue(); return SDValue();
case ISD::FRAMEADDR: case ISD::FRAMEADDR:
return LowerFRAMEADDR(Op, DAG); return LowerFRAMEADDR(Op, DAG);
case ISD::CopyToReg: case ISD::CopyToReg:
return LowerCopyToReg(Op, DAG); return LowerCopyToReg(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN: case ISD::INTRINSIC_WO_CHAIN:
return LowerINTRINSIC_WO_CHAIN(Op, DAG); return LowerINTRINSIC_WO_CHAIN(Op, DAG);
} }
} }
@ -838,16 +820,15 @@ SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
SDLoc DL(Op); SDLoc DL(Op);
unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg(); unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
EVT VT = Src.getValueType(); EVT VT = Src.getValueType();
SDValue Copy( SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32 : WebAssembly::COPY_I64,
: WebAssembly::COPY_I64, DL, VT, Src),
DL, VT, Src), 0);
0);
return Op.getNode()->getNumValues() == 1 return Op.getNode()->getNumValues() == 1
? DAG.getCopyToReg(Chain, DL, Reg, Copy) ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
: DAG.getCopyToReg(Chain, DL, Reg, Copy, Op.getNumOperands() == 4 : DAG.getCopyToReg(Chain, DL, Reg, Copy,
? Op.getOperand(3) Op.getNumOperands() == 4 ? Op.getOperand(3)
: SDValue()); : SDValue());
} }
return SDValue(); return SDValue();
} }
@ -887,8 +868,9 @@ SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset())); DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
} }
SDValue WebAssemblyTargetLowering::LowerExternalSymbol( SDValue
SDValue Op, SelectionDAG &DAG) const { WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op); SDLoc DL(Op);
const auto *ES = cast<ExternalSymbolSDNode>(Op); const auto *ES = cast<ExternalSymbolSDNode>(Op);
EVT VT = Op.getValueType(); EVT VT = Op.getValueType();
@ -899,9 +881,10 @@ SDValue WebAssemblyTargetLowering::LowerExternalSymbol(
// we don't know anything about the symbol other than its name, because all // we don't know anything about the symbol other than its name, because all
// external symbols used in target-independent SelectionDAG code are for // external symbols used in target-independent SelectionDAG code are for
// functions. // functions.
return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT, return DAG.getNode(
DAG.getTargetExternalSymbol(ES->getSymbol(), VT, WebAssemblyISD::Wrapper, DL, VT,
WebAssemblyII::MO_SYMBOL_FUNCTION)); DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
WebAssemblyII::MO_SYMBOL_FUNCTION));
} }
SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op, SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
@ -930,7 +913,8 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs; const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
// Add an operand for each case. // Add an operand for each case.
for (auto MBB : MBBs) Ops.push_back(DAG.getBasicBlock(MBB)); for (auto MBB : MBBs)
Ops.push_back(DAG.getBasicBlock(MBB));
// TODO: For now, we just pick something arbitrary for a default case for now. // TODO: For now, we just pick something arbitrary for a default case for now.
// We really want to sniff out the guard and put in the real default case (and // We really want to sniff out the guard and put in the real default case (and

View File

@ -29,17 +29,17 @@ enum NodeType : unsigned {
#undef HANDLE_NODETYPE #undef HANDLE_NODETYPE
}; };
} // end namespace WebAssemblyISD } // end namespace WebAssemblyISD
class WebAssemblySubtarget; class WebAssemblySubtarget;
class WebAssemblyTargetMachine; class WebAssemblyTargetMachine;
class WebAssemblyTargetLowering final : public TargetLowering { class WebAssemblyTargetLowering final : public TargetLowering {
public: public:
WebAssemblyTargetLowering(const TargetMachine &TM, WebAssemblyTargetLowering(const TargetMachine &TM,
const WebAssemblySubtarget &STI); const WebAssemblySubtarget &STI);
private: private:
/// Keep a pointer to the WebAssemblySubtarget around so that we can make the /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
/// right decision when generating code for different targets. /// right decision when generating code for different targets.
const WebAssemblySubtarget *Subtarget; const WebAssemblySubtarget *Subtarget;
@ -53,9 +53,9 @@ class WebAssemblyTargetLowering final : public TargetLowering {
EmitInstrWithCustomInserter(MachineInstr &MI, EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override; MachineBasicBlock *MBB) const override;
const char *getTargetNodeName(unsigned Opcode) const override; const char *getTargetNodeName(unsigned Opcode) const override;
std::pair<unsigned, const TargetRegisterClass *> getRegForInlineAsmConstraint( std::pair<unsigned, const TargetRegisterClass *>
const TargetRegisterInfo *TRI, StringRef Constraint, getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
MVT VT) const override; StringRef Constraint, MVT VT) const override;
bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override; bool isCheapToSpeculateCtlz() const override;
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
@ -103,8 +103,8 @@ class WebAssemblyTargetLowering final : public TargetLowering {
namespace WebAssembly { namespace WebAssembly {
FastISel *createFastISel(FunctionLoweringInfo &funcInfo, FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo); const TargetLibraryInfo *libInfo);
} // end namespace WebAssembly } // end namespace WebAssembly
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -77,10 +77,8 @@ void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addReg(SrcReg, KillSrc ? RegState::Kill : 0); .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
} }
MachineInstr * MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(
WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {
unsigned OpIdx1,
unsigned OpIdx2) const {
// If the operands are stackified, we can't reorder them. // If the operands are stackified, we can't reorder them.
WebAssemblyFunctionInfo &MFI = WebAssemblyFunctionInfo &MFI =
*MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>(); *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
@ -165,12 +163,9 @@ unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
return Count; return Count;
} }
unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB, unsigned WebAssemblyInstrInfo::insertBranch(
MachineBasicBlock *TBB, MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded) const {
assert(!BytesAdded && "code size not handled"); assert(!BytesAdded && "code size not handled");
if (Cond.empty()) { if (Cond.empty()) {

View File

@ -78,30 +78,102 @@ bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
MachineInstr *Def = MRI.getVRegDef(Cond); MachineInstr *Def = MRI.getVRegDef(Cond);
switch (Def->getOpcode()) { switch (Def->getOpcode()) {
using namespace WebAssembly; using namespace WebAssembly;
case EQ_I32: Def->setDesc(TII.get(NE_I32)); Inverted = true; break; case EQ_I32:
case NE_I32: Def->setDesc(TII.get(EQ_I32)); Inverted = true; break; Def->setDesc(TII.get(NE_I32));
case GT_S_I32: Def->setDesc(TII.get(LE_S_I32)); Inverted = true; break; Inverted = true;
case GE_S_I32: Def->setDesc(TII.get(LT_S_I32)); Inverted = true; break; break;
case LT_S_I32: Def->setDesc(TII.get(GE_S_I32)); Inverted = true; break; case NE_I32:
case LE_S_I32: Def->setDesc(TII.get(GT_S_I32)); Inverted = true; break; Def->setDesc(TII.get(EQ_I32));
case GT_U_I32: Def->setDesc(TII.get(LE_U_I32)); Inverted = true; break; Inverted = true;
case GE_U_I32: Def->setDesc(TII.get(LT_U_I32)); Inverted = true; break; break;
case LT_U_I32: Def->setDesc(TII.get(GE_U_I32)); Inverted = true; break; case GT_S_I32:
case LE_U_I32: Def->setDesc(TII.get(GT_U_I32)); Inverted = true; break; Def->setDesc(TII.get(LE_S_I32));
case EQ_I64: Def->setDesc(TII.get(NE_I64)); Inverted = true; break; Inverted = true;
case NE_I64: Def->setDesc(TII.get(EQ_I64)); Inverted = true; break; break;
case GT_S_I64: Def->setDesc(TII.get(LE_S_I64)); Inverted = true; break; case GE_S_I32:
case GE_S_I64: Def->setDesc(TII.get(LT_S_I64)); Inverted = true; break; Def->setDesc(TII.get(LT_S_I32));
case LT_S_I64: Def->setDesc(TII.get(GE_S_I64)); Inverted = true; break; Inverted = true;
case LE_S_I64: Def->setDesc(TII.get(GT_S_I64)); Inverted = true; break; break;
case GT_U_I64: Def->setDesc(TII.get(LE_U_I64)); Inverted = true; break; case LT_S_I32:
case GE_U_I64: Def->setDesc(TII.get(LT_U_I64)); Inverted = true; break; Def->setDesc(TII.get(GE_S_I32));
case LT_U_I64: Def->setDesc(TII.get(GE_U_I64)); Inverted = true; break; Inverted = true;
case LE_U_I64: Def->setDesc(TII.get(GT_U_I64)); Inverted = true; break; break;
case EQ_F32: Def->setDesc(TII.get(NE_F32)); Inverted = true; break; case LE_S_I32:
case NE_F32: Def->setDesc(TII.get(EQ_F32)); Inverted = true; break; Def->setDesc(TII.get(GT_S_I32));
case EQ_F64: Def->setDesc(TII.get(NE_F64)); Inverted = true; break; Inverted = true;
case NE_F64: Def->setDesc(TII.get(EQ_F64)); Inverted = true; break; break;
case GT_U_I32:
Def->setDesc(TII.get(LE_U_I32));
Inverted = true;
break;
case GE_U_I32:
Def->setDesc(TII.get(LT_U_I32));
Inverted = true;
break;
case LT_U_I32:
Def->setDesc(TII.get(GE_U_I32));
Inverted = true;
break;
case LE_U_I32:
Def->setDesc(TII.get(GT_U_I32));
Inverted = true;
break;
case EQ_I64:
Def->setDesc(TII.get(NE_I64));
Inverted = true;
break;
case NE_I64:
Def->setDesc(TII.get(EQ_I64));
Inverted = true;
break;
case GT_S_I64:
Def->setDesc(TII.get(LE_S_I64));
Inverted = true;
break;
case GE_S_I64:
Def->setDesc(TII.get(LT_S_I64));
Inverted = true;
break;
case LT_S_I64:
Def->setDesc(TII.get(GE_S_I64));
Inverted = true;
break;
case LE_S_I64:
Def->setDesc(TII.get(GT_S_I64));
Inverted = true;
break;
case GT_U_I64:
Def->setDesc(TII.get(LE_U_I64));
Inverted = true;
break;
case GE_U_I64:
Def->setDesc(TII.get(LT_U_I64));
Inverted = true;
break;
case LT_U_I64:
Def->setDesc(TII.get(GE_U_I64));
Inverted = true;
break;
case LE_U_I64:
Def->setDesc(TII.get(GT_U_I64));
Inverted = true;
break;
case EQ_F32:
Def->setDesc(TII.get(NE_F32));
Inverted = true;
break;
case NE_F32:
Def->setDesc(TII.get(EQ_F32));
Inverted = true;
break;
case EQ_F64:
Def->setDesc(TII.get(NE_F64));
Inverted = true;
break;
case NE_F64:
Def->setDesc(TII.get(EQ_F64));
Inverted = true;
break;
case EQZ_I32: { case EQZ_I32: {
// Invert an eqz by replacing it with its operand. // Invert an eqz by replacing it with its operand.
Cond = Def->getOperand(1).getReg(); Cond = Def->getOperand(1).getReg();
@ -109,7 +181,8 @@ bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
Inverted = true; Inverted = true;
break; break;
} }
default: break; default:
break;
} }
} }

View File

@ -18,15 +18,15 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "WebAssembly.h" #include "WebAssembly.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
using namespace llvm; using namespace llvm;
#define DEBUG_TYPE "wasm-lower-global-dtors" #define DEBUG_TYPE "wasm-lower-global-dtors"
@ -77,18 +77,20 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
// Collect the contents of @llvm.global_dtors, collated by priority and // Collect the contents of @llvm.global_dtors, collated by priority and
// associated symbol. // associated symbol.
std::map<uint16_t, MapVector<Constant *, std::vector<Constant *> > > DtorFuncs; std::map<uint16_t, MapVector<Constant *, std::vector<Constant *>>> DtorFuncs;
for (Value *O : InitList->operands()) { for (Value *O : InitList->operands()) {
ConstantStruct *CS = dyn_cast<ConstantStruct>(O); ConstantStruct *CS = dyn_cast<ConstantStruct>(O);
if (!CS) continue; // Malformed. if (!CS)
continue; // Malformed.
ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
if (!Priority) continue; // Malformed. if (!Priority)
continue; // Malformed.
uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX); uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX);
Constant *DtorFunc = CS->getOperand(1); Constant *DtorFunc = CS->getOperand(1);
if (DtorFunc->isNullValue()) if (DtorFunc->isNullValue())
break; // Found a null terminator, skip the rest. break; // Found a null terminator, skip the rest.
Constant *Associated = CS->getOperand(2); Constant *Associated = CS->getOperand(2);
Associated = cast<Constant>(Associated->stripPointerCastsNoFollowAliases()); Associated = cast<Constant>(Associated->stripPointerCastsNoFollowAliases());
@ -101,31 +103,23 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
// extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d); // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
PointerType *VoidStar = Type::getInt8PtrTy(C); PointerType *VoidStar = Type::getInt8PtrTy(C);
Type *AtExitFuncArgs[] = { VoidStar }; Type *AtExitFuncArgs[] = {VoidStar};
FunctionType *AtExitFuncTy = FunctionType::get( FunctionType *AtExitFuncTy =
Type::getVoidTy(C), FunctionType::get(Type::getVoidTy(C), AtExitFuncArgs,
AtExitFuncArgs, /*isVarArg=*/false);
/*isVarArg=*/false);
Type *AtExitArgs[] = { Type *AtExitArgs[] = {PointerType::get(AtExitFuncTy, 0), VoidStar, VoidStar};
PointerType::get(AtExitFuncTy, 0), FunctionType *AtExitTy = FunctionType::get(Type::getInt32Ty(C), AtExitArgs,
VoidStar, /*isVarArg=*/false);
VoidStar
};
FunctionType *AtExitTy = FunctionType::get(
Type::getInt32Ty(C),
AtExitArgs,
/*isVarArg=*/false);
Constant *AtExit = M.getOrInsertFunction("__cxa_atexit", AtExitTy); Constant *AtExit = M.getOrInsertFunction("__cxa_atexit", AtExitTy);
// Declare __dso_local. // Declare __dso_local.
Constant *DsoHandle = M.getNamedValue("__dso_handle"); Constant *DsoHandle = M.getNamedValue("__dso_handle");
if (!DsoHandle) { if (!DsoHandle) {
Type *DsoHandleTy = Type::getInt8Ty(C); Type *DsoHandleTy = Type::getInt8Ty(C);
GlobalVariable *Handle = GlobalVariable *Handle = new GlobalVariable(
new GlobalVariable(M, DsoHandleTy, /*isConstant=*/true, M, DsoHandleTy, /*isConstant=*/true,
GlobalVariable::ExternalWeakLinkage, GlobalVariable::ExternalWeakLinkage, nullptr, "__dso_handle");
nullptr, "__dso_handle");
Handle->setVisibility(GlobalVariable::HiddenVisibility); Handle->setVisibility(GlobalVariable::HiddenVisibility);
DsoHandle = Handle; DsoHandle = Handle;
} }
@ -139,13 +133,13 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
Constant *Associated = AssociatedAndMore.first; Constant *Associated = AssociatedAndMore.first;
Function *CallDtors = Function::Create( Function *CallDtors = Function::Create(
AtExitFuncTy, Function::PrivateLinkage, AtExitFuncTy, Function::PrivateLinkage,
"call_dtors" + "call_dtors" +
(Priority != UINT16_MAX ? (Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
(Twine(".") + Twine(Priority)) : Twine()) + : Twine()) +
(!Associated->isNullValue() ? (!Associated->isNullValue() ? (Twine(".") + Associated->getName())
(Twine(".") + Associated->getName()) : Twine()), : Twine()),
&M); &M);
BasicBlock *BB = BasicBlock::Create(C, "body", CallDtors); BasicBlock *BB = BasicBlock::Create(C, "body", CallDtors);
for (auto Dtor : AssociatedAndMore.second) for (auto Dtor : AssociatedAndMore.second)
@ -155,29 +149,29 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
FunctionType *VoidVoid = FunctionType::get(Type::getVoidTy(C), FunctionType *VoidVoid = FunctionType::get(Type::getVoidTy(C),
/*isVarArg=*/false); /*isVarArg=*/false);
Function *RegisterCallDtors = Function::Create( Function *RegisterCallDtors = Function::Create(
VoidVoid, Function::PrivateLinkage, VoidVoid, Function::PrivateLinkage,
"register_call_dtors" + "register_call_dtors" +
(Priority != UINT16_MAX ? (Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
(Twine(".") + Twine(Priority)) : Twine()) + : Twine()) +
(!Associated->isNullValue() ? (!Associated->isNullValue() ? (Twine(".") + Associated->getName())
(Twine(".") + Associated->getName()) : Twine()), : Twine()),
&M); &M);
BasicBlock *EntryBB = BasicBlock::Create(C, "entry", RegisterCallDtors); BasicBlock *EntryBB = BasicBlock::Create(C, "entry", RegisterCallDtors);
BasicBlock *FailBB = BasicBlock::Create(C, "fail", RegisterCallDtors); BasicBlock *FailBB = BasicBlock::Create(C, "fail", RegisterCallDtors);
BasicBlock *RetBB = BasicBlock::Create(C, "return", RegisterCallDtors); BasicBlock *RetBB = BasicBlock::Create(C, "return", RegisterCallDtors);
Value *Null = ConstantPointerNull::get(VoidStar); Value *Null = ConstantPointerNull::get(VoidStar);
Value *Args[] = { CallDtors, Null, DsoHandle }; Value *Args[] = {CallDtors, Null, DsoHandle};
Value *Res = CallInst::Create(AtExit, Args, "call", EntryBB); Value *Res = CallInst::Create(AtExit, Args, "call", EntryBB);
Value *Cmp = new ICmpInst(*EntryBB, ICmpInst::ICMP_NE, Res, Value *Cmp = new ICmpInst(*EntryBB, ICmpInst::ICMP_NE, Res,
Constant::getNullValue(Res->getType())); Constant::getNullValue(Res->getType()));
BranchInst::Create(FailBB, RetBB, Cmp, EntryBB); BranchInst::Create(FailBB, RetBB, Cmp, EntryBB);
// If `__cxa_atexit` hits out-of-memory, trap, so that we don't misbehave. // If `__cxa_atexit` hits out-of-memory, trap, so that we don't misbehave.
// This should be very rare, because if the process is running out of memory // This should be very rare, because if the process is running out of
// before main has even started, something is wrong. // memory before main has even started, something is wrong.
CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), "",
"", FailBB); FailBB);
new UnreachableInst(C, FailBB); new UnreachableInst(C, FailBB);
ReturnInst::Create(C, RetBB); ReturnInst::Create(C, RetBB);

View File

@ -32,11 +32,11 @@ using namespace llvm;
// This disables the removal of registers when lowering into MC, as required // This disables the removal of registers when lowering into MC, as required
// by some current tests. // by some current tests.
static cl::opt<bool> WasmKeepRegisters( static cl::opt<bool>
"wasm-keep-registers", cl::Hidden, WasmKeepRegisters("wasm-keep-registers", cl::Hidden,
cl::desc("WebAssembly: output stack registers in" cl::desc("WebAssembly: output stack registers in"
" instruction output for test purposes only."), " instruction output for test purposes only."),
cl::init(false)); cl::init(false));
static unsigned regInstructionToStackInstruction(unsigned OpCode); static unsigned regInstructionToStackInstruction(unsigned OpCode);
static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI); static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
@ -54,10 +54,9 @@ WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
SmallVector<wasm::ValType, 4> Returns; SmallVector<wasm::ValType, 4> Returns;
SmallVector<wasm::ValType, 4> Params; SmallVector<wasm::ValType, 4> Params;
wasm::ValType iPTR = wasm::ValType iPTR = MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() ? ? wasm::ValType::I64
wasm::ValType::I64 : : wasm::ValType::I32;
wasm::ValType::I32;
SmallVector<MVT, 4> ResultMVTs; SmallVector<MVT, 4> ResultMVTs;
ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs); ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs);
@ -122,9 +121,9 @@ MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
bool IsFunc, bool IsFunc,
bool IsGlob) const { bool IsGlob) const {
MCSymbolRefExpr::VariantKind VK = MCSymbolRefExpr::VariantKind VK =
IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION : IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION
IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL : IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
: MCSymbolRefExpr::VK_None; : MCSymbolRefExpr::VK_None;
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx); const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
@ -238,7 +237,8 @@ void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
// variable or a function. // variable or a function.
assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 && assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 &&
"WebAssembly uses only symbol flags on ExternalSymbols"); "WebAssembly uses only symbol flags on ExternalSymbols");
MCOp = LowerSymbolOperand(GetExternalSymbolSymbol(MO), /*Offset=*/0, MCOp = LowerSymbolOperand(
GetExternalSymbolSymbol(MO), /*Offset=*/0,
(MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_FUNCTION) != 0, (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_FUNCTION) != 0,
(MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0); (MO.getTargetFlags() & WebAssemblyII::MO_SYMBOL_GLOBAL) != 0);
break; break;
@ -295,7 +295,7 @@ static unsigned regInstructionToStackInstruction(unsigned OpCode) {
switch (OpCode) { switch (OpCode) {
default: default:
llvm_unreachable( llvm_unreachable(
"unknown WebAssembly instruction in WebAssemblyMCInstLower pass"); "unknown WebAssembly instruction in WebAssemblyMCInstLower pass");
#include "WebAssemblyGenStackifier.inc" #include "WebAssemblyGenStackifier.inc"
} }
} }

View File

@ -33,8 +33,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyMCInstLower {
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
bool IsFunc, bool IsGlob) const; bool IsGlob) const;
public: public:
WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer) WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)

View File

@ -50,7 +50,7 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
// overaligned values on the user stack. // overaligned values on the user stack.
unsigned BasePtrVreg = -1U; unsigned BasePtrVreg = -1U;
public: public:
explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {} explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {}
~WebAssemblyFunctionInfo() override; ~WebAssemblyFunctionInfo() override;
@ -60,7 +60,10 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
void addResult(MVT VT) { Results.push_back(VT); } void addResult(MVT VT) { Results.push_back(VT); }
const std::vector<MVT> &getResults() const { return Results; } const std::vector<MVT> &getResults() const { return Results; }
void clearParamsAndResults() { Params.clear(); Results.clear(); } void clearParamsAndResults() {
Params.clear();
Results.clear();
}
void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
void setLocal(size_t i, MVT VT) { Locals[i] = VT; } void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
@ -115,8 +118,8 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
} }
}; };
void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
Type *Ty, SmallVectorImpl<MVT> &ValueVTs); SmallVectorImpl<MVT> &ValueVTs);
void ComputeSignatureVTs(const Function &F, const TargetMachine &TM, void ComputeSignatureVTs(const Function &F, const TargetMachine &TM,
SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Params,

View File

@ -65,7 +65,8 @@ FunctionPass *llvm::createWebAssemblyOptimizeLiveIntervals() {
return new WebAssemblyOptimizeLiveIntervals(); return new WebAssemblyOptimizeLiveIntervals();
} }
bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF) { bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n" LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n"
"********** Function: " "********** Function: "
<< MF.getName() << '\n'); << MF.getName() << '\n');
@ -76,11 +77,10 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF)
// We don't preserve SSA form. // We don't preserve SSA form.
MRI.leaveSSA(); MRI.leaveSSA();
assert(MRI.tracksLiveness() && assert(MRI.tracksLiveness() && "OptimizeLiveIntervals expects liveness");
"OptimizeLiveIntervals expects liveness");
// Split multiple-VN LiveIntervals into multiple LiveIntervals. // Split multiple-VN LiveIntervals into multiple LiveIntervals.
SmallVector<LiveInterval*, 4> SplitLIs; SmallVector<LiveInterval *, 4> SplitLIs;
for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) { for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
unsigned Reg = TargetRegisterInfo::index2VirtReg(i); unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
if (MRI.reg_nodbg_empty(Reg)) if (MRI.reg_nodbg_empty(Reg))
@ -94,7 +94,7 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF)
// instructions to satisfy LiveIntervals' requirement that all uses be // instructions to satisfy LiveIntervals' requirement that all uses be
// dominated by defs. Now that LiveIntervals has computed which of these // dominated by defs. Now that LiveIntervals has computed which of these
// defs are actually needed and which are dead, remove the dead ones. // defs are actually needed and which are dead, remove the dead ones.
for (auto MII = MF.begin()->begin(), MIE = MF.begin()->end(); MII != MIE; ) { for (auto MII = MF.begin()->begin(), MIE = MF.begin()->end(); MII != MIE;) {
MachineInstr *MI = &*MII++; MachineInstr *MI = &*MII++;
if (MI->isImplicitDef() && MI->getOperand(0).isDead()) { if (MI->isImplicitDef() && MI->getOperand(0).isDead()) {
LiveInterval &LI = LIS.getInterval(MI->getOperand(0).getReg()); LiveInterval &LI = LIS.getInterval(MI->getOperand(0).getReg());

View File

@ -70,7 +70,8 @@ static bool HasArgumentDef(unsigned Reg, const MachineRegisterInfo &MRI) {
return false; return false;
} }
bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(MachineFunction &MF) { bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(
MachineFunction &MF) {
LLVM_DEBUG({ LLVM_DEBUG({
dbgs() << "********** Prepare For LiveIntervals **********\n" dbgs() << "********** Prepare For LiveIntervals **********\n"
<< "********** Function: " << MF.getName() << '\n'; << "********** Function: " << MF.getName() << '\n';
@ -112,7 +113,7 @@ bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(MachineFunction &M
// Move ARGUMENT_* instructions to the top of the entry block, so that their // Move ARGUMENT_* instructions to the top of the entry block, so that their
// liveness reflects the fact that these really are live-in values. // liveness reflects the fact that these really are live-in values.
for (auto MII = Entry.begin(), MIE = Entry.end(); MII != MIE; ) { for (auto MII = Entry.begin(), MIE = Entry.end(); MII != MIE;) {
MachineInstr &MI = *MII++; MachineInstr &MI = *MII++;
if (WebAssembly::isArgument(MI)) { if (WebAssembly::isArgument(MI)) {
MI.removeFromParent(); MI.removeFromParent();

View File

@ -100,8 +100,7 @@ static void ConvertImplicitDefToConstZero(MachineInstr *MI,
MachineFunction &MF) { MachineFunction &MF) {
assert(MI->getOpcode() == TargetOpcode::IMPLICIT_DEF); assert(MI->getOpcode() == TargetOpcode::IMPLICIT_DEF);
const auto *RegClass = const auto *RegClass = MRI.getRegClass(MI->getOperand(0).getReg());
MRI.getRegClass(MI->getOperand(0).getReg());
if (RegClass == &WebAssembly::I32RegClass) { if (RegClass == &WebAssembly::I32RegClass) {
MI->setDesc(TII->get(WebAssembly::CONST_I32)); MI->setDesc(TII->get(WebAssembly::CONST_I32));
MI->addOperand(MachineOperand::CreateImm(0)); MI->addOperand(MachineOperand::CreateImm(0));
@ -187,14 +186,22 @@ static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
} }
} else if (MI.hasOrderedMemoryRef()) { } else if (MI.hasOrderedMemoryRef()) {
switch (MI.getOpcode()) { switch (MI.getOpcode()) {
case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64: case WebAssembly::DIV_S_I32:
case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64: case WebAssembly::DIV_S_I64:
case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64: case WebAssembly::REM_S_I32:
case WebAssembly::REM_U_I32: case WebAssembly::REM_U_I64: case WebAssembly::REM_S_I64:
case WebAssembly::I32_TRUNC_S_F32: case WebAssembly::I64_TRUNC_S_F32: case WebAssembly::DIV_U_I32:
case WebAssembly::I32_TRUNC_S_F64: case WebAssembly::I64_TRUNC_S_F64: case WebAssembly::DIV_U_I64:
case WebAssembly::I32_TRUNC_U_F32: case WebAssembly::I64_TRUNC_U_F32: case WebAssembly::REM_U_I32:
case WebAssembly::I32_TRUNC_U_F64: case WebAssembly::I64_TRUNC_U_F64: case WebAssembly::REM_U_I64:
case WebAssembly::I32_TRUNC_S_F32:
case WebAssembly::I64_TRUNC_S_F32:
case WebAssembly::I32_TRUNC_S_F64:
case WebAssembly::I64_TRUNC_S_F64:
case WebAssembly::I32_TRUNC_U_F32:
case WebAssembly::I64_TRUNC_U_F32:
case WebAssembly::I32_TRUNC_U_F64:
case WebAssembly::I64_TRUNC_U_F64:
// These instruction have hasUnmodeledSideEffects() returning true // These instruction have hasUnmodeledSideEffects() returning true
// because they trap on overflow and invalid so they can't be arbitrarily // because they trap on overflow and invalid so they can't be arbitrarily
// moved, however hasOrderedMemoryRef() interprets this plus their lack // moved, however hasOrderedMemoryRef() interprets this plus their lack
@ -214,14 +221,22 @@ static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
// Check for side effects. // Check for side effects.
if (MI.hasUnmodeledSideEffects()) { if (MI.hasUnmodeledSideEffects()) {
switch (MI.getOpcode()) { switch (MI.getOpcode()) {
case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64: case WebAssembly::DIV_S_I32:
case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64: case WebAssembly::DIV_S_I64:
case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64: case WebAssembly::REM_S_I32:
case WebAssembly::REM_U_I32: case WebAssembly::REM_U_I64: case WebAssembly::REM_S_I64:
case WebAssembly::I32_TRUNC_S_F32: case WebAssembly::I64_TRUNC_S_F32: case WebAssembly::DIV_U_I32:
case WebAssembly::I32_TRUNC_S_F64: case WebAssembly::I64_TRUNC_S_F64: case WebAssembly::DIV_U_I64:
case WebAssembly::I32_TRUNC_U_F32: case WebAssembly::I64_TRUNC_U_F32: case WebAssembly::REM_U_I32:
case WebAssembly::I32_TRUNC_U_F64: case WebAssembly::I64_TRUNC_U_F64: case WebAssembly::REM_U_I64:
case WebAssembly::I32_TRUNC_S_F32:
case WebAssembly::I64_TRUNC_S_F32:
case WebAssembly::I32_TRUNC_S_F64:
case WebAssembly::I64_TRUNC_S_F64:
case WebAssembly::I32_TRUNC_U_F32:
case WebAssembly::I64_TRUNC_U_F32:
case WebAssembly::I32_TRUNC_U_F64:
case WebAssembly::I64_TRUNC_U_F64:
// These instructions have hasUnmodeledSideEffects() returning true // These instructions have hasUnmodeledSideEffects() returning true
// because they trap on overflow and invalid so they can't be arbitrarily // because they trap on overflow and invalid so they can't be arbitrarily
// moved, however in the specific case of register stackifying, it is safe // moved, however in the specific case of register stackifying, it is safe
@ -251,8 +266,7 @@ static bool ShouldRematerialize(const MachineInstr &Def, AliasAnalysis &AA,
// LiveIntervals to handle complex cases. // LiveIntervals to handle complex cases.
static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert, static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert,
const MachineRegisterInfo &MRI, const MachineRegisterInfo &MRI,
const LiveIntervals &LIS) const LiveIntervals &LIS) {
{
// Most registers are in SSA form here so we try a quick MRI query first. // Most registers are in SSA form here so we try a quick MRI query first.
if (MachineInstr *Def = MRI.getUniqueVRegDef(Reg)) if (MachineInstr *Def = MRI.getUniqueVRegDef(Reg))
return Def; return Def;
@ -268,17 +282,16 @@ static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert,
// Test whether Reg, as defined at Def, has exactly one use. This is a // Test whether Reg, as defined at Def, has exactly one use. This is a
// generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals // generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals
// to handle complex cases. // to handle complex cases.
static bool HasOneUse(unsigned Reg, MachineInstr *Def, static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
MachineRegisterInfo &MRI, MachineDominatorTree &MDT, MachineDominatorTree &MDT, LiveIntervals &LIS) {
LiveIntervals &LIS) {
// Most registers are in SSA form here so we try a quick MRI query first. // Most registers are in SSA form here so we try a quick MRI query first.
if (MRI.hasOneUse(Reg)) if (MRI.hasOneUse(Reg))
return true; return true;
bool HasOne = false; bool HasOne = false;
const LiveInterval &LI = LIS.getInterval(Reg); const LiveInterval &LI = LIS.getInterval(Reg);
const VNInfo *DefVNI = LI.getVNInfoAt( const VNInfo *DefVNI =
LIS.getInstructionIndex(*Def).getRegSlot()); LI.getVNInfoAt(LIS.getInstructionIndex(*Def).getRegSlot());
assert(DefVNI); assert(DefVNI);
for (auto &I : MRI.use_nodbg_operands(Reg)) { for (auto &I : MRI.use_nodbg_operands(Reg)) {
const auto &Result = LI.Query(LIS.getInstructionIndex(*I.getParent())); const auto &Result = LI.Query(LIS.getInstructionIndex(*I.getParent()));
@ -447,16 +460,15 @@ static unsigned GetTeeOpcode(const TargetRegisterClass *RC) {
// Shrink LI to its uses, cleaning up LI. // Shrink LI to its uses, cleaning up LI.
static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS) { static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
if (LIS.shrinkToUses(&LI)) { if (LIS.shrinkToUses(&LI)) {
SmallVector<LiveInterval*, 4> SplitLIs; SmallVector<LiveInterval *, 4> SplitLIs;
LIS.splitSeparateComponents(LI, SplitLIs); LIS.splitSeparateComponents(LI, SplitLIs);
} }
} }
/// A single-use def in the same block with no intervening memory or register /// A single-use def in the same block with no intervening memory or register
/// dependencies; move the def down and nest it with the current instruction. /// dependencies; move the def down and nest it with the current instruction.
static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand& Op, static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand &Op,
MachineInstr *Def, MachineInstr *Def, MachineBasicBlock &MBB,
MachineBasicBlock &MBB,
MachineInstr *Insert, LiveIntervals &LIS, MachineInstr *Insert, LiveIntervals &LIS,
WebAssemblyFunctionInfo &MFI, WebAssemblyFunctionInfo &MFI,
MachineRegisterInfo &MRI) { MachineRegisterInfo &MRI) {

View File

@ -22,9 +22,9 @@
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
using namespace llvm; using namespace llvm;

View File

@ -54,8 +54,8 @@ private:
char WebAssemblyReplacePhysRegs::ID = 0; char WebAssemblyReplacePhysRegs::ID = 0;
INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE, INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
"Replace physical registers with virtual registers", "Replace physical registers with virtual registers", false,
false, false) false)
FunctionPass *llvm::createWebAssemblyReplacePhysRegs() { FunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
return new WebAssemblyReplacePhysRegs(); return new WebAssemblyReplacePhysRegs();
@ -86,7 +86,7 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
// Replace explicit uses of the physical register with a virtual register. // Replace explicit uses of the physical register with a virtual register.
const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg); const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
unsigned VReg = WebAssembly::NoRegister; unsigned VReg = WebAssembly::NoRegister;
for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E; ) { for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E;) {
MachineOperand &MO = *I++; MachineOperand &MO = *I++;
if (!MO.isImplicit()) { if (!MO.isImplicit()) {
if (VReg == WebAssembly::NoRegister) if (VReg == WebAssembly::NoRegister)

View File

@ -88,7 +88,6 @@ enum RuntimeLibcallSignature {
unsupported unsupported
}; };
struct RuntimeLibcallSignatureTable { struct RuntimeLibcallSignatureTable {
std::vector<RuntimeLibcallSignature> Table; std::vector<RuntimeLibcallSignature> Table;
@ -486,8 +485,6 @@ struct StaticLibcallNameMap {
} // end anonymous namespace } // end anonymous namespace
void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, void llvm::GetSignature(const WebAssemblySubtarget &Subtarget,
RTLIB::Libcall LC, SmallVectorImpl<wasm::ValType> &Rets, RTLIB::Libcall LC, SmallVectorImpl<wasm::ValType> &Rets,
SmallVectorImpl<wasm::ValType> &Params) { SmallVectorImpl<wasm::ValType> &Params) {
@ -497,7 +494,7 @@ void llvm::GetSignature(const WebAssemblySubtarget &Subtarget,
wasm::ValType iPTR = wasm::ValType iPTR =
Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32; Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
auto& Table = RuntimeLibcallSignatures->Table; auto &Table = RuntimeLibcallSignatures->Table;
switch (Table[LC]) { switch (Table[LC]) {
case func: case func:
break; break;
@ -837,7 +834,7 @@ static ManagedStatic<StaticLibcallNameMap> LibcallNameMap;
void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, const char *Name, void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, const char *Name,
SmallVectorImpl<wasm::ValType> &Rets, SmallVectorImpl<wasm::ValType> &Rets,
SmallVectorImpl<wasm::ValType> &Params) { SmallVectorImpl<wasm::ValType> &Params) {
auto& Map = LibcallNameMap->Map; auto &Map = LibcallNameMap->Map;
auto val = Map.find(Name); auto val = Map.find(Name);
assert(val != Map.end() && "unexpected runtime library name"); assert(val != Map.end() && "unexpected runtime library name");
return GetSignature(Subtarget, val->second, Rets, Params); return GetSignature(Subtarget, val->second, Rets, Params);

View File

@ -60,8 +60,7 @@ static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
assert(MI.hasOneMemOperand() && assert(MI.hasOneMemOperand() &&
"Load and store instructions have exactly one mem operand"); "Load and store instructions have exactly one mem operand");
assert((*MI.memoperands_begin())->getSize() == assert((*MI.memoperands_begin())->getSize() ==
(UINT64_C(1) (UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
<< WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
"Default p2align value should be natural"); "Default p2align value should be natural");
assert(MI.getDesc().OpInfo[OperandNo].OperandType == assert(MI.getDesc().OpInfo[OperandNo].OperandType ==
WebAssembly::OPERAND_P2ALIGN && WebAssembly::OPERAND_P2ALIGN &&
@ -69,8 +68,8 @@ static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment()); uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment());
// WebAssembly does not currently support supernatural alignment. // WebAssembly does not currently support supernatural alignment.
P2Align = std::min( P2Align = std::min(P2Align,
P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode()))); uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
MI.getOperand(OperandNo).setImm(P2Align); MI.getOperand(OperandNo).setImm(P2Align);
} }

View File

@ -91,7 +91,8 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
SmallVector<SlotIndex, 4> Indices; SmallVector<SlotIndex, 4> Indices;
for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end(); I != E;) { for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end();
I != E;) {
MachineOperand &O = *I++; MachineOperand &O = *I++;
MachineInstr *Where = O.getParent(); MachineInstr *Where = O.getParent();
@ -132,9 +133,9 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
// If we replaced all dominated uses, FromReg is now killed at MI. // If we replaced all dominated uses, FromReg is now killed at MI.
if (!FromLI->liveAt(FromIdx.getDeadSlot())) if (!FromLI->liveAt(FromIdx.getDeadSlot()))
MI.addRegisterKilled(FromReg, MI.addRegisterKilled(FromReg, MBB.getParent()
MBB.getParent()->getSubtarget<WebAssemblySubtarget>() ->getSubtarget<WebAssemblySubtarget>()
.getRegisterInfo()); .getRegisterInfo());
} }
return Changed; return Changed;
@ -142,8 +143,7 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI, static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI,
const MachineRegisterInfo &MRI, const MachineRegisterInfo &MRI,
MachineDominatorTree &MDT, MachineDominatorTree &MDT, LiveIntervals &LIS,
LiveIntervals &LIS,
const WebAssemblyTargetLowering &TLI, const WebAssemblyTargetLowering &TLI,
const TargetLibraryInfo &LibInfo) { const TargetLibraryInfo &LibInfo) {
MachineOperand &Op1 = MI.getOperand(1); MachineOperand &Op1 = MI.getOperand(1);

View File

@ -150,7 +150,7 @@ class StripThreadLocal final : public ModulePass {
// pass just converts all GlobalVariables to NotThreadLocal // pass just converts all GlobalVariables to NotThreadLocal
static char ID; static char ID;
public: public:
StripThreadLocal() : ModulePass(ID) {} StripThreadLocal() : ModulePass(ID) {}
bool runOnModule(Module &M) override { bool runOnModule(Module &M) override {
for (auto &GV : M.globals()) for (auto &GV : M.globals())

View File

@ -23,28 +23,22 @@ using namespace object;
namespace { namespace {
static const EnumEntry<unsigned> WasmSymbolTypes[] = { static const EnumEntry<unsigned> WasmSymbolTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SYMBOL_TYPE_##X } #define ENUM_ENTRY(X) \
ENUM_ENTRY(FUNCTION), { #X, wasm::WASM_SYMBOL_TYPE_##X }
ENUM_ENTRY(DATA), ENUM_ENTRY(FUNCTION),
ENUM_ENTRY(GLOBAL), ENUM_ENTRY(DATA),
ENUM_ENTRY(SECTION), ENUM_ENTRY(GLOBAL),
ENUM_ENTRY(SECTION),
#undef ENUM_ENTRY #undef ENUM_ENTRY
}; };
static const EnumEntry<uint32_t> WasmSectionTypes[] = { static const EnumEntry<uint32_t> WasmSectionTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X } #define ENUM_ENTRY(X) \
ENUM_ENTRY(CUSTOM), { #X, wasm::WASM_SEC_##X }
ENUM_ENTRY(TYPE), ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
ENUM_ENTRY(IMPORT), ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EXPORT), ENUM_ENTRY(START),
ENUM_ENTRY(TABLE), ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE), ENUM_ENTRY(DATA),
ENUM_ENTRY(MEMORY),
ENUM_ENTRY(GLOBAL),
ENUM_ENTRY(EXPORT),
ENUM_ENTRY(START),
ENUM_ENTRY(ELEM),
ENUM_ENTRY(CODE),
ENUM_ENTRY(DATA),
#undef ENUM_ENTRY #undef ENUM_ENTRY
}; };
@ -108,7 +102,7 @@ void WasmDumper::printRelocation(const SectionRef &Section,
if (HasAddend) if (HasAddend)
W.printNumber("Addend", WasmReloc.Addend); W.printNumber("Addend", WasmReloc.Addend);
} else { } else {
raw_ostream& OS = W.startLine(); raw_ostream &OS = W.startLine();
OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " "; OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
if (!SymName.empty()) if (!SymName.empty())
OS << SymName; OS << SymName;
@ -169,7 +163,7 @@ void WasmDumper::printSections() {
const wasm::WasmLinkingData &LinkingData = Obj->linkingData(); const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
if (!LinkingData.InitFunctions.empty()) { if (!LinkingData.InitFunctions.empty()) {
ListScope Group(W, "InitFunctions"); ListScope Group(W, "InitFunctions");
for (const wasm::WasmInitFunc &F: LinkingData.InitFunctions) for (const wasm::WasmInitFunc &F : LinkingData.InitFunctions)
W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n"; W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
} }
} }
@ -177,7 +171,7 @@ void WasmDumper::printSections() {
case wasm::WASM_SEC_DATA: { case wasm::WASM_SEC_DATA: {
ListScope Group(W, "Segments"); ListScope Group(W, "Segments");
for (const WasmSegment &Segment : Obj->dataSegments()) { for (const WasmSegment &Segment : Obj->dataSegments()) {
const wasm::WasmDataSegment& Seg = Segment.Data; const wasm::WasmDataSegment &Seg = Segment.Data;
DictScope Group(W, "Segment"); DictScope Group(W, "Segment");
if (!Seg.Name.empty()) if (!Seg.Name.empty())
W.printString("Name", Seg.Name); W.printString("Name", Seg.Name);
@ -219,7 +213,7 @@ void WasmDumper::printSymbol(const SymbolRef &Sym) {
W.printHex("Flags", Symbol.Info.Flags); W.printHex("Flags", Symbol.Info.Flags);
} }
} } // namespace
namespace llvm { namespace llvm {

View File

@ -49,11 +49,13 @@ static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
return L; return L;
} }
std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const WasmSection &WasmSec) { std::unique_ptr<WasmYAML::CustomSection>
WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
std::unique_ptr<WasmYAML::CustomSection> CustomSec; std::unique_ptr<WasmYAML::CustomSection> CustomSec;
if (WasmSec.Name == "name") { if (WasmSec.Name == "name") {
std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>(); std::unique_ptr<WasmYAML::NameSection> NameSec =
for (const llvm::wasm::WasmFunctionName &Func: Obj.debugNames()) { make_unique<WasmYAML::NameSection>();
for (const llvm::wasm::WasmFunctionName &Func : Obj.debugNames()) {
WasmYAML::NameEntry NameEntry; WasmYAML::NameEntry NameEntry;
NameEntry.Name = Func.Name; NameEntry.Name = Func.Name;
NameEntry.Index = Func.Index; NameEntry.Index = Func.Index;
@ -61,7 +63,8 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
} }
CustomSec = std::move(NameSec); CustomSec = std::move(NameSec);
} else if (WasmSec.Name == "linking") { } else if (WasmSec.Name == "linking") {
std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>(); std::unique_ptr<WasmYAML::LinkingSection> LinkingSec =
make_unique<WasmYAML::LinkingSection>();
LinkingSec->Version = Obj.linkingData().Version; LinkingSec->Version = Obj.linkingData().Version;
ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats; ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
@ -70,7 +73,7 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
for (auto &Func : Obj.functions()) { for (auto &Func : Obj.functions()) {
if (Func.Comdat != UINT32_MAX) { if (Func.Comdat != UINT32_MAX) {
LinkingSec->Comdats[Func.Comdat].Entries.emplace_back( LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index}); WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
} }
} }
@ -290,7 +293,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
llvm_unreachable("Unknown section type"); llvm_unreachable("Unknown section type");
break; break;
} }
for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) { for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
WasmYAML::Relocation R; WasmYAML::Relocation R;
R.Type = Reloc.Type; R.Type = Reloc.Type;
R.Index = Reloc.Index; R.Index = Reloc.Index;

View File

@ -127,12 +127,11 @@ public:
OutString.clear(); OutString.clear();
} }
raw_ostream& GetStream() { raw_ostream &GetStream() { return StringStream; }
return StringStream;
}
}; };
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) { int WasmWriter::writeSectionContent(raw_ostream &OS,
WasmYAML::LinkingSection &Section) {
writeStringRef(Section.Name, OS); writeStringRef(Section.Name, OS);
encodeULEB128(Section.Version, OS); encodeULEB128(Section.Version, OS);
@ -218,7 +217,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S
return 0; return 0;
} }
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) { int WasmWriter::writeSectionContent(raw_ostream &OS,
WasmYAML::NameSection &Section) {
writeStringRef(Section.Name, OS); writeStringRef(Section.Name, OS);
if (Section.FunctionNames.size()) { if (Section.FunctionNames.size()) {
writeUint8(OS, wasm::WASM_NAMES_FUNCTION); writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
@ -296,7 +296,7 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
writeLimits(Import.Memory, OS); writeLimits(Import.Memory, OS);
break; break;
case wasm::WASM_EXTERNAL_TABLE: case wasm::WASM_EXTERNAL_TABLE:
writeUint8(OS,Import.TableImport.ElemType); writeUint8(OS, Import.TableImport.ElemType);
writeLimits(Import.TableImport.TableLimits, OS); writeLimits(Import.TableImport.TableLimits, OS);
break; break;
default: default:
@ -428,47 +428,46 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec, int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
uint32_t SectionIndex) { uint32_t SectionIndex) {
switch (Sec.Type) { switch (Sec.Type) {
case wasm::WASM_SEC_CODE: case wasm::WASM_SEC_CODE:
writeStringRef("reloc.CODE", OS); writeStringRef("reloc.CODE", OS);
break; break;
case wasm::WASM_SEC_DATA: case wasm::WASM_SEC_DATA:
writeStringRef("reloc.DATA", OS); writeStringRef("reloc.DATA", OS);
break; break;
case wasm::WASM_SEC_CUSTOM: { case wasm::WASM_SEC_CUSTOM: {
auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec); auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
if (!CustomSection->Name.startswith(".debug_")) { if (!CustomSection->Name.startswith(".debug_")) {
llvm_unreachable("not yet implemented (only for debug sections)"); llvm_unreachable("not yet implemented (only for debug sections)");
return 1;
}
writeStringRef(("reloc." + CustomSection->Name).str(), OS);
break;
}
default:
llvm_unreachable("not yet implemented");
return 1; return 1;
}
writeStringRef(("reloc." + CustomSection->Name).str(), OS);
break;
}
default:
llvm_unreachable("not yet implemented");
return 1;
} }
encodeULEB128(SectionIndex, OS); encodeULEB128(SectionIndex, OS);
encodeULEB128(Sec.Relocations.size(), OS); encodeULEB128(Sec.Relocations.size(), OS);
for (auto Reloc: Sec.Relocations) { for (auto Reloc : Sec.Relocations) {
writeUint8(OS, Reloc.Type); writeUint8(OS, Reloc.Type);
encodeULEB128(Reloc.Offset, OS); encodeULEB128(Reloc.Offset, OS);
encodeULEB128(Reloc.Index, OS); encodeULEB128(Reloc.Index, OS);
switch (Reloc.Type) { switch (Reloc.Type) {
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
encodeULEB128(Reloc.Addend, OS); encodeULEB128(Reloc.Addend, OS);
} }
} }
return 0; return 0;
} }
int WasmWriter::writeWasm(raw_ostream &OS) { int WasmWriter::writeWasm(raw_ostream &OS) {
// Write headers // Write headers
OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));