forked from OSchip/llvm-project
[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:
parent
5d05be84b7
commit
f208f6311b
|
@ -104,8 +104,8 @@ struct WasmFunction {
|
|||
uint32_t Size;
|
||||
uint32_t CodeOffset; // start of Locals and Body
|
||||
StringRef SymbolName; // from the "linking" section
|
||||
StringRef DebugName; // from the "name" section
|
||||
uint32_t Comdat; // from the "comdat info" section
|
||||
StringRef DebugName; // from the "name" section
|
||||
uint32_t Comdat; // from the "comdat info" section
|
||||
};
|
||||
|
||||
struct WasmDataSegment {
|
||||
|
@ -231,21 +231,21 @@ enum class ValType {
|
|||
// Kind codes used in the custom "name" section
|
||||
enum : unsigned {
|
||||
WASM_NAMES_FUNCTION = 0x1,
|
||||
WASM_NAMES_LOCAL = 0x2,
|
||||
WASM_NAMES_LOCAL = 0x2,
|
||||
};
|
||||
|
||||
// Kind codes used in the custom "linking" section
|
||||
enum : unsigned {
|
||||
WASM_SEGMENT_INFO = 0x5,
|
||||
WASM_INIT_FUNCS = 0x6,
|
||||
WASM_COMDAT_INFO = 0x7,
|
||||
WASM_SYMBOL_TABLE = 0x8,
|
||||
WASM_SEGMENT_INFO = 0x5,
|
||||
WASM_INIT_FUNCS = 0x6,
|
||||
WASM_COMDAT_INFO = 0x7,
|
||||
WASM_SYMBOL_TABLE = 0x8,
|
||||
};
|
||||
|
||||
// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
|
||||
enum : unsigned {
|
||||
WASM_COMDAT_DATA = 0x0,
|
||||
WASM_COMDAT_FUNCTION = 0x1,
|
||||
WASM_COMDAT_DATA = 0x0,
|
||||
WASM_COMDAT_FUNCTION = 0x1,
|
||||
};
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
|
||||
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
|
||||
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
|
||||
const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
|
||||
|
||||
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
|
||||
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
|
||||
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
|
||||
const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
|
||||
const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
|
||||
const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
|
||||
const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
|
||||
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
|
||||
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
|
||||
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
|
||||
const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
|
||||
|
||||
#define WASM_RELOC(name, value) name = value,
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
|
||||
#define LLVM_CODEGEN_WASMEHFUNCINFO_H
|
||||
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ class MCAsmInfoWasm : public MCAsmInfo {
|
|||
protected:
|
||||
MCAsmInfoWasm();
|
||||
};
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,7 @@ public:
|
|||
// 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.
|
||||
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: MCSymbol(SymbolKindWasm, Name, isTemporary),
|
||||
ModuleName("env") {}
|
||||
: MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {}
|
||||
static bool classof(const MCSymbol *S) { return S->isWasm(); }
|
||||
|
||||
const MCExpr *getSize() const { return SymbolSize; }
|
||||
|
@ -92,6 +91,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_MC_MCSYMBOLWASM_H
|
||||
|
|
|
@ -51,6 +51,6 @@ std::unique_ptr<MCObjectWriter>
|
|||
createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#define LLVM_OBJECT_WASM_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Wasm.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
|
@ -98,9 +98,9 @@ public:
|
|||
struct WasmSection {
|
||||
WasmSection() = default;
|
||||
|
||||
uint32_t Type = 0; // Section type (See below)
|
||||
uint32_t Offset = 0; // Offset with in the file
|
||||
StringRef Name; // Section name (User-defined sections only)
|
||||
uint32_t Type = 0; // Section type (See below)
|
||||
uint32_t Offset = 0; // Offset with in the file
|
||||
StringRef Name; // Section name (User-defined sections only)
|
||||
ArrayRef<uint8_t> Content; // Section content
|
||||
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 SymbolRef &Symbol) 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(); }
|
||||
|
||||
|
@ -131,7 +131,7 @@ public:
|
|||
ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
|
||||
ArrayRef<wasm::WasmExport> exports() const { return Exports; }
|
||||
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(); }
|
||||
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
|
||||
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
|
||||
|
@ -151,7 +151,7 @@ public:
|
|||
Expected<StringRef> getSymbolName(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;
|
||||
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
|
||||
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
|
||||
|
@ -264,8 +264,7 @@ private:
|
|||
|
||||
} // end namespace object
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS,
|
||||
const object::WasmSymbol &Sym) {
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
|
||||
Sym.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ std::string llvm::wasm::toString(wasm::WasmSymbolType type) {
|
|||
|
||||
std::string llvm::wasm::relocTypetoString(uint32_t 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"
|
||||
#undef WASM_RELOC
|
||||
default:
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "llvm/MC/MCAsmInfoWasm.h"
|
||||
using namespace llvm;
|
||||
|
||||
void MCAsmInfoWasm::anchor() { }
|
||||
void MCAsmInfoWasm::anchor() {}
|
||||
|
||||
MCAsmInfoWasm::MCAsmInfoWasm() {
|
||||
HasIdentDirective = true;
|
||||
|
|
|
@ -137,11 +137,11 @@ struct WasmComdatEntry {
|
|||
|
||||
// Information about a single relocation.
|
||||
struct WasmRelocationEntry {
|
||||
uint64_t Offset; // Where is the relocation.
|
||||
const MCSymbolWasm *Symbol; // The symbol to relocate with.
|
||||
int64_t Addend; // A value to add to the symbol.
|
||||
unsigned Type; // The type of the relocation.
|
||||
const MCSectionWasm *FixupSection;// The section the relocation is targeting.
|
||||
uint64_t Offset; // Where is the relocation.
|
||||
const MCSymbolWasm *Symbol; // The symbol to relocate with.
|
||||
int64_t Addend; // A value to add to the symbol.
|
||||
unsigned Type; // The type of the relocation.
|
||||
const MCSectionWasm *FixupSection; // The section the relocation is targeting.
|
||||
|
||||
WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
|
||||
int64_t Addend, unsigned Type,
|
||||
|
@ -163,8 +163,8 @@ struct WasmRelocationEntry {
|
|||
}
|
||||
|
||||
void print(raw_ostream &Out) const {
|
||||
Out << wasm::relocTypetoString(Type)
|
||||
<< " Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
|
||||
Out << wasm::relocTypetoString(Type) << " Off=" << Offset
|
||||
<< ", Sym=" << *Symbol << ", Addend=" << Addend
|
||||
<< ", FixupSection=" << FixupSection->getSectionName();
|
||||
}
|
||||
|
||||
|
@ -291,9 +291,7 @@ private:
|
|||
W.OS << Str;
|
||||
}
|
||||
|
||||
void writeValueType(wasm::ValType Ty) {
|
||||
W.OS << static_cast<char>(Ty);
|
||||
}
|
||||
void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
|
||||
|
||||
void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
|
||||
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
|
||||
|
@ -306,7 +304,7 @@ private:
|
|||
ArrayRef<WasmFunction> Functions);
|
||||
void writeDataSection();
|
||||
void writeRelocSection(uint32_t SectionIndex, StringRef Name,
|
||||
std::vector<WasmRelocationEntry>& Relocations);
|
||||
std::vector<WasmRelocationEntry> &Relocations);
|
||||
void writeLinkingMetaDataSection(
|
||||
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
|
||||
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
|
||||
// to allow patching.
|
||||
static void
|
||||
WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
|
||||
static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
|
||||
uint64_t Offset) {
|
||||
uint8_t Buffer[5];
|
||||
unsigned SizeLen = encodeULEB128(X, Buffer, 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
|
||||
// to allow patching.
|
||||
static void
|
||||
WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
|
||||
static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
|
||||
uint64_t Offset) {
|
||||
uint8_t Buffer[5];
|
||||
unsigned SizeLen = encodeSLEB128(X, Buffer, 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);
|
||||
}
|
||||
|
||||
static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
|
||||
static const MCSymbolWasm *ResolveSymbol(const MCSymbolWasm &Symbol) {
|
||||
if (Symbol.isVariable()) {
|
||||
const MCExpr *Expr = Symbol.getVariableValue();
|
||||
auto *Inner = cast<MCSymbolRefExpr>(Expr);
|
||||
|
@ -626,10 +624,9 @@ static void addData(SmallVectorImpl<char> &DataBytes,
|
|||
report_fatal_error("only byte values supported for alignment");
|
||||
// If nops are requested, use zeros, as this is the data section.
|
||||
uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
|
||||
uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
|
||||
Align->getAlignment()),
|
||||
DataBytes.size() +
|
||||
Align->getMaxBytesToEmit());
|
||||
uint64_t Size =
|
||||
std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
|
||||
DataBytes.size() + Align->getMaxBytesToEmit());
|
||||
DataBytes.resize(Size, Value);
|
||||
} else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
|
||||
int64_t NumValues;
|
||||
|
@ -745,12 +742,12 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
|
|||
W.OS << char(Import.Global.Mutable ? 1 : 0);
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_MEMORY:
|
||||
encodeULEB128(0, W.OS); // flags
|
||||
encodeULEB128(0, W.OS); // flags
|
||||
encodeULEB128(NumPages, W.OS); // initial
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_TABLE:
|
||||
W.OS << char(Import.Table.ElemType);
|
||||
encodeULEB128(0, W.OS); // flags
|
||||
encodeULEB128(0, W.OS); // flags
|
||||
encodeULEB128(NumElements, W.OS); // initial
|
||||
break;
|
||||
default:
|
||||
|
@ -892,7 +889,7 @@ void WasmObjectWriter::writeDataSection() {
|
|||
|
||||
void WasmObjectWriter::writeRelocSection(
|
||||
uint32_t SectionIndex, StringRef Name,
|
||||
std::vector<WasmRelocationEntry>& Relocs) {
|
||||
std::vector<WasmRelocationEntry> &Relocs) {
|
||||
// See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
|
||||
// for descriptions of the reloc sections.
|
||||
|
||||
|
@ -916,9 +913,9 @@ void WasmObjectWriter::writeRelocSection(
|
|||
|
||||
encodeULEB128(SectionIndex, W.OS);
|
||||
encodeULEB128(Relocs.size(), W.OS);
|
||||
for (const WasmRelocationEntry& RelEntry : Relocs) {
|
||||
uint64_t Offset = RelEntry.Offset +
|
||||
RelEntry.FixupSection->getSectionOffset();
|
||||
for (const WasmRelocationEntry &RelEntry : Relocs) {
|
||||
uint64_t Offset =
|
||||
RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
|
||||
uint32_t Index = getRelocationIndexValue(RelEntry);
|
||||
|
||||
W.OS << char(RelEntry.Type);
|
||||
|
@ -996,7 +993,7 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
|
|||
startSection(SubSection, wasm::WASM_INIT_FUNCS);
|
||||
encodeULEB128(InitFuncs.size(), W.OS);
|
||||
for (auto &StartFunc : InitFuncs) {
|
||||
encodeULEB128(StartFunc.first, W.OS); // priority
|
||||
encodeULEB128(StartFunc.first, W.OS); // priority
|
||||
encodeULEB128(StartFunc.second, W.OS); // function index
|
||||
}
|
||||
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(TypeIndices.count(&Symbol));
|
||||
return TypeIndices[&Symbol];
|
||||
}
|
||||
|
||||
uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
|
||||
uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
|
||||
assert(Symbol.isFunction());
|
||||
|
||||
WasmFunctionType F;
|
||||
const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
|
||||
const MCSymbolWasm *ResolvedSym = ResolveSymbol(Symbol);
|
||||
F.Returns = ResolvedSym->getReturns();
|
||||
F.Params = ResolvedSym->getParams();
|
||||
|
||||
|
@ -1207,7 +1204,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
if (Name.startswith(".custom_section."))
|
||||
Name = Name.substr(strlen(".custom_section."));
|
||||
|
||||
MCSymbol* Begin = Sec.getBeginSymbol();
|
||||
MCSymbol *Begin = Sec.getBeginSymbol();
|
||||
if (Begin) {
|
||||
WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
|
||||
if (SectionName != Begin->getName())
|
||||
|
@ -1436,7 +1433,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
unsigned PrefixLength = strlen(".init_array");
|
||||
if (WS.getSectionName().size() > 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()
|
||||
.substr(PrefixLength + 1)
|
||||
.getAsInteger(10, Priority))
|
||||
|
@ -1444,14 +1442,16 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
}
|
||||
const auto &DataFrag = cast<MCDataFragment>(Frag);
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
for (const uint8_t *p = (const uint8_t *)Contents.data(),
|
||||
*end = (const uint8_t *)Contents.data() + Contents.size();
|
||||
for (const uint8_t *
|
||||
p = (const uint8_t *)Contents.data(),
|
||||
*end = (const uint8_t *)Contents.data() + Contents.size();
|
||||
p != end; ++p) {
|
||||
if (*p != 0)
|
||||
report_fatal_error("non-symbolic data in .init_array section");
|
||||
}
|
||||
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();
|
||||
auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
if (!Sym)
|
||||
|
|
|
@ -37,8 +37,8 @@ using namespace object;
|
|||
|
||||
void WasmSymbol::print(raw_ostream &Out) const {
|
||||
Out << "Name=" << Info.Name
|
||||
<< ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
|
||||
<< ", Flags=" << Info.Flags;
|
||||
<< ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
|
||||
<< ", Flags=" << Info.Flags;
|
||||
if (!isTypeData()) {
|
||||
Out << ", ElemIndex=" << Info.ElementIndex;
|
||||
} else if (isDefined()) {
|
||||
|
@ -62,9 +62,9 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
|
|||
return std::move(ObjectFile);
|
||||
}
|
||||
|
||||
#define VARINT7_MAX ((1<<7)-1)
|
||||
#define VARINT7_MIN (-(1<<7))
|
||||
#define VARUINT7_MAX (1<<7)
|
||||
#define VARINT7_MAX ((1 << 7) - 1)
|
||||
#define VARINT7_MIN (-(1 << 7))
|
||||
#define VARUINT7_MAX (1 << 7)
|
||||
#define VARUINT1_MAX (1)
|
||||
|
||||
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) {
|
||||
unsigned Count;
|
||||
const char* Error = nullptr;
|
||||
const char *Error = nullptr;
|
||||
uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
|
||||
if (Error)
|
||||
report_fatal_error(Error);
|
||||
|
@ -121,7 +121,7 @@ static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
|
|||
|
||||
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
|
||||
unsigned Count;
|
||||
const char* Error = nullptr;
|
||||
const char *Error = nullptr;
|
||||
uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
|
||||
if (Error)
|
||||
report_fatal_error(Error);
|
||||
|
@ -241,8 +241,8 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
|
|||
ErrorAsOutParameter ErrAsOutParam(&Err);
|
||||
Header.Magic = getData().substr(0, 4);
|
||||
if (Header.Magic != StringRef("\0asm", 4)) {
|
||||
Err = make_error<StringError>("Bad magic number",
|
||||
object_error::parse_failed);
|
||||
Err =
|
||||
make_error<StringError>("Bad magic number", object_error::parse_failed);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -347,8 +347,8 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
|
|||
break;
|
||||
}
|
||||
if (Ctx.Ptr != SubSectionEnd)
|
||||
return make_error<GenericBinaryError>("Name sub-section ended prematurely",
|
||||
object_error::parse_failed);
|
||||
return make_error<GenericBinaryError>(
|
||||
"Name sub-section ended prematurely", object_error::parse_failed);
|
||||
}
|
||||
|
||||
if (Ctx.Ptr != Ctx.End)
|
||||
|
@ -361,7 +361,8 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
|
|||
HasLinkingSection = true;
|
||||
if (Functions.size() != FunctionTypes.size()) {
|
||||
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);
|
||||
|
@ -484,9 +485,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
|
|||
IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
|
||||
return make_error<GenericBinaryError>("invalid global symbol index",
|
||||
object_error::parse_failed);
|
||||
if (!IsDefined &&
|
||||
(Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
|
||||
wasm::WASM_SYMBOL_BINDING_WEAK)
|
||||
if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
|
||||
wasm::WASM_SYMBOL_BINDING_WEAK)
|
||||
return make_error<GenericBinaryError>("undefined weak global symbol",
|
||||
object_error::parse_failed);
|
||||
if (IsDefined) {
|
||||
|
@ -558,7 +558,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
|
|||
for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
|
||||
StringRef Name = readString(Ctx);
|
||||
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);
|
||||
LinkingData.Comdats.emplace_back(Name);
|
||||
uint32_t Flags = readVaruint32(Ctx);
|
||||
|
@ -576,8 +577,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
|
|||
object_error::parse_failed);
|
||||
case wasm::WASM_COMDAT_DATA:
|
||||
if (Index >= DataSegments.size())
|
||||
return make_error<GenericBinaryError>("COMDAT data index out of range",
|
||||
object_error::parse_failed);
|
||||
return make_error<GenericBinaryError>(
|
||||
"COMDAT data index out of range", object_error::parse_failed);
|
||||
if (DataSegments[Index].Data.Comdat != UINT32_MAX)
|
||||
return make_error<GenericBinaryError>("Data segment in two COMDATs",
|
||||
object_error::parse_failed);
|
||||
|
@ -585,8 +586,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
|
|||
break;
|
||||
case wasm::WASM_COMDAT_FUNCTION:
|
||||
if (!isDefinedFunctionIndex(Index))
|
||||
return make_error<GenericBinaryError>("COMDAT function index out of range",
|
||||
object_error::parse_failed);
|
||||
return make_error<GenericBinaryError>(
|
||||
"COMDAT function index out of range", object_error::parse_failed);
|
||||
if (getDefinedFunction(Index).Comdat != UINT32_MAX)
|
||||
return make_error<GenericBinaryError>("Function in two COMDATs",
|
||||
object_error::parse_failed);
|
||||
|
@ -603,7 +604,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
|
|||
if (SectionIndex >= Sections.size())
|
||||
return make_error<GenericBinaryError>("Invalid section index",
|
||||
object_error::parse_failed);
|
||||
WasmSection& Section = Sections[SectionIndex];
|
||||
WasmSection &Section = Sections[SectionIndex];
|
||||
uint32_t RelocCount = readVaruint32(Ctx);
|
||||
uint32_t EndOffset = Section.Content.size();
|
||||
uint32_t PreviousOffset = 0;
|
||||
|
@ -756,8 +757,8 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
|
|||
object_error::parse_failed);
|
||||
break;
|
||||
default:
|
||||
return make_error<GenericBinaryError>(
|
||||
"Unexpected import kind", object_error::parse_failed);
|
||||
return make_error<GenericBinaryError>("Unexpected import kind",
|
||||
object_error::parse_failed);
|
||||
}
|
||||
Imports.push_back(Im);
|
||||
}
|
||||
|
@ -854,8 +855,8 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
|
|||
case wasm::WASM_EXTERNAL_TABLE:
|
||||
break;
|
||||
default:
|
||||
return make_error<GenericBinaryError>(
|
||||
"Unexpected export kind", object_error::parse_failed);
|
||||
return make_error<GenericBinaryError>("Unexpected export kind",
|
||||
object_error::parse_failed);
|
||||
}
|
||||
Exports.push_back(Ex);
|
||||
}
|
||||
|
@ -1066,7 +1067,7 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
|
|||
return getSymbolValue(Symb);
|
||||
}
|
||||
|
||||
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
|
||||
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
|
||||
switch (Sym.Info.Kind) {
|
||||
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
|
||||
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
|
||||
|
@ -1120,7 +1121,7 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
|
|||
|
||||
Expected<section_iterator>
|
||||
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
|
||||
const WasmSymbol& Sym = getWasmSymbol(Symb);
|
||||
const WasmSymbol &Sym = getWasmSymbol(Symb);
|
||||
if (Sym.isUndefined())
|
||||
return section_end();
|
||||
|
||||
|
@ -1234,9 +1235,7 @@ relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
|
|||
return relocation_iterator(RelocationRef(RelocRef, this));
|
||||
}
|
||||
|
||||
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
|
||||
Rel.d.b++;
|
||||
}
|
||||
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
|
||||
|
||||
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
|
||||
const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
|
||||
|
@ -1260,12 +1259,12 @@ uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
|
|||
|
||||
void WasmObjectFile::getRelocationTypeName(
|
||||
DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
|
||||
const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
|
||||
const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
|
||||
StringRef Res = "Unknown";
|
||||
|
||||
#define WASM_RELOC(name, value) \
|
||||
case wasm::name: \
|
||||
Res = #name; \
|
||||
#define WASM_RELOC(name, value) \
|
||||
case wasm::name: \
|
||||
Res = #name; \
|
||||
break;
|
||||
|
||||
switch (Rel.Type) {
|
||||
|
@ -1299,9 +1298,7 @@ SubtargetFeatures WasmObjectFile::getFeatures() const {
|
|||
return SubtargetFeatures();
|
||||
}
|
||||
|
||||
bool WasmObjectFile::isRelocatableObject() const {
|
||||
return HasLinkingSection;
|
||||
}
|
||||
bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
|
||||
|
||||
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
|
||||
assert(Ref.d.a < Sections.size());
|
||||
|
@ -1321,7 +1318,7 @@ WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
|
|||
const wasm::WasmRelocation &
|
||||
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
|
||||
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());
|
||||
return Sec.Relocations[Ref.d.b];
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
|
|||
IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
|
||||
} else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
|
||||
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);
|
||||
} else {
|
||||
llvm_unreachable("unhandled import type");
|
||||
|
@ -383,8 +383,8 @@ void MappingTraits<WasmYAML::ComdatEntry>::mapping(
|
|||
IO.mapRequired("Index", ComdatEntry.Index);
|
||||
}
|
||||
|
||||
void MappingTraits<WasmYAML::Comdat>::mapping(
|
||||
IO &IO, WasmYAML::Comdat &Comdat) {
|
||||
void MappingTraits<WasmYAML::Comdat>::mapping(IO &IO,
|
||||
WasmYAML::Comdat &Comdat) {
|
||||
IO.mapRequired("Name", Comdat.Name);
|
||||
IO.mapRequired("Entries", Comdat.Entries);
|
||||
}
|
||||
|
@ -420,16 +420,16 @@ void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(
|
|||
}
|
||||
|
||||
void ScalarBitSetTraits<WasmYAML::SegmentFlags>::bitset(
|
||||
IO &IO, WasmYAML::SegmentFlags &Value) {
|
||||
}
|
||||
IO &IO, WasmYAML::SegmentFlags &Value) {}
|
||||
|
||||
void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset(
|
||||
IO &IO, WasmYAML::SymbolFlags &Value) {
|
||||
#define BCaseMask(M, X) IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M)
|
||||
//BCaseMask(BINDING_MASK, BINDING_GLOBAL);
|
||||
#define BCaseMask(M, X) \
|
||||
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_LOCAL);
|
||||
//BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
|
||||
// BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
|
||||
BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN);
|
||||
BCaseMask(UNDEFINED, UNDEFINED);
|
||||
#undef BCaseMask
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
|
||||
#include "WebAssembly.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/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/MCSymbol.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
|
@ -65,18 +65,18 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
|
|||
};
|
||||
|
||||
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)
|
||||
: 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)
|
||||
: 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)
|
||||
: Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
|
||||
: Kind(K), StartLoc(Start), EndLoc(End), Sym(S) {}
|
||||
|
||||
bool isToken() const override { return Kind == Token; }
|
||||
bool isImm() const override { return Kind == Integer ||
|
||||
Kind == Float ||
|
||||
Kind == Symbol; }
|
||||
bool isImm() const override {
|
||||
return Kind == Integer || Kind == Float || Kind == Symbol;
|
||||
}
|
||||
bool isMem() const override { return false; }
|
||||
bool isReg() const override { return false; }
|
||||
|
||||
|
@ -145,8 +145,8 @@ public:
|
|||
#include "WebAssemblyGenAsmMatcher.inc"
|
||||
|
||||
// TODO: This is required to be implemented, but appears unused.
|
||||
bool ParseRegister(unsigned &/*RegNo*/, SMLoc &/*StartLoc*/,
|
||||
SMLoc &/*EndLoc*/) override {
|
||||
bool ParseRegister(unsigned & /*RegNo*/, SMLoc & /*StartLoc*/,
|
||||
SMLoc & /*EndLoc*/) override {
|
||||
llvm_unreachable("ParseRegister is not implemented.");
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,8 @@ public:
|
|||
|
||||
bool IsNext(AsmToken::TokenKind Kind) {
|
||||
auto ok = Lexer.is(Kind);
|
||||
if (ok) Parser.Lex();
|
||||
if (ok)
|
||||
Parser.Lex();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -190,15 +191,15 @@ public:
|
|||
void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
|
||||
auto &Int = Lexer.getTok();
|
||||
int64_t Val = Int.getIntVal();
|
||||
if (IsNegative) Val = -Val;
|
||||
if (IsNegative)
|
||||
Val = -Val;
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Integer, Int.getLoc(),
|
||||
Int.getEndLoc(), WebAssemblyOperand::IntOp{Val}));
|
||||
WebAssemblyOperand::Integer, Int.getLoc(), Int.getEndLoc(),
|
||||
WebAssemblyOperand::IntOp{Val}));
|
||||
Parser.Lex();
|
||||
}
|
||||
|
||||
bool ParseOperandStartingWithInteger(bool IsNegative,
|
||||
OperandVector &Operands,
|
||||
bool ParseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands,
|
||||
StringRef InstName) {
|
||||
ParseSingleInteger(IsNegative, Operands);
|
||||
// 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
|
||||
// an opcode until after the assembly matcher.
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Integer, Offset.getLoc(),
|
||||
Offset.getEndLoc(), WebAssemblyOperand::IntOp{0}));
|
||||
WebAssemblyOperand::Integer, Offset.getLoc(), Offset.getEndLoc(),
|
||||
WebAssemblyOperand::IntOp{0}));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParseInstruction(ParseInstructionInfo &/*Info*/, StringRef Name,
|
||||
bool ParseInstruction(ParseInstructionInfo & /*Info*/, StringRef Name,
|
||||
SMLoc NameLoc, OperandVector &Operands) override {
|
||||
Operands.push_back(
|
||||
make_unique<WebAssemblyOperand>(WebAssemblyOperand::Token, NameLoc,
|
||||
SMLoc::getFromPointer(
|
||||
NameLoc.getPointer() + Name.size()),
|
||||
WebAssemblyOperand::TokOp{
|
||||
StringRef(NameLoc.getPointer(),
|
||||
Name.size())}));
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Token, NameLoc,
|
||||
SMLoc::getFromPointer(NameLoc.getPointer() + Name.size()),
|
||||
WebAssemblyOperand::TokOp{
|
||||
StringRef(NameLoc.getPointer(), Name.size())}));
|
||||
auto NamePair = Name.split('.');
|
||||
// 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)) {
|
||||
auto &Tok = Lexer.getTok();
|
||||
switch (Tok.getKind()) {
|
||||
|
@ -246,8 +246,8 @@ public:
|
|||
if (Parser.parsePrimaryExpr(Val, End))
|
||||
return Error("Cannot parse symbol: ", Lexer.getTok());
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Symbol, Id.getLoc(),
|
||||
Id.getEndLoc(), WebAssemblyOperand::SymOp{Val}));
|
||||
WebAssemblyOperand::Symbol, Id.getLoc(), Id.getEndLoc(),
|
||||
WebAssemblyOperand::SymOp{Val}));
|
||||
break;
|
||||
}
|
||||
case AsmToken::Minus:
|
||||
|
@ -266,8 +266,8 @@ public:
|
|||
if (Tok.getString().getAsDouble(Val, false))
|
||||
return Error("Cannot parse real: ", Tok);
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Float, Tok.getLoc(),
|
||||
Tok.getEndLoc(), WebAssemblyOperand::FltOp{Val}));
|
||||
WebAssemblyOperand::Float, Tok.getLoc(), Tok.getEndLoc(),
|
||||
WebAssemblyOperand::FltOp{Val}));
|
||||
Parser.Lex();
|
||||
break;
|
||||
}
|
||||
|
@ -275,7 +275,8 @@ public:
|
|||
return Error("Unexpected token in operand: ", Tok);
|
||||
}
|
||||
if (Lexer.isNot(AsmToken::EndOfStatement)) {
|
||||
if (Expect(AsmToken::Comma, ",")) return true;
|
||||
if (Expect(AsmToken::Comma, ","))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Parser.Lex();
|
||||
|
@ -285,34 +286,30 @@ public:
|
|||
// the wasm module is generated).
|
||||
if (NamePair.second == "block" || NamePair.second == "loop") {
|
||||
Operands.push_back(make_unique<WebAssemblyOperand>(
|
||||
WebAssemblyOperand::Integer, NameLoc,
|
||||
NameLoc, WebAssemblyOperand::IntOp{-1}));
|
||||
WebAssemblyOperand::Integer, NameLoc, NameLoc,
|
||||
WebAssemblyOperand::IntOp{-1}));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void onLabelParsed(MCSymbol *Symbol) override {
|
||||
LastLabel = Symbol;
|
||||
}
|
||||
void onLabelParsed(MCSymbol *Symbol) override { LastLabel = Symbol; }
|
||||
|
||||
bool ParseDirective(AsmToken DirectiveID) override {
|
||||
assert(DirectiveID.getKind() == AsmToken::Identifier);
|
||||
auto &Out = getStreamer();
|
||||
auto &TOut = reinterpret_cast<WebAssemblyTargetStreamer &>(
|
||||
*Out.getTargetStreamer());
|
||||
auto &TOut =
|
||||
reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
|
||||
// TODO: we're just parsing the subset of directives we're interested in,
|
||||
// and ignoring ones we don't recognise. We should ideally verify
|
||||
// all directives here.
|
||||
if (DirectiveID.getString() == ".type") {
|
||||
// This could be the start of a function, check if followed by
|
||||
// "label,@function"
|
||||
if (!(IsNext(AsmToken::Identifier) &&
|
||||
IsNext(AsmToken::Comma) &&
|
||||
IsNext(AsmToken::At) &&
|
||||
Lexer.is(AsmToken::Identifier)))
|
||||
if (!(IsNext(AsmToken::Identifier) && IsNext(AsmToken::Comma) &&
|
||||
IsNext(AsmToken::At) && Lexer.is(AsmToken::Identifier)))
|
||||
return Error("Expected label,@type declaration, got: ", Lexer.getTok());
|
||||
Parser.Lex();
|
||||
//Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
|
||||
// Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
|
||||
} else if (DirectiveID.getString() == ".param" ||
|
||||
DirectiveID.getString() == ".local") {
|
||||
// Track the number of locals, needed for correct virtual register
|
||||
|
@ -322,28 +319,31 @@ public:
|
|||
std::vector<MVT> Locals;
|
||||
while (Lexer.is(AsmToken::Identifier)) {
|
||||
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") {
|
||||
Params.push_back(RegType);
|
||||
} else {
|
||||
Locals.push_back(RegType);
|
||||
}
|
||||
Parser.Lex();
|
||||
if (!IsNext(AsmToken::Comma)) break;
|
||||
if (!IsNext(AsmToken::Comma))
|
||||
break;
|
||||
}
|
||||
assert(LastLabel);
|
||||
TOut.emitParam(LastLabel, Params);
|
||||
TOut.emitLocal(Locals);
|
||||
} else {
|
||||
// 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");
|
||||
}
|
||||
|
||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &/*Opcode*/,
|
||||
OperandVector &Operands,
|
||||
MCStreamer &Out, uint64_t &ErrorInfo,
|
||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned & /*Opcode*/,
|
||||
OperandVector &Operands, MCStreamer &Out,
|
||||
uint64_t &ErrorInfo,
|
||||
bool MatchingInlineAsm) override {
|
||||
MCInst Inst;
|
||||
unsigned MatchResult =
|
||||
|
@ -354,8 +354,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
case Match_MissingFeature:
|
||||
return Parser.Error(IDLoc,
|
||||
"instruction requires a WASM feature not currently enabled");
|
||||
return Parser.Error(
|
||||
IDLoc, "instruction requires a WASM feature not currently enabled");
|
||||
case Match_MnemonicFail:
|
||||
return Parser.Error(IDLoc, "invalid instruction");
|
||||
case Match_NearMisses:
|
||||
|
|
|
@ -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
|
||||
// we have an extra flags operand which is not currently printed, for
|
||||
// compatiblity reasons.
|
||||
if (i != 0 &&
|
||||
((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
|
||||
MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
|
||||
i != Desc.getNumOperands()))
|
||||
if (i != 0 && ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
|
||||
MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
|
||||
i != Desc.getNumOperands()))
|
||||
OS << ", ";
|
||||
printOperand(MI, i, OS);
|
||||
}
|
||||
|
@ -88,12 +87,14 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
|
|||
case WebAssembly::END_LOOP_S:
|
||||
// Have to guard against an empty stack, in case of mismatched pairs
|
||||
// in assembly parsing.
|
||||
if (!ControlFlowStack.empty()) ControlFlowStack.pop_back();
|
||||
if (!ControlFlowStack.empty())
|
||||
ControlFlowStack.pop_back();
|
||||
break;
|
||||
case WebAssembly::END_BLOCK:
|
||||
case WebAssembly::END_BLOCK_S:
|
||||
if (!ControlFlowStack.empty()) printAnnotation(
|
||||
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
|
||||
if (!ControlFlowStack.empty())
|
||||
printAnnotation(
|
||||
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -118,17 +119,15 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
|
|||
|
||||
static std::string toString(const APFloat &FP) {
|
||||
// Print NaNs with custom payloads specially.
|
||||
if (FP.isNaN() &&
|
||||
!FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
|
||||
if (FP.isNaN() && !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) &&
|
||||
!FP.bitwiseIsEqual(
|
||||
APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) {
|
||||
APInt AI = FP.bitcastToAPInt();
|
||||
return
|
||||
std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
|
||||
utohexstr(AI.getZExtValue() &
|
||||
(AI.getBitWidth() == 32 ? INT64_C(0x007fffff) :
|
||||
INT64_C(0x000fffffffffffff)),
|
||||
/*LowerCase=*/true);
|
||||
return std::string(AI.isNegative() ? "-" : "") + "nan:0x" +
|
||||
utohexstr(AI.getZExtValue() &
|
||||
(AI.getBitWidth() == 32 ? INT64_C(0x007fffff)
|
||||
: INT64_C(0x000fffffffffffff)),
|
||||
/*LowerCase=*/true);
|
||||
}
|
||||
|
||||
// Use C99's hexadecimal floating-point representation.
|
||||
|
@ -199,25 +198,40 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
|||
}
|
||||
}
|
||||
|
||||
void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(
|
||||
const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||
void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI,
|
||||
unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
int64_t Imm = MI->getOperand(OpNo).getImm();
|
||||
if (Imm == WebAssembly::GetDefaultP2Align(MI->getOpcode()))
|
||||
return;
|
||||
O << ":p2align=" << Imm;
|
||||
}
|
||||
|
||||
void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(
|
||||
const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||
void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
|
||||
unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
int64_t Imm = MI->getOperand(OpNo).getImm();
|
||||
switch (WebAssembly::ExprType(Imm)) {
|
||||
case WebAssembly::ExprType::Void: break;
|
||||
case WebAssembly::ExprType::I32: O << "i32"; break;
|
||||
case WebAssembly::ExprType::I64: 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;
|
||||
case WebAssembly::ExprType::Void:
|
||||
break;
|
||||
case WebAssembly::ExprType::I32:
|
||||
O << "i32";
|
||||
break;
|
||||
case WebAssembly::ExprType::I64:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,13 +73,13 @@ public:
|
|||
const MCFixupKindInfo &
|
||||
WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
|
||||
// This table *must* be in the order that the fixup_* kinds are defined in
|
||||
// WebAssemblyFixupKinds.h.
|
||||
//
|
||||
// Name Offset (bits) Size (bits) Flags
|
||||
{ "fixup_code_sleb128_i32", 0, 5*8, 0 },
|
||||
{ "fixup_code_sleb128_i64", 0, 10*8, 0 },
|
||||
{ "fixup_code_uleb128_i32", 0, 5*8, 0 },
|
||||
// This table *must* be in the order that the fixup_* kinds are defined in
|
||||
// WebAssemblyFixupKinds.h.
|
||||
//
|
||||
// Name Offset (bits) Size (bits) Flags
|
||||
{"fixup_code_sleb128_i32", 0, 5 * 8, 0},
|
||||
{"fixup_code_sleb128_i64", 0, 10 * 8, 0},
|
||||
{"fixup_code_uleb128_i32", 0, 5 * 8, 0},
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
namespace llvm {
|
||||
namespace WebAssembly {
|
||||
enum Fixups {
|
||||
fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed
|
||||
fixup_code_sleb128_i64, // 64-bit signed
|
||||
fixup_code_uleb128_i32, // 32-bit unsigned
|
||||
fixup_code_sleb128_i32 = FirstTargetFixupKind, // 32-bit signed
|
||||
fixup_code_sleb128_i64, // 64-bit signed
|
||||
fixup_code_uleb128_i32, // 32-bit unsigned
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
|
|
|
@ -67,8 +67,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
|
|||
OS << uint8_t(Binary);
|
||||
} else {
|
||||
assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet");
|
||||
OS << uint8_t(Binary >> 8)
|
||||
<< uint8_t(Binary);
|
||||
OS << uint8_t(Binary >> 8) << uint8_t(Binary);
|
||||
}
|
||||
|
||||
// For br_table instructions, encode the size of the table. In the MCInst,
|
||||
|
@ -162,9 +161,8 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
|
|||
} else {
|
||||
llvm_unreachable("unexpected symbolic operand kind");
|
||||
}
|
||||
Fixups.push_back(MCFixup::create(
|
||||
OS.tell() - Start, MO.getExpr(),
|
||||
FixupKind, MI.getLoc()));
|
||||
Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
|
||||
FixupKind, MI.getLoc()));
|
||||
++MCNumFixups;
|
||||
encodeULEB128(0, OS, PaddedSize);
|
||||
} else {
|
||||
|
|
|
@ -125,11 +125,17 @@ extern "C" void LLVMInitializeWebAssemblyTargetMC() {
|
|||
|
||||
wasm::ValType WebAssembly::toValType(const MVT &Ty) {
|
||||
switch (Ty.SimpleTy) {
|
||||
case MVT::i32: return wasm::ValType::I32;
|
||||
case MVT::i64: return wasm::ValType::I64;
|
||||
case MVT::f32: return wasm::ValType::F32;
|
||||
case MVT::f64: return wasm::ValType::F64;
|
||||
case MVT::ExceptRef: return wasm::ValType::EXCEPT_REF;
|
||||
default: llvm_unreachable("unexpected type");
|
||||
case MVT::i32:
|
||||
return wasm::ValType::I32;
|
||||
case MVT::i64:
|
||||
return wasm::ValType::I64;
|
||||
case MVT::f32:
|
||||
return wasm::ValType::F32;
|
||||
case MVT::f64:
|
||||
return wasm::ValType::F64;
|
||||
case MVT::ExceptRef:
|
||||
return wasm::ValType::EXCEPT_REF;
|
||||
default:
|
||||
llvm_unreachable("unexpected type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,8 @@ enum TOF {
|
|||
|
||||
// Flags to indicate the type of the symbol being referenced
|
||||
MO_SYMBOL_FUNCTION = 0x1,
|
||||
MO_SYMBOL_GLOBAL = 0x2,
|
||||
MO_SYMBOL_MASK = 0x3,
|
||||
MO_SYMBOL_GLOBAL = 0x2,
|
||||
MO_SYMBOL_MASK = 0x3,
|
||||
};
|
||||
} // end namespace WebAssemblyII
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
|
|||
void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
|
||||
|
||||
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();
|
||||
if (Results.empty())
|
||||
OS << ", void";
|
||||
|
|
|
@ -65,8 +65,7 @@ public:
|
|||
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(MCSymbol *Symbol,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) override;
|
||||
void emitIndIdx(const MCExpr *Value) override;
|
||||
void emitGlobalImport(StringRef name) override;
|
||||
|
@ -82,8 +81,7 @@ public:
|
|||
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(MCSymbol *Symbol,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
void emitIndirectFunctionType(MCSymbol *Symbol, SmallVectorImpl<MVT> &Params,
|
||||
SmallVectorImpl<MVT> &Results) override;
|
||||
void emitIndIdx(const MCExpr *Value) override;
|
||||
void emitGlobalImport(StringRef name) override;
|
||||
|
|
|
@ -86,9 +86,8 @@ static bool IsGlobalType(const MCValue &Target) {
|
|||
return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
|
||||
}
|
||||
|
||||
unsigned
|
||||
WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup) const {
|
||||
unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
||||
const MCFixup &Fixup) const {
|
||||
// WebAssembly functions are not allocated in the data address space. To
|
||||
// resolve a pointer to a function, we must use a special relocation type.
|
||||
bool IsFunction = IsFunctionExpr(Fixup.getValue());
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "wasm-add-missing-prototypes"
|
||||
|
@ -62,14 +62,15 @@ ModulePass *llvm::createWebAssemblyAddMissingPrototypes() {
|
|||
bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
|
||||
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
|
||||
for (Function &F : M) {
|
||||
if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
|
||||
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
|
||||
// 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: " +
|
||||
F.getName());
|
||||
|
||||
|
||||
// Create a function prototype based on the first call site (first bitcast)
|
||||
// that we find.
|
||||
FunctionType *NewType = nullptr;
|
||||
Function* NewF = nullptr;
|
||||
Function *NewF = nullptr;
|
||||
for (Use &U : F.uses()) {
|
||||
LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
|
||||
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
|
||||
for (auto &Pair : Replacements) {
|
||||
Function* Old = Pair.first;
|
||||
Function* New = Pair.second;
|
||||
Function *Old = Pair.first;
|
||||
Function *New = Pair.second;
|
||||
Old->eraseFromParent();
|
||||
M.getFunctionList().push_back(New);
|
||||
}
|
||||
|
|
|
@ -90,8 +90,8 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
|||
if (TM.getTargetTriple().isOSBinFormatWasm() &&
|
||||
F.hasFnAttribute("wasm-import-module")) {
|
||||
MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
|
||||
StringRef Name = F.getFnAttribute("wasm-import-module")
|
||||
.getValueAsString();
|
||||
StringRef Name =
|
||||
F.getFnAttribute("wasm-import-module").getValueAsString();
|
||||
getTargetStreamer()->emitImportModule(WasmSym, Name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
|
|||
public:
|
||||
explicit WebAssemblyAsmPrinter(TargetMachine &TM,
|
||||
std::unique_ptr<MCStreamer> Streamer)
|
||||
: AsmPrinter(TM, std::move(Streamer)),
|
||||
Subtarget(nullptr), MRI(nullptr), MFI(nullptr) {}
|
||||
: AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), MRI(nullptr),
|
||||
MFI(nullptr) {}
|
||||
|
||||
StringRef getPassName() const override {
|
||||
return "WebAssembly Assembly Printer";
|
||||
|
|
|
@ -97,8 +97,8 @@ public:
|
|||
|
||||
char WebAssemblyCFGStackify::ID = 0;
|
||||
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
|
||||
"Insert BLOCK and LOOP markers for WebAssembly scopes",
|
||||
false, false)
|
||||
"Insert BLOCK and LOOP markers for WebAssembly scopes", false,
|
||||
false)
|
||||
|
||||
FunctionPass *llvm::createWebAssemblyCFGStackify() {
|
||||
return new WebAssemblyCFGStackify();
|
||||
|
@ -633,10 +633,18 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
|
|||
|
||||
WebAssembly::ExprType retType;
|
||||
switch (MFI.getResults().front().SimpleTy) {
|
||||
case MVT::i32: retType = WebAssembly::ExprType::I32; 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::i32:
|
||||
retType = WebAssembly::ExprType::I32;
|
||||
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::v8i16:
|
||||
case MVT::v4i32:
|
||||
|
@ -645,8 +653,11 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
|
|||
case MVT::v2f64:
|
||||
retType = WebAssembly::ExprType::V128;
|
||||
break;
|
||||
case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break;
|
||||
default: llvm_unreachable("unexpected return type");
|
||||
case MVT::ExceptRef:
|
||||
retType = WebAssembly::ExprType::ExceptRef;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unexpected return type");
|
||||
}
|
||||
|
||||
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
|
||||
// were a block.
|
||||
static void AppendEndToFunction(
|
||||
MachineFunction &MF,
|
||||
const WebAssemblyInstrInfo &TII) {
|
||||
static void AppendEndToFunction(MachineFunction &MF,
|
||||
const WebAssemblyInstrInfo &TII) {
|
||||
BuildMI(MF.back(), MF.back().end(),
|
||||
MF.back().findPrevDebugLoc(MF.back().end()),
|
||||
TII.get(WebAssembly::END_FUNCTION));
|
||||
|
|
|
@ -64,18 +64,30 @@ FunctionPass *llvm::createWebAssemblyCallIndirectFixup() {
|
|||
static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) {
|
||||
switch (MI.getOpcode()) {
|
||||
using namespace WebAssembly;
|
||||
case PCALL_INDIRECT_VOID: return CALL_INDIRECT_VOID;
|
||||
case PCALL_INDIRECT_I32: return CALL_INDIRECT_I32;
|
||||
case PCALL_INDIRECT_I64: return CALL_INDIRECT_I64;
|
||||
case PCALL_INDIRECT_F32: return CALL_INDIRECT_F32;
|
||||
case PCALL_INDIRECT_F64: return CALL_INDIRECT_F64;
|
||||
case PCALL_INDIRECT_v16i8: 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;
|
||||
case PCALL_INDIRECT_VOID:
|
||||
return CALL_INDIRECT_VOID;
|
||||
case PCALL_INDIRECT_I32:
|
||||
return CALL_INDIRECT_I32;
|
||||
case PCALL_INDIRECT_I64:
|
||||
return CALL_INDIRECT_I64;
|
||||
case PCALL_INDIRECT_F32:
|
||||
return CALL_INDIRECT_F32;
|
||||
case PCALL_INDIRECT_F64:
|
||||
return CALL_INDIRECT_F64;
|
||||
case PCALL_INDIRECT_v16i8:
|
||||
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));
|
||||
|
||||
for (const MachineOperand &MO :
|
||||
make_range(MI.operands_begin() +
|
||||
MI.getDesc().getNumDefs() + 1,
|
||||
MI.operands_begin() +
|
||||
MI.getNumExplicitOperands()))
|
||||
make_range(MI.operands_begin() + MI.getDesc().getNumDefs() + 1,
|
||||
MI.operands_begin() + MI.getNumExplicitOperands()))
|
||||
Ops.push_back(MO);
|
||||
Ops.push_back(MI.getOperand(MI.getDesc().getNumDefs()));
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "WebAssemblyExceptionInfo.h"
|
||||
#include "WebAssemblyUtilities.h"
|
||||
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||
#include "WebAssemblyUtilities.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/CodeGen/MachineDominanceFrontier.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
|
|
|
@ -114,8 +114,8 @@ private:
|
|||
// Utility helper routines
|
||||
MVT::SimpleValueType getSimpleType(Type *Ty) {
|
||||
EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
|
||||
return VT.isSimple() ? VT.getSimpleVT().SimpleTy :
|
||||
MVT::INVALID_SIMPLE_VALUE_TYPE;
|
||||
return VT.isSimple() ? VT.getSimpleVT().SimpleTy
|
||||
: MVT::INVALID_SIMPLE_VALUE_TYPE;
|
||||
}
|
||||
MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
|
||||
switch (VT) {
|
||||
|
@ -155,11 +155,9 @@ private:
|
|||
MVT::SimpleValueType From);
|
||||
unsigned signExtendToI32(unsigned Reg, const Value *V,
|
||||
MVT::SimpleValueType From);
|
||||
unsigned zeroExtend(unsigned Reg, const Value *V,
|
||||
MVT::SimpleValueType From,
|
||||
unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
|
||||
MVT::SimpleValueType To);
|
||||
unsigned signExtend(unsigned Reg, const Value *V,
|
||||
MVT::SimpleValueType From,
|
||||
unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
|
||||
MVT::SimpleValueType To);
|
||||
unsigned getRegForUnsignedValue(const Value *V);
|
||||
unsigned getRegForSignedValue(const Value *V);
|
||||
|
@ -376,14 +374,12 @@ void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
|
|||
if (Addr.isRegBase()) {
|
||||
unsigned Reg = Addr.getReg();
|
||||
if (Reg == 0) {
|
||||
Reg = createResultReg(Subtarget->hasAddr64() ?
|
||||
&WebAssembly::I64RegClass :
|
||||
&WebAssembly::I32RegClass);
|
||||
unsigned Opc = Subtarget->hasAddr64() ?
|
||||
WebAssembly::CONST_I64 :
|
||||
WebAssembly::CONST_I32;
|
||||
Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
|
||||
: &WebAssembly::I32RegClass);
|
||||
unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
|
||||
: WebAssembly::CONST_I32;
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
|
||||
.addImm(0);
|
||||
.addImm(0);
|
||||
Addr.setReg(Reg);
|
||||
}
|
||||
}
|
||||
|
@ -459,13 +455,13 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
|
|||
unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
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);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::AND_I32), Result)
|
||||
.addReg(Reg)
|
||||
.addReg(Imm);
|
||||
.addReg(Reg)
|
||||
.addReg(Imm);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -489,19 +485,19 @@ unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
|
|||
unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::CONST_I32), Imm)
|
||||
.addImm(32 - MVT(From).getSizeInBits());
|
||||
.addImm(32 - MVT(From).getSizeInBits());
|
||||
|
||||
unsigned Left = createResultReg(&WebAssembly::I32RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::SHL_I32), Left)
|
||||
.addReg(Reg)
|
||||
.addReg(Imm);
|
||||
.addReg(Reg)
|
||||
.addReg(Imm);
|
||||
|
||||
unsigned Right = createResultReg(&WebAssembly::I32RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::SHR_S_I32), Right)
|
||||
.addReg(Left)
|
||||
.addReg(Imm);
|
||||
.addReg(Left)
|
||||
.addReg(Imm);
|
||||
|
||||
return Right;
|
||||
}
|
||||
|
@ -564,8 +560,7 @@ unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
|
|||
|
||||
unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
|
||||
bool IsSigned) {
|
||||
return IsSigned ? getRegForSignedValue(V) :
|
||||
getRegForUnsignedValue(V);
|
||||
return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
|
||||
}
|
||||
|
||||
unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
|
||||
|
@ -574,15 +569,15 @@ unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
|
|||
unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::EQZ_I32), NotReg)
|
||||
.addReg(Reg);
|
||||
.addReg(Reg);
|
||||
return NotReg;
|
||||
}
|
||||
|
||||
unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
|
||||
unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(WebAssembly::COPY), ResultReg)
|
||||
.addReg(Reg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
|
||||
ResultReg)
|
||||
.addReg(Reg);
|
||||
return ResultReg;
|
||||
}
|
||||
|
||||
|
@ -591,12 +586,11 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
|
|||
FuncInfo.StaticAllocaMap.find(AI);
|
||||
|
||||
if (SI != FuncInfo.StaticAllocaMap.end()) {
|
||||
unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
|
||||
&WebAssembly::I64RegClass :
|
||||
&WebAssembly::I32RegClass);
|
||||
unsigned Opc = Subtarget->hasAddr64() ?
|
||||
WebAssembly::COPY_I64 :
|
||||
WebAssembly::COPY_I32;
|
||||
unsigned ResultReg =
|
||||
createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
|
||||
: &WebAssembly::I32RegClass);
|
||||
unsigned Opc =
|
||||
Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
|
||||
.addFrameIndex(SI->second);
|
||||
return ResultReg;
|
||||
|
@ -607,14 +601,13 @@ unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
|
|||
|
||||
unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
|
||||
unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
|
||||
&WebAssembly::I64RegClass :
|
||||
&WebAssembly::I32RegClass);
|
||||
unsigned Opc = Subtarget->hasAddr64() ?
|
||||
WebAssembly::CONST_I64 :
|
||||
WebAssembly::CONST_I32;
|
||||
unsigned ResultReg =
|
||||
createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
|
||||
: &WebAssembly::I32RegClass);
|
||||
unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
|
||||
: WebAssembly::CONST_I32;
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
|
||||
.addGlobalAddress(GV);
|
||||
.addGlobalAddress(GV);
|
||||
return ResultReg;
|
||||
}
|
||||
|
||||
|
@ -701,7 +694,7 @@ bool WebAssemblyFastISel::fastLowerArguments() {
|
|||
}
|
||||
unsigned ResultReg = createResultReg(RC);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
|
||||
.addImm(i);
|
||||
.addImm(i);
|
||||
updateValueMap(&Arg, ResultReg);
|
||||
|
||||
++i;
|
||||
|
@ -720,7 +713,8 @@ bool WebAssemblyFastISel::fastLowerArguments() {
|
|||
}
|
||||
|
||||
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) {
|
||||
MFI->clearParamsAndResults();
|
||||
return false;
|
||||
|
@ -778,33 +772,33 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
|
|||
ResultReg = createResultReg(&WebAssembly::F64RegClass);
|
||||
break;
|
||||
case MVT::v16i8:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v16i8
|
||||
: WebAssembly::PCALL_INDIRECT_v16i8;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::v8i16:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v8i16
|
||||
: WebAssembly::PCALL_INDIRECT_v8i16;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::v4i32:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v4i32
|
||||
: WebAssembly::PCALL_INDIRECT_v4i32;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::v2i64:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v2i64 : WebAssembly::PCALL_INDIRECT_v2i64;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v2i64
|
||||
: WebAssembly::PCALL_INDIRECT_v2i64;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::v4f32:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v4f32
|
||||
: WebAssembly::PCALL_INDIRECT_v4f32;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::v2f64:
|
||||
Opc =
|
||||
IsDirect ? WebAssembly::CALL_v2f64 : WebAssembly::PCALL_INDIRECT_v2f64;
|
||||
Opc = IsDirect ? WebAssembly::CALL_v2f64
|
||||
: WebAssembly::PCALL_INDIRECT_v2f64;
|
||||
ResultReg = createResultReg(&WebAssembly::V128RegClass);
|
||||
break;
|
||||
case MVT::ExceptRef:
|
||||
|
@ -873,11 +867,11 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
|
|||
const SelectInst *Select = cast<SelectInst>(I);
|
||||
|
||||
bool Not;
|
||||
unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
|
||||
unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
|
||||
if (CondReg == 0)
|
||||
return false;
|
||||
|
||||
unsigned TrueReg = getRegForValue(Select->getTrueValue());
|
||||
unsigned TrueReg = getRegForValue(Select->getTrueValue());
|
||||
if (TrueReg == 0)
|
||||
return false;
|
||||
|
||||
|
@ -920,9 +914,9 @@ bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
|
|||
|
||||
unsigned ResultReg = createResultReg(RC);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
|
||||
.addReg(TrueReg)
|
||||
.addReg(FalseReg)
|
||||
.addReg(CondReg);
|
||||
.addReg(TrueReg)
|
||||
.addReg(FalseReg)
|
||||
.addReg(CondReg);
|
||||
|
||||
updateValueMap(Select, ResultReg);
|
||||
return true;
|
||||
|
@ -1022,7 +1016,8 @@ bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
|
|||
Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
|
||||
isSigned = true;
|
||||
break;
|
||||
default: return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
|
||||
|
@ -1230,7 +1225,8 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) {
|
|||
case MVT::f64:
|
||||
Opc = WebAssembly::STORE_F64;
|
||||
break;
|
||||
default: return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
materializeLoadStoreOperands(Addr);
|
||||
|
@ -1295,8 +1291,10 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
|
|||
|
||||
unsigned Opc;
|
||||
switch (getSimpleType(RV->getType())) {
|
||||
case MVT::i1: case MVT::i8:
|
||||
case MVT::i16: case MVT::i32:
|
||||
case MVT::i1:
|
||||
case MVT::i8:
|
||||
case MVT::i16:
|
||||
case MVT::i32:
|
||||
Opc = WebAssembly::RETURN_I32;
|
||||
break;
|
||||
case MVT::i64:
|
||||
|
@ -1329,7 +1327,8 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) {
|
|||
case MVT::ExceptRef:
|
||||
Opc = WebAssembly::RETURN_EXCEPT_REF;
|
||||
break;
|
||||
default: return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned Reg;
|
||||
|
@ -1359,19 +1358,32 @@ bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
|
|||
if (selectCall(I))
|
||||
return true;
|
||||
break;
|
||||
case Instruction::Select: return selectSelect(I);
|
||||
case Instruction::Trunc: return selectTrunc(I);
|
||||
case Instruction::ZExt: return selectZExt(I);
|
||||
case Instruction::SExt: return selectSExt(I);
|
||||
case Instruction::ICmp: return selectICmp(I);
|
||||
case Instruction::FCmp: return selectFCmp(I);
|
||||
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;
|
||||
case Instruction::Select:
|
||||
return selectSelect(I);
|
||||
case Instruction::Trunc:
|
||||
return selectTrunc(I);
|
||||
case Instruction::ZExt:
|
||||
return selectZExt(I);
|
||||
case Instruction::SExt:
|
||||
return selectSExt(I);
|
||||
case Instruction::ICmp:
|
||||
return selectICmp(I);
|
||||
case Instruction::FCmp:
|
||||
return selectFCmp(I);
|
||||
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.
|
||||
|
|
|
@ -36,10 +36,10 @@ using namespace llvm;
|
|||
|
||||
#define DEBUG_TYPE "wasm-fix-function-bitcasts"
|
||||
|
||||
static cl::opt<bool> TemporaryWorkarounds(
|
||||
"wasm-temporary-workarounds",
|
||||
cl::desc("Apply certain temporary workarounds"),
|
||||
cl::init(true), cl::Hidden);
|
||||
static cl::opt<bool>
|
||||
TemporaryWorkarounds("wasm-temporary-workarounds",
|
||||
cl::desc("Apply certain temporary workarounds"),
|
||||
cl::init(true), cl::Hidden);
|
||||
|
||||
namespace {
|
||||
class FixFunctionBitcasts final : public ModulePass {
|
||||
|
@ -108,7 +108,7 @@ static void FindUses(Value *V, Function &F,
|
|||
// instead).
|
||||
//
|
||||
// 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,
|
||||
// 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
|
||||
|
@ -117,7 +117,7 @@ static void FindUses(Value *V, Function &F,
|
|||
// 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
|
||||
// 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.
|
||||
static Function *CreateWrapper(Function *F, FunctionType *Ty) {
|
||||
Module *M = F->getParent();
|
||||
|
@ -212,7 +212,8 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
|
|||
if (TypeMismatch) {
|
||||
// Create a new wrapper that simply contains `unreachable`.
|
||||
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);
|
||||
new UnreachableInst(M->getContext(), BB);
|
||||
Wrapper->setName(F->getName() + "_bitcast_invalid");
|
||||
|
@ -243,19 +244,15 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
|
|||
if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") {
|
||||
Main = &F;
|
||||
LLVMContext &C = M.getContext();
|
||||
Type *MainArgTys[] = {
|
||||
PointerType::get(Type::getInt8PtrTy(C), 0),
|
||||
Type::getInt32Ty(C)
|
||||
};
|
||||
Type *MainArgTys[] = {PointerType::get(Type::getInt8PtrTy(C), 0),
|
||||
Type::getInt32Ty(C)};
|
||||
FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys,
|
||||
/*isVarArg=*/false);
|
||||
if (F.getFunctionType() != MainTy) {
|
||||
Value *Args[] = {
|
||||
UndefValue::get(MainArgTys[0]),
|
||||
UndefValue::get(MainArgTys[1])
|
||||
};
|
||||
Value *Casted = ConstantExpr::getBitCast(Main,
|
||||
PointerType::get(MainTy, 0));
|
||||
Value *Args[] = {UndefValue::get(MainArgTys[0]),
|
||||
UndefValue::get(MainArgTys[1])};
|
||||
Value *Casted =
|
||||
ConstantExpr::getBitCast(Main, PointerType::get(MainTy, 0));
|
||||
CallMain = CallInst::Create(Casted, Args, "call_main");
|
||||
Use *UseMain = &CallMain->getOperandUse(2);
|
||||
Uses.push_back(std::make_pair(UseMain, &F));
|
||||
|
|
|
@ -43,8 +43,7 @@ using namespace llvm;
|
|||
/// require stricter alignment than the stack pointer itself. Because we need
|
||||
/// 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.
|
||||
bool WebAssemblyFrameLowering::hasBP(
|
||||
const MachineFunction &MF) const {
|
||||
bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const {
|
||||
const auto *RegInfo =
|
||||
MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
|
||||
return RegInfo->needsStackRealignment(MF);
|
||||
|
@ -158,7 +157,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
assert(MFI.getCalleeSavedInfo().empty() &&
|
||||
"WebAssembly should not have callee-saved registers");
|
||||
|
||||
if (!needsSP(MF)) return;
|
||||
if (!needsSP(MF))
|
||||
return;
|
||||
uint64_t StackSize = MFI.getStackSize();
|
||||
|
||||
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
||||
|
@ -202,7 +202,7 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC);
|
||||
unsigned Alignment = MFI.getMaxAlignment();
|
||||
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)
|
||||
.addImm((int)~(Alignment - 1));
|
||||
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),
|
||||
// FP points to the bottom of the fixed-size locals, so we can use positive
|
||||
// offsets in load/store instructions.
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY),
|
||||
WebAssembly::FP32)
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32)
|
||||
.addReg(WebAssembly::SP32);
|
||||
}
|
||||
if (StackSize && needsSPWriteback(MF)) {
|
||||
|
@ -226,7 +225,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
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();
|
||||
auto &MRI = MF.getRegInfo();
|
||||
auto InsertPt = MBB.getFirstTerminator();
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace llvm {
|
|||
class MachineFrameInfo;
|
||||
|
||||
class WebAssemblyFrameLowering final : public TargetFrameLowering {
|
||||
public:
|
||||
public:
|
||||
/// 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
|
||||
/// global).
|
||||
|
@ -35,9 +35,9 @@ class WebAssemblyFrameLowering final : public TargetFrameLowering {
|
|||
/*TransientStackAlignment=*/16,
|
||||
/*StackRealignable=*/true) {}
|
||||
|
||||
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(
|
||||
MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const override;
|
||||
MachineBasicBlock::iterator
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const override;
|
||||
|
||||
/// These methods insert prolog and epilog code into the function.
|
||||
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
|
||||
|
@ -61,6 +61,6 @@ private:
|
|||
bool needsSPWriteback(const MachineFunction &MF) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -95,8 +95,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
|||
ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
|
||||
setCondCodeAction(CC, T, Expand);
|
||||
// Expand floating-point library function operators.
|
||||
for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM,
|
||||
ISD::FMA})
|
||||
for (auto Op :
|
||||
{ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FMA})
|
||||
setOperationAction(Op, T, Expand);
|
||||
// Note supported floating-point library function operators that otherwise
|
||||
// default to expand.
|
||||
|
@ -116,10 +116,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
|||
for (auto T : {MVT::i32, MVT::i64}) {
|
||||
// Expand unavailable integer operations.
|
||||
for (auto Op :
|
||||
{ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI,
|
||||
ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS,
|
||||
ISD::SRA_PARTS, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC,
|
||||
ISD::SUBE}) {
|
||||
{ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
|
||||
ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
|
||||
ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
|
||||
setOperationAction(Op, T, Expand);
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +200,8 @@ bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
|
|||
MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
|
||||
EVT VT) const {
|
||||
unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
|
||||
if (BitWidth > 1 && BitWidth < 8) BitWidth = 8;
|
||||
if (BitWidth > 1 && BitWidth < 8)
|
||||
BitWidth = 8;
|
||||
|
||||
if (BitWidth > 64) {
|
||||
// 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
|
||||
// undefined result on invalid/overflow, to the WebAssembly opcode, which
|
||||
// traps on invalid/overflow.
|
||||
static MachineBasicBlock *
|
||||
LowerFPToInt(
|
||||
MachineInstr &MI,
|
||||
DebugLoc DL,
|
||||
MachineBasicBlock *BB,
|
||||
const TargetInstrInfo &TII,
|
||||
bool IsUnsigned,
|
||||
bool Int64,
|
||||
bool Float64,
|
||||
unsigned LoweredOpcode
|
||||
) {
|
||||
static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
|
||||
MachineBasicBlock *BB,
|
||||
const TargetInstrInfo &TII,
|
||||
bool IsUnsigned, bool Int64,
|
||||
bool Float64, unsigned LoweredOpcode) {
|
||||
MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
|
||||
|
||||
unsigned OutReg = MI.getOperand(0).getReg();
|
||||
|
@ -262,8 +256,7 @@ LowerFPToInt(
|
|||
|
||||
// Transfer the remainder of BB and its successor edges to DoneMBB.
|
||||
DoneMBB->splice(DoneMBB->begin(), BB,
|
||||
std::next(MachineBasicBlock::iterator(MI)),
|
||||
BB->end());
|
||||
std::next(MachineBasicBlock::iterator(MI)), BB->end());
|
||||
DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
|
||||
|
||||
BB->addSuccessor(TrueMBB);
|
||||
|
@ -285,45 +278,33 @@ LowerFPToInt(
|
|||
if (IsUnsigned) {
|
||||
Tmp0 = InReg;
|
||||
} else {
|
||||
BuildMI(BB, DL, TII.get(Abs), Tmp0)
|
||||
.addReg(InReg);
|
||||
BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
|
||||
}
|
||||
BuildMI(BB, DL, TII.get(FConst), Tmp1)
|
||||
.addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
|
||||
BuildMI(BB, DL, TII.get(LT), CmpReg)
|
||||
.addReg(Tmp0)
|
||||
.addReg(Tmp1);
|
||||
BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
|
||||
|
||||
// For unsigned numbers, we have to do a separate comparison with zero.
|
||||
if (IsUnsigned) {
|
||||
Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
|
||||
unsigned SecondCmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
|
||||
unsigned SecondCmpReg =
|
||||
MRI.createVirtualRegister(&WebAssembly::I32RegClass);
|
||||
unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
|
||||
BuildMI(BB, DL, TII.get(FConst), Tmp1)
|
||||
.addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
|
||||
BuildMI(BB, DL, TII.get(GE), SecondCmpReg)
|
||||
.addReg(Tmp0)
|
||||
.addReg(Tmp1);
|
||||
BuildMI(BB, DL, TII.get(And), AndReg)
|
||||
.addReg(CmpReg)
|
||||
.addReg(SecondCmpReg);
|
||||
BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
|
||||
BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
|
||||
CmpReg = AndReg;
|
||||
}
|
||||
|
||||
BuildMI(BB, DL, TII.get(Eqz), EqzReg)
|
||||
.addReg(CmpReg);
|
||||
BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
|
||||
|
||||
// Create the CFG diamond to select between doing the conversion or using
|
||||
// the substitute value.
|
||||
BuildMI(BB, DL, TII.get(WebAssembly::BR_IF))
|
||||
.addMBB(TrueMBB)
|
||||
.addReg(EqzReg);
|
||||
BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg)
|
||||
.addReg(InReg);
|
||||
BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR))
|
||||
.addMBB(DoneMBB);
|
||||
BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg)
|
||||
.addImm(Substitute);
|
||||
BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
|
||||
BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).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)
|
||||
.addReg(FalseReg)
|
||||
.addMBB(FalseMBB)
|
||||
|
@ -333,16 +314,14 @@ LowerFPToInt(
|
|||
return DoneMBB;
|
||||
}
|
||||
|
||||
MachineBasicBlock *
|
||||
WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
|
||||
MachineInstr &MI,
|
||||
MachineBasicBlock *BB
|
||||
) const {
|
||||
MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
|
||||
MachineInstr &MI, MachineBasicBlock *BB) const {
|
||||
const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
|
||||
DebugLoc DL = MI.getDebugLoc();
|
||||
|
||||
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:
|
||||
return LowerFPToInt(MI, DL, BB, TII, false, false, false,
|
||||
WebAssembly::I32_TRUNC_S_F32);
|
||||
|
@ -367,17 +346,17 @@ WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
|
|||
case WebAssembly::FP_TO_UINT_I64_F64:
|
||||
return LowerFPToInt(MI, DL, BB, TII, true, true, true,
|
||||
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(
|
||||
unsigned Opcode) const {
|
||||
const char *
|
||||
WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
|
||||
case WebAssemblyISD::FIRST_NUMBER:
|
||||
break;
|
||||
#define HANDLE_NODETYPE(NODE) \
|
||||
case WebAssemblyISD::NODE: \
|
||||
case WebAssemblyISD::FIRST_NUMBER:
|
||||
break;
|
||||
#define HANDLE_NODETYPE(NODE) \
|
||||
case WebAssemblyISD::NODE: \
|
||||
return "WebAssemblyISD::" #NODE;
|
||||
#include "WebAssemblyISD.def"
|
||||
#undef HANDLE_NODETYPE
|
||||
|
@ -392,21 +371,21 @@ WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
|
|||
// WebAssembly register class.
|
||||
if (Constraint.size() == 1) {
|
||||
switch (Constraint[0]) {
|
||||
case 'r':
|
||||
assert(VT != MVT::iPTR && "Pointer MVT not expected here");
|
||||
if (Subtarget->hasSIMD128() && VT.isVector()) {
|
||||
if (VT.getSizeInBits() == 128)
|
||||
return std::make_pair(0U, &WebAssembly::V128RegClass);
|
||||
}
|
||||
if (VT.isInteger() && !VT.isVector()) {
|
||||
if (VT.getSizeInBits() <= 32)
|
||||
return std::make_pair(0U, &WebAssembly::I32RegClass);
|
||||
if (VT.getSizeInBits() <= 64)
|
||||
return std::make_pair(0U, &WebAssembly::I64RegClass);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case 'r':
|
||||
assert(VT != MVT::iPTR && "Pointer MVT not expected here");
|
||||
if (Subtarget->hasSIMD128() && VT.isVector()) {
|
||||
if (VT.getSizeInBits() == 128)
|
||||
return std::make_pair(0U, &WebAssembly::V128RegClass);
|
||||
}
|
||||
if (VT.isInteger() && !VT.isVector()) {
|
||||
if (VT.getSizeInBits() <= 32)
|
||||
return std::make_pair(0U, &WebAssembly::I32RegClass);
|
||||
if (VT.getSizeInBits() <= 64)
|
||||
return std::make_pair(0U, &WebAssembly::I64RegClass);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,16 +404,17 @@ bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
|
|||
|
||||
bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
|
||||
const AddrMode &AM,
|
||||
Type *Ty,
|
||||
unsigned AS,
|
||||
Type *Ty, unsigned AS,
|
||||
Instruction *I) const {
|
||||
// WebAssembly offsets are added as unsigned without wrapping. The
|
||||
// isLegalAddressingMode gives us no way to determine if wrapping could be
|
||||
// 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.
|
||||
if (AM.Scale != 0) return false;
|
||||
if (AM.Scale != 0)
|
||||
return false;
|
||||
|
||||
// Everything else is legal.
|
||||
return true;
|
||||
|
@ -448,7 +428,8 @@ bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
|
|||
// for the kinds of things that LLVM uses this for (merging adjacent stores
|
||||
// of constants, etc.), WebAssembly implementations will either want the
|
||||
// unaligned access or they'll split anyway.
|
||||
if (Fast) *Fast = true;
|
||||
if (Fast)
|
||||
*Fast = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -535,8 +516,9 @@ static bool CallingConvSupported(CallingConv::ID CallConv) {
|
|||
CallConv == CallingConv::CXX_FAST_TLS;
|
||||
}
|
||||
|
||||
SDValue WebAssemblyTargetLowering::LowerCall(
|
||||
CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
|
||||
SDValue
|
||||
WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
|
||||
SmallVectorImpl<SDValue> &InVals) const {
|
||||
SelectionDAG &DAG = CLI.DAG;
|
||||
SDLoc DL = CLI.DL;
|
||||
SDValue Chain = CLI.Chain;
|
||||
|
@ -638,9 +620,9 @@ SDValue WebAssemblyTargetLowering::LowerCall(
|
|||
FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
|
||||
SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
|
||||
DAG.getConstant(Offset, DL, PtrVT));
|
||||
Chains.push_back(DAG.getStore(
|
||||
Chain, DL, Arg, Add,
|
||||
MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
|
||||
Chains.push_back(
|
||||
DAG.getStore(Chain, DL, Arg, Add,
|
||||
MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
|
||||
}
|
||||
if (!Chains.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
|
||||
|
@ -658,7 +640,8 @@ SDValue WebAssemblyTargetLowering::LowerCall(
|
|||
Ops.append(OutVals.begin(),
|
||||
IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
|
||||
// Add a pointer to the vararg buffer.
|
||||
if (IsVarArg) Ops.push_back(FINode);
|
||||
if (IsVarArg)
|
||||
Ops.push_back(FINode);
|
||||
|
||||
SmallVector<EVT, 8> InTys;
|
||||
for (const auto &In : Ins) {
|
||||
|
@ -752,11 +735,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments(
|
|||
fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
|
||||
// Ignore In.getOrigAlign() because all our arguments are passed in
|
||||
// registers.
|
||||
InVals.push_back(
|
||||
In.Used
|
||||
? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
|
||||
DAG.getTargetConstant(InVals.size(), DL, MVT::i32))
|
||||
: DAG.getUNDEF(In.VT));
|
||||
InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
|
||||
DAG.getTargetConstant(InVals.size(),
|
||||
DL, MVT::i32))
|
||||
: DAG.getUNDEF(In.VT));
|
||||
|
||||
// Record the number and types of arguments.
|
||||
MFI->addParam(In.VT);
|
||||
|
@ -794,34 +776,34 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
|
|||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
switch (Op.getOpcode()) {
|
||||
default:
|
||||
llvm_unreachable("unimplemented operation lowering");
|
||||
return SDValue();
|
||||
case ISD::FrameIndex:
|
||||
return LowerFrameIndex(Op, DAG);
|
||||
case ISD::GlobalAddress:
|
||||
return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::ExternalSymbol:
|
||||
return LowerExternalSymbol(Op, DAG);
|
||||
case ISD::JumpTable:
|
||||
return LowerJumpTable(Op, DAG);
|
||||
case ISD::BR_JT:
|
||||
return LowerBR_JT(Op, DAG);
|
||||
case ISD::VASTART:
|
||||
return LowerVASTART(Op, DAG);
|
||||
case ISD::BlockAddress:
|
||||
case ISD::BRIND:
|
||||
fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
|
||||
return SDValue();
|
||||
case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
|
||||
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
|
||||
return SDValue();
|
||||
case ISD::FRAMEADDR:
|
||||
return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::CopyToReg:
|
||||
return LowerCopyToReg(Op, DAG);
|
||||
case ISD::INTRINSIC_WO_CHAIN:
|
||||
return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||
default:
|
||||
llvm_unreachable("unimplemented operation lowering");
|
||||
return SDValue();
|
||||
case ISD::FrameIndex:
|
||||
return LowerFrameIndex(Op, DAG);
|
||||
case ISD::GlobalAddress:
|
||||
return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::ExternalSymbol:
|
||||
return LowerExternalSymbol(Op, DAG);
|
||||
case ISD::JumpTable:
|
||||
return LowerJumpTable(Op, DAG);
|
||||
case ISD::BR_JT:
|
||||
return LowerBR_JT(Op, DAG);
|
||||
case ISD::VASTART:
|
||||
return LowerVASTART(Op, DAG);
|
||||
case ISD::BlockAddress:
|
||||
case ISD::BRIND:
|
||||
fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
|
||||
return SDValue();
|
||||
case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
|
||||
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
|
||||
return SDValue();
|
||||
case ISD::FRAMEADDR:
|
||||
return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::CopyToReg:
|
||||
return LowerCopyToReg(Op, DAG);
|
||||
case ISD::INTRINSIC_WO_CHAIN:
|
||||
return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -838,16 +820,15 @@ SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
|
|||
SDLoc DL(Op);
|
||||
unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
|
||||
EVT VT = Src.getValueType();
|
||||
SDValue Copy(
|
||||
DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
|
||||
: WebAssembly::COPY_I64,
|
||||
DL, VT, Src),
|
||||
0);
|
||||
SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
|
||||
: WebAssembly::COPY_I64,
|
||||
DL, VT, Src),
|
||||
0);
|
||||
return Op.getNode()->getNumValues() == 1
|
||||
? DAG.getCopyToReg(Chain, DL, Reg, Copy)
|
||||
: DAG.getCopyToReg(Chain, DL, Reg, Copy, Op.getNumOperands() == 4
|
||||
? Op.getOperand(3)
|
||||
: SDValue());
|
||||
: DAG.getCopyToReg(Chain, DL, Reg, Copy,
|
||||
Op.getNumOperands() == 4 ? Op.getOperand(3)
|
||||
: SDValue());
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
|
@ -887,8 +868,9 @@ SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
|
|||
DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
|
||||
}
|
||||
|
||||
SDValue WebAssemblyTargetLowering::LowerExternalSymbol(
|
||||
SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue
|
||||
WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
const auto *ES = cast<ExternalSymbolSDNode>(Op);
|
||||
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
|
||||
// external symbols used in target-independent SelectionDAG code are for
|
||||
// functions.
|
||||
return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
|
||||
DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
|
||||
WebAssemblyII::MO_SYMBOL_FUNCTION));
|
||||
return DAG.getNode(
|
||||
WebAssemblyISD::Wrapper, DL, VT,
|
||||
DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
|
||||
WebAssemblyII::MO_SYMBOL_FUNCTION));
|
||||
}
|
||||
|
||||
SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
|
||||
|
@ -930,7 +913,8 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
|
|||
const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
|
||||
|
||||
// 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.
|
||||
// We really want to sniff out the guard and put in the real default case (and
|
||||
|
|
|
@ -29,17 +29,17 @@ enum NodeType : unsigned {
|
|||
#undef HANDLE_NODETYPE
|
||||
};
|
||||
|
||||
} // end namespace WebAssemblyISD
|
||||
} // end namespace WebAssemblyISD
|
||||
|
||||
class WebAssemblySubtarget;
|
||||
class WebAssemblyTargetMachine;
|
||||
|
||||
class WebAssemblyTargetLowering final : public TargetLowering {
|
||||
public:
|
||||
public:
|
||||
WebAssemblyTargetLowering(const TargetMachine &TM,
|
||||
const WebAssemblySubtarget &STI);
|
||||
|
||||
private:
|
||||
private:
|
||||
/// Keep a pointer to the WebAssemblySubtarget around so that we can make the
|
||||
/// right decision when generating code for different targets.
|
||||
const WebAssemblySubtarget *Subtarget;
|
||||
|
@ -53,9 +53,9 @@ class WebAssemblyTargetLowering final : public TargetLowering {
|
|||
EmitInstrWithCustomInserter(MachineInstr &MI,
|
||||
MachineBasicBlock *MBB) const override;
|
||||
const char *getTargetNodeName(unsigned Opcode) const override;
|
||||
std::pair<unsigned, const TargetRegisterClass *> getRegForInlineAsmConstraint(
|
||||
const TargetRegisterInfo *TRI, StringRef Constraint,
|
||||
MVT VT) const override;
|
||||
std::pair<unsigned, const TargetRegisterClass *>
|
||||
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||
StringRef Constraint, MVT VT) const override;
|
||||
bool isCheapToSpeculateCttz() const override;
|
||||
bool isCheapToSpeculateCtlz() const override;
|
||||
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
|
||||
|
@ -103,8 +103,8 @@ class WebAssemblyTargetLowering final : public TargetLowering {
|
|||
namespace WebAssembly {
|
||||
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
|
||||
const TargetLibraryInfo *libInfo);
|
||||
} // end namespace WebAssembly
|
||||
} // end namespace WebAssembly
|
||||
|
||||
} // end namespace llvm
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,10 +77,8 @@ void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|||
.addReg(SrcReg, KillSrc ? RegState::Kill : 0);
|
||||
}
|
||||
|
||||
MachineInstr *
|
||||
WebAssemblyInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const {
|
||||
MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(
|
||||
MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {
|
||||
// If the operands are stackified, we can't reorder them.
|
||||
WebAssemblyFunctionInfo &MFI =
|
||||
*MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
|
||||
|
@ -165,12 +163,9 @@ unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
|
|||
return Count;
|
||||
}
|
||||
|
||||
unsigned WebAssemblyInstrInfo::insertBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
ArrayRef<MachineOperand> Cond,
|
||||
const DebugLoc &DL,
|
||||
int *BytesAdded) const {
|
||||
unsigned WebAssemblyInstrInfo::insertBranch(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
|
||||
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
|
||||
assert(!BytesAdded && "code size not handled");
|
||||
|
||||
if (Cond.empty()) {
|
||||
|
|
|
@ -78,30 +78,102 @@ bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
|
|||
MachineInstr *Def = MRI.getVRegDef(Cond);
|
||||
switch (Def->getOpcode()) {
|
||||
using namespace WebAssembly;
|
||||
case EQ_I32: Def->setDesc(TII.get(NE_I32)); Inverted = true; break;
|
||||
case NE_I32: Def->setDesc(TII.get(EQ_I32)); Inverted = true; break;
|
||||
case GT_S_I32: Def->setDesc(TII.get(LE_S_I32)); Inverted = true; break;
|
||||
case GE_S_I32: Def->setDesc(TII.get(LT_S_I32)); Inverted = true; break;
|
||||
case LT_S_I32: Def->setDesc(TII.get(GE_S_I32)); Inverted = true; break;
|
||||
case LE_S_I32: Def->setDesc(TII.get(GT_S_I32)); Inverted = true; 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 EQ_I32:
|
||||
Def->setDesc(TII.get(NE_I32));
|
||||
Inverted = true;
|
||||
break;
|
||||
case NE_I32:
|
||||
Def->setDesc(TII.get(EQ_I32));
|
||||
Inverted = true;
|
||||
break;
|
||||
case GT_S_I32:
|
||||
Def->setDesc(TII.get(LE_S_I32));
|
||||
Inverted = true;
|
||||
break;
|
||||
case GE_S_I32:
|
||||
Def->setDesc(TII.get(LT_S_I32));
|
||||
Inverted = true;
|
||||
break;
|
||||
case LT_S_I32:
|
||||
Def->setDesc(TII.get(GE_S_I32));
|
||||
Inverted = true;
|
||||
break;
|
||||
case LE_S_I32:
|
||||
Def->setDesc(TII.get(GT_S_I32));
|
||||
Inverted = true;
|
||||
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: {
|
||||
// Invert an eqz by replacing it with its operand.
|
||||
Cond = Def->getOperand(1).getReg();
|
||||
|
@ -109,7 +181,8 @@ bool WebAssemblyLowerBrUnless::runOnMachineFunction(MachineFunction &MF) {
|
|||
Inverted = true;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "WebAssembly.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
using namespace llvm;
|
||||
|
||||
#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
|
||||
// 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()) {
|
||||
ConstantStruct *CS = dyn_cast<ConstantStruct>(O);
|
||||
if (!CS) continue; // Malformed.
|
||||
if (!CS)
|
||||
continue; // Malformed.
|
||||
|
||||
ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
|
||||
if (!Priority) continue; // Malformed.
|
||||
if (!Priority)
|
||||
continue; // Malformed.
|
||||
uint16_t PriorityValue = Priority->getLimitedValue(UINT16_MAX);
|
||||
|
||||
Constant *DtorFunc = CS->getOperand(1);
|
||||
if (DtorFunc->isNullValue())
|
||||
break; // Found a null terminator, skip the rest.
|
||||
break; // Found a null terminator, skip the rest.
|
||||
|
||||
Constant *Associated = CS->getOperand(2);
|
||||
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);
|
||||
LLVMContext &C = M.getContext();
|
||||
PointerType *VoidStar = Type::getInt8PtrTy(C);
|
||||
Type *AtExitFuncArgs[] = { VoidStar };
|
||||
FunctionType *AtExitFuncTy = FunctionType::get(
|
||||
Type::getVoidTy(C),
|
||||
AtExitFuncArgs,
|
||||
/*isVarArg=*/false);
|
||||
Type *AtExitFuncArgs[] = {VoidStar};
|
||||
FunctionType *AtExitFuncTy =
|
||||
FunctionType::get(Type::getVoidTy(C), AtExitFuncArgs,
|
||||
/*isVarArg=*/false);
|
||||
|
||||
Type *AtExitArgs[] = {
|
||||
PointerType::get(AtExitFuncTy, 0),
|
||||
VoidStar,
|
||||
VoidStar
|
||||
};
|
||||
FunctionType *AtExitTy = FunctionType::get(
|
||||
Type::getInt32Ty(C),
|
||||
AtExitArgs,
|
||||
/*isVarArg=*/false);
|
||||
Type *AtExitArgs[] = {PointerType::get(AtExitFuncTy, 0), VoidStar, VoidStar};
|
||||
FunctionType *AtExitTy = FunctionType::get(Type::getInt32Ty(C), AtExitArgs,
|
||||
/*isVarArg=*/false);
|
||||
Constant *AtExit = M.getOrInsertFunction("__cxa_atexit", AtExitTy);
|
||||
|
||||
// Declare __dso_local.
|
||||
Constant *DsoHandle = M.getNamedValue("__dso_handle");
|
||||
if (!DsoHandle) {
|
||||
Type *DsoHandleTy = Type::getInt8Ty(C);
|
||||
GlobalVariable *Handle =
|
||||
new GlobalVariable(M, DsoHandleTy, /*isConstant=*/true,
|
||||
GlobalVariable::ExternalWeakLinkage,
|
||||
nullptr, "__dso_handle");
|
||||
GlobalVariable *Handle = new GlobalVariable(
|
||||
M, DsoHandleTy, /*isConstant=*/true,
|
||||
GlobalVariable::ExternalWeakLinkage, nullptr, "__dso_handle");
|
||||
Handle->setVisibility(GlobalVariable::HiddenVisibility);
|
||||
DsoHandle = Handle;
|
||||
}
|
||||
|
@ -139,13 +133,13 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
|
|||
Constant *Associated = AssociatedAndMore.first;
|
||||
|
||||
Function *CallDtors = Function::Create(
|
||||
AtExitFuncTy, Function::PrivateLinkage,
|
||||
"call_dtors" +
|
||||
(Priority != UINT16_MAX ?
|
||||
(Twine(".") + Twine(Priority)) : Twine()) +
|
||||
(!Associated->isNullValue() ?
|
||||
(Twine(".") + Associated->getName()) : Twine()),
|
||||
&M);
|
||||
AtExitFuncTy, Function::PrivateLinkage,
|
||||
"call_dtors" +
|
||||
(Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
|
||||
: Twine()) +
|
||||
(!Associated->isNullValue() ? (Twine(".") + Associated->getName())
|
||||
: Twine()),
|
||||
&M);
|
||||
BasicBlock *BB = BasicBlock::Create(C, "body", CallDtors);
|
||||
|
||||
for (auto Dtor : AssociatedAndMore.second)
|
||||
|
@ -155,29 +149,29 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
|
|||
FunctionType *VoidVoid = FunctionType::get(Type::getVoidTy(C),
|
||||
/*isVarArg=*/false);
|
||||
Function *RegisterCallDtors = Function::Create(
|
||||
VoidVoid, Function::PrivateLinkage,
|
||||
"register_call_dtors" +
|
||||
(Priority != UINT16_MAX ?
|
||||
(Twine(".") + Twine(Priority)) : Twine()) +
|
||||
(!Associated->isNullValue() ?
|
||||
(Twine(".") + Associated->getName()) : Twine()),
|
||||
&M);
|
||||
VoidVoid, Function::PrivateLinkage,
|
||||
"register_call_dtors" +
|
||||
(Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
|
||||
: Twine()) +
|
||||
(!Associated->isNullValue() ? (Twine(".") + Associated->getName())
|
||||
: Twine()),
|
||||
&M);
|
||||
BasicBlock *EntryBB = BasicBlock::Create(C, "entry", RegisterCallDtors);
|
||||
BasicBlock *FailBB = BasicBlock::Create(C, "fail", RegisterCallDtors);
|
||||
BasicBlock *RetBB = BasicBlock::Create(C, "return", RegisterCallDtors);
|
||||
|
||||
Value *Null = ConstantPointerNull::get(VoidStar);
|
||||
Value *Args[] = { CallDtors, Null, DsoHandle };
|
||||
Value *Args[] = {CallDtors, Null, DsoHandle};
|
||||
Value *Res = CallInst::Create(AtExit, Args, "call", EntryBB);
|
||||
Value *Cmp = new ICmpInst(*EntryBB, ICmpInst::ICMP_NE, Res,
|
||||
Constant::getNullValue(Res->getType()));
|
||||
BranchInst::Create(FailBB, RetBB, Cmp, EntryBB);
|
||||
|
||||
// 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
|
||||
// before main has even started, something is wrong.
|
||||
CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap),
|
||||
"", FailBB);
|
||||
// This should be very rare, because if the process is running out of
|
||||
// memory before main has even started, something is wrong.
|
||||
CallInst::Create(Intrinsic::getDeclaration(&M, Intrinsic::trap), "",
|
||||
FailBB);
|
||||
new UnreachableInst(C, FailBB);
|
||||
|
||||
ReturnInst::Create(C, RetBB);
|
||||
|
|
|
@ -32,11 +32,11 @@ using namespace llvm;
|
|||
|
||||
// This disables the removal of registers when lowering into MC, as required
|
||||
// by some current tests.
|
||||
static cl::opt<bool> WasmKeepRegisters(
|
||||
"wasm-keep-registers", cl::Hidden,
|
||||
cl::desc("WebAssembly: output stack registers in"
|
||||
" instruction output for test purposes only."),
|
||||
cl::init(false));
|
||||
static cl::opt<bool>
|
||||
WasmKeepRegisters("wasm-keep-registers", cl::Hidden,
|
||||
cl::desc("WebAssembly: output stack registers in"
|
||||
" instruction output for test purposes only."),
|
||||
cl::init(false));
|
||||
|
||||
static unsigned regInstructionToStackInstruction(unsigned OpCode);
|
||||
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> Params;
|
||||
|
||||
wasm::ValType iPTR =
|
||||
MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() ?
|
||||
wasm::ValType::I64 :
|
||||
wasm::ValType::I32;
|
||||
wasm::ValType iPTR = MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
|
||||
? wasm::ValType::I64
|
||||
: wasm::ValType::I32;
|
||||
|
||||
SmallVector<MVT, 4> ResultMVTs;
|
||||
ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs);
|
||||
|
@ -122,9 +121,9 @@ MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
|
|||
bool IsFunc,
|
||||
bool IsGlob) const {
|
||||
MCSymbolRefExpr::VariantKind VK =
|
||||
IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION :
|
||||
IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
|
||||
: MCSymbolRefExpr::VK_None;
|
||||
IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION
|
||||
: IsGlob ? MCSymbolRefExpr::VK_WebAssembly_GLOBAL
|
||||
: MCSymbolRefExpr::VK_None;
|
||||
|
||||
const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
|
||||
|
||||
|
@ -238,7 +237,8 @@ void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
|
|||
// variable or a function.
|
||||
assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 &&
|
||||
"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_GLOBAL) != 0);
|
||||
break;
|
||||
|
@ -295,7 +295,7 @@ static unsigned regInstructionToStackInstruction(unsigned OpCode) {
|
|||
switch (OpCode) {
|
||||
default:
|
||||
llvm_unreachable(
|
||||
"unknown WebAssembly instruction in WebAssemblyMCInstLower pass");
|
||||
"unknown WebAssembly instruction in WebAssemblyMCInstLower pass");
|
||||
#include "WebAssemblyGenStackifier.inc"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyMCInstLower {
|
|||
|
||||
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
|
||||
MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset,
|
||||
bool IsFunc, bool IsGlob) const;
|
||||
MCOperand LowerSymbolOperand(MCSymbol *Sym, int64_t Offset, bool IsFunc,
|
||||
bool IsGlob) const;
|
||||
|
||||
public:
|
||||
WebAssemblyMCInstLower(MCContext &ctx, WebAssemblyAsmPrinter &printer)
|
||||
|
|
|
@ -50,7 +50,7 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
|||
// overaligned values on the user stack.
|
||||
unsigned BasePtrVreg = -1U;
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {}
|
||||
~WebAssemblyFunctionInfo() override;
|
||||
|
||||
|
@ -60,7 +60,10 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
|||
void addResult(MVT VT) { Results.push_back(VT); }
|
||||
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 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,
|
||||
Type *Ty, SmallVectorImpl<MVT> &ValueVTs);
|
||||
void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
|
||||
SmallVectorImpl<MVT> &ValueVTs);
|
||||
|
||||
void ComputeSignatureVTs(const Function &F, const TargetMachine &TM,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
|
|
|
@ -65,7 +65,8 @@ FunctionPass *llvm::createWebAssemblyOptimizeLiveIntervals() {
|
|||
return new WebAssemblyOptimizeLiveIntervals();
|
||||
}
|
||||
|
||||
bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
|
||||
MachineFunction &MF) {
|
||||
LLVM_DEBUG(dbgs() << "********** Optimize LiveIntervals **********\n"
|
||||
"********** Function: "
|
||||
<< MF.getName() << '\n');
|
||||
|
@ -76,11 +77,10 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF)
|
|||
// We don't preserve SSA form.
|
||||
MRI.leaveSSA();
|
||||
|
||||
assert(MRI.tracksLiveness() &&
|
||||
"OptimizeLiveIntervals expects liveness");
|
||||
assert(MRI.tracksLiveness() && "OptimizeLiveIntervals expects liveness");
|
||||
|
||||
// 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) {
|
||||
unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
|
||||
if (MRI.reg_nodbg_empty(Reg))
|
||||
|
@ -94,7 +94,7 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(MachineFunction &MF)
|
|||
// instructions to satisfy LiveIntervals' requirement that all uses be
|
||||
// dominated by defs. Now that LiveIntervals has computed which of these
|
||||
// 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++;
|
||||
if (MI->isImplicitDef() && MI->getOperand(0).isDead()) {
|
||||
LiveInterval &LI = LIS.getInterval(MI->getOperand(0).getReg());
|
||||
|
|
|
@ -70,7 +70,8 @@ static bool HasArgumentDef(unsigned Reg, const MachineRegisterInfo &MRI) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool WebAssemblyPrepareForLiveIntervals::runOnMachineFunction(
|
||||
MachineFunction &MF) {
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "********** Prepare For LiveIntervals **********\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
|
||||
// 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++;
|
||||
if (WebAssembly::isArgument(MI)) {
|
||||
MI.removeFromParent();
|
||||
|
|
|
@ -100,8 +100,7 @@ static void ConvertImplicitDefToConstZero(MachineInstr *MI,
|
|||
MachineFunction &MF) {
|
||||
assert(MI->getOpcode() == TargetOpcode::IMPLICIT_DEF);
|
||||
|
||||
const auto *RegClass =
|
||||
MRI.getRegClass(MI->getOperand(0).getReg());
|
||||
const auto *RegClass = MRI.getRegClass(MI->getOperand(0).getReg());
|
||||
if (RegClass == &WebAssembly::I32RegClass) {
|
||||
MI->setDesc(TII->get(WebAssembly::CONST_I32));
|
||||
MI->addOperand(MachineOperand::CreateImm(0));
|
||||
|
@ -187,14 +186,22 @@ static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
|
|||
}
|
||||
} else if (MI.hasOrderedMemoryRef()) {
|
||||
switch (MI.getOpcode()) {
|
||||
case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64:
|
||||
case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64:
|
||||
case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64:
|
||||
case WebAssembly::REM_U_I32: 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:
|
||||
case WebAssembly::DIV_S_I32:
|
||||
case WebAssembly::DIV_S_I64:
|
||||
case WebAssembly::REM_S_I32:
|
||||
case WebAssembly::REM_S_I64:
|
||||
case WebAssembly::DIV_U_I32:
|
||||
case WebAssembly::DIV_U_I64:
|
||||
case WebAssembly::REM_U_I32:
|
||||
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
|
||||
// because they trap on overflow and invalid so they can't be arbitrarily
|
||||
// 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.
|
||||
if (MI.hasUnmodeledSideEffects()) {
|
||||
switch (MI.getOpcode()) {
|
||||
case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64:
|
||||
case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64:
|
||||
case WebAssembly::DIV_U_I32: case WebAssembly::DIV_U_I64:
|
||||
case WebAssembly::REM_U_I32: 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:
|
||||
case WebAssembly::DIV_S_I32:
|
||||
case WebAssembly::DIV_S_I64:
|
||||
case WebAssembly::REM_S_I32:
|
||||
case WebAssembly::REM_S_I64:
|
||||
case WebAssembly::DIV_U_I32:
|
||||
case WebAssembly::DIV_U_I64:
|
||||
case WebAssembly::REM_U_I32:
|
||||
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
|
||||
// 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
|
||||
|
@ -251,8 +266,7 @@ static bool ShouldRematerialize(const MachineInstr &Def, AliasAnalysis &AA,
|
|||
// LiveIntervals to handle complex cases.
|
||||
static MachineInstr *GetVRegDef(unsigned Reg, const MachineInstr *Insert,
|
||||
const MachineRegisterInfo &MRI,
|
||||
const LiveIntervals &LIS)
|
||||
{
|
||||
const LiveIntervals &LIS) {
|
||||
// Most registers are in SSA form here so we try a quick MRI query first.
|
||||
if (MachineInstr *Def = MRI.getUniqueVRegDef(Reg))
|
||||
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
|
||||
// generalization of MachineRegisterInfo::hasOneUse that uses LiveIntervals
|
||||
// to handle complex cases.
|
||||
static bool HasOneUse(unsigned Reg, MachineInstr *Def,
|
||||
MachineRegisterInfo &MRI, MachineDominatorTree &MDT,
|
||||
LiveIntervals &LIS) {
|
||||
static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI,
|
||||
MachineDominatorTree &MDT, LiveIntervals &LIS) {
|
||||
// Most registers are in SSA form here so we try a quick MRI query first.
|
||||
if (MRI.hasOneUse(Reg))
|
||||
return true;
|
||||
|
||||
bool HasOne = false;
|
||||
const LiveInterval &LI = LIS.getInterval(Reg);
|
||||
const VNInfo *DefVNI = LI.getVNInfoAt(
|
||||
LIS.getInstructionIndex(*Def).getRegSlot());
|
||||
const VNInfo *DefVNI =
|
||||
LI.getVNInfoAt(LIS.getInstructionIndex(*Def).getRegSlot());
|
||||
assert(DefVNI);
|
||||
for (auto &I : MRI.use_nodbg_operands(Reg)) {
|
||||
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.
|
||||
static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS) {
|
||||
if (LIS.shrinkToUses(&LI)) {
|
||||
SmallVector<LiveInterval*, 4> SplitLIs;
|
||||
SmallVector<LiveInterval *, 4> SplitLIs;
|
||||
LIS.splitSeparateComponents(LI, SplitLIs);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand& Op,
|
||||
MachineInstr *Def,
|
||||
MachineBasicBlock &MBB,
|
||||
static MachineInstr *MoveForSingleUse(unsigned Reg, MachineOperand &Op,
|
||||
MachineInstr *Def, MachineBasicBlock &MBB,
|
||||
MachineInstr *Insert, LiveIntervals &LIS,
|
||||
WebAssemblyFunctionInfo &MFI,
|
||||
MachineRegisterInfo &MRI) {
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
using namespace llvm;
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ private:
|
|||
|
||||
char WebAssemblyReplacePhysRegs::ID = 0;
|
||||
INITIALIZE_PASS(WebAssemblyReplacePhysRegs, DEBUG_TYPE,
|
||||
"Replace physical registers with virtual registers",
|
||||
false, false)
|
||||
"Replace physical registers with virtual registers", false,
|
||||
false)
|
||||
|
||||
FunctionPass *llvm::createWebAssemblyReplacePhysRegs() {
|
||||
return new WebAssemblyReplacePhysRegs();
|
||||
|
@ -86,7 +86,7 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
|
|||
// Replace explicit uses of the physical register with a virtual register.
|
||||
const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(PReg);
|
||||
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++;
|
||||
if (!MO.isImplicit()) {
|
||||
if (VReg == WebAssembly::NoRegister)
|
||||
|
|
|
@ -88,7 +88,6 @@ enum RuntimeLibcallSignature {
|
|||
unsupported
|
||||
};
|
||||
|
||||
|
||||
struct RuntimeLibcallSignatureTable {
|
||||
std::vector<RuntimeLibcallSignature> Table;
|
||||
|
||||
|
@ -486,8 +485,6 @@ struct StaticLibcallNameMap {
|
|||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
|
||||
void llvm::GetSignature(const WebAssemblySubtarget &Subtarget,
|
||||
RTLIB::Libcall LC, SmallVectorImpl<wasm::ValType> &Rets,
|
||||
SmallVectorImpl<wasm::ValType> &Params) {
|
||||
|
@ -497,7 +494,7 @@ void llvm::GetSignature(const WebAssemblySubtarget &Subtarget,
|
|||
wasm::ValType iPTR =
|
||||
Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32;
|
||||
|
||||
auto& Table = RuntimeLibcallSignatures->Table;
|
||||
auto &Table = RuntimeLibcallSignatures->Table;
|
||||
switch (Table[LC]) {
|
||||
case func:
|
||||
break;
|
||||
|
@ -837,7 +834,7 @@ static ManagedStatic<StaticLibcallNameMap> LibcallNameMap;
|
|||
void llvm::GetSignature(const WebAssemblySubtarget &Subtarget, const char *Name,
|
||||
SmallVectorImpl<wasm::ValType> &Rets,
|
||||
SmallVectorImpl<wasm::ValType> &Params) {
|
||||
auto& Map = LibcallNameMap->Map;
|
||||
auto &Map = LibcallNameMap->Map;
|
||||
auto val = Map.find(Name);
|
||||
assert(val != Map.end() && "unexpected runtime library name");
|
||||
return GetSignature(Subtarget, val->second, Rets, Params);
|
||||
|
|
|
@ -60,8 +60,7 @@ static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
|
|||
assert(MI.hasOneMemOperand() &&
|
||||
"Load and store instructions have exactly one mem operand");
|
||||
assert((*MI.memoperands_begin())->getSize() ==
|
||||
(UINT64_C(1)
|
||||
<< WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
|
||||
(UINT64_C(1) << WebAssembly::GetDefaultP2Align(MI.getOpcode())) &&
|
||||
"Default p2align value should be natural");
|
||||
assert(MI.getDesc().OpInfo[OperandNo].OperandType ==
|
||||
WebAssembly::OPERAND_P2ALIGN &&
|
||||
|
@ -69,8 +68,8 @@ static void RewriteP2Align(MachineInstr &MI, unsigned OperandNo) {
|
|||
uint64_t P2Align = Log2_64((*MI.memoperands_begin())->getAlignment());
|
||||
|
||||
// WebAssembly does not currently support supernatural alignment.
|
||||
P2Align = std::min(
|
||||
P2Align, uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
|
||||
P2Align = std::min(P2Align,
|
||||
uint64_t(WebAssembly::GetDefaultP2Align(MI.getOpcode())));
|
||||
|
||||
MI.getOperand(OperandNo).setImm(P2Align);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
|
|||
|
||||
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++;
|
||||
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 (!FromLI->liveAt(FromIdx.getDeadSlot()))
|
||||
MI.addRegisterKilled(FromReg,
|
||||
MBB.getParent()->getSubtarget<WebAssemblySubtarget>()
|
||||
.getRegisterInfo());
|
||||
MI.addRegisterKilled(FromReg, MBB.getParent()
|
||||
->getSubtarget<WebAssemblySubtarget>()
|
||||
.getRegisterInfo());
|
||||
}
|
||||
|
||||
return Changed;
|
||||
|
@ -142,8 +143,7 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
|
|||
|
||||
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI,
|
||||
const MachineRegisterInfo &MRI,
|
||||
MachineDominatorTree &MDT,
|
||||
LiveIntervals &LIS,
|
||||
MachineDominatorTree &MDT, LiveIntervals &LIS,
|
||||
const WebAssemblyTargetLowering &TLI,
|
||||
const TargetLibraryInfo &LibInfo) {
|
||||
MachineOperand &Op1 = MI.getOperand(1);
|
||||
|
|
|
@ -150,7 +150,7 @@ class StripThreadLocal final : public ModulePass {
|
|||
// pass just converts all GlobalVariables to NotThreadLocal
|
||||
static char ID;
|
||||
|
||||
public:
|
||||
public:
|
||||
StripThreadLocal() : ModulePass(ID) {}
|
||||
bool runOnModule(Module &M) override {
|
||||
for (auto &GV : M.globals())
|
||||
|
|
|
@ -23,28 +23,22 @@ using namespace object;
|
|||
namespace {
|
||||
|
||||
static const EnumEntry<unsigned> WasmSymbolTypes[] = {
|
||||
#define ENUM_ENTRY(X) { #X, wasm::WASM_SYMBOL_TYPE_##X }
|
||||
ENUM_ENTRY(FUNCTION),
|
||||
ENUM_ENTRY(DATA),
|
||||
ENUM_ENTRY(GLOBAL),
|
||||
ENUM_ENTRY(SECTION),
|
||||
#define ENUM_ENTRY(X) \
|
||||
{ #X, wasm::WASM_SYMBOL_TYPE_##X }
|
||||
ENUM_ENTRY(FUNCTION),
|
||||
ENUM_ENTRY(DATA),
|
||||
ENUM_ENTRY(GLOBAL),
|
||||
ENUM_ENTRY(SECTION),
|
||||
#undef ENUM_ENTRY
|
||||
};
|
||||
|
||||
static const EnumEntry<uint32_t> WasmSectionTypes[] = {
|
||||
#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
|
||||
ENUM_ENTRY(CUSTOM),
|
||||
ENUM_ENTRY(TYPE),
|
||||
ENUM_ENTRY(IMPORT),
|
||||
ENUM_ENTRY(FUNCTION),
|
||||
ENUM_ENTRY(TABLE),
|
||||
ENUM_ENTRY(MEMORY),
|
||||
ENUM_ENTRY(GLOBAL),
|
||||
ENUM_ENTRY(EXPORT),
|
||||
ENUM_ENTRY(START),
|
||||
ENUM_ENTRY(ELEM),
|
||||
ENUM_ENTRY(CODE),
|
||||
ENUM_ENTRY(DATA),
|
||||
#define ENUM_ENTRY(X) \
|
||||
{ #X, wasm::WASM_SEC_##X }
|
||||
ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
|
||||
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
|
||||
ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EXPORT), ENUM_ENTRY(START),
|
||||
ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE), ENUM_ENTRY(DATA),
|
||||
#undef ENUM_ENTRY
|
||||
};
|
||||
|
||||
|
@ -108,7 +102,7 @@ void WasmDumper::printRelocation(const SectionRef &Section,
|
|||
if (HasAddend)
|
||||
W.printNumber("Addend", WasmReloc.Addend);
|
||||
} else {
|
||||
raw_ostream& OS = W.startLine();
|
||||
raw_ostream &OS = W.startLine();
|
||||
OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
|
||||
if (!SymName.empty())
|
||||
OS << SymName;
|
||||
|
@ -169,7 +163,7 @@ void WasmDumper::printSections() {
|
|||
const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
|
||||
if (!LinkingData.InitFunctions.empty()) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +171,7 @@ void WasmDumper::printSections() {
|
|||
case wasm::WASM_SEC_DATA: {
|
||||
ListScope Group(W, "Segments");
|
||||
for (const WasmSegment &Segment : Obj->dataSegments()) {
|
||||
const wasm::WasmDataSegment& Seg = Segment.Data;
|
||||
const wasm::WasmDataSegment &Seg = Segment.Data;
|
||||
DictScope Group(W, "Segment");
|
||||
if (!Seg.Name.empty())
|
||||
W.printString("Name", Seg.Name);
|
||||
|
@ -219,7 +213,7 @@ void WasmDumper::printSymbol(const SymbolRef &Sym) {
|
|||
W.printHex("Flags", Symbol.Info.Flags);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
|
|
@ -49,11 +49,13 @@ static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
|
|||
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;
|
||||
if (WasmSec.Name == "name") {
|
||||
std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
|
||||
for (const llvm::wasm::WasmFunctionName &Func: Obj.debugNames()) {
|
||||
std::unique_ptr<WasmYAML::NameSection> NameSec =
|
||||
make_unique<WasmYAML::NameSection>();
|
||||
for (const llvm::wasm::WasmFunctionName &Func : Obj.debugNames()) {
|
||||
WasmYAML::NameEntry NameEntry;
|
||||
NameEntry.Name = Func.Name;
|
||||
NameEntry.Index = Func.Index;
|
||||
|
@ -61,7 +63,8 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
|
|||
}
|
||||
CustomSec = std::move(NameSec);
|
||||
} 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;
|
||||
|
||||
ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
|
||||
|
@ -70,7 +73,7 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
|
|||
for (auto &Func : Obj.functions()) {
|
||||
if (Func.Comdat != UINT32_MAX) {
|
||||
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");
|
||||
break;
|
||||
}
|
||||
for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
|
||||
for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
|
||||
WasmYAML::Relocation R;
|
||||
R.Type = Reloc.Type;
|
||||
R.Index = Reloc.Index;
|
||||
|
|
|
@ -127,12 +127,11 @@ public:
|
|||
OutString.clear();
|
||||
}
|
||||
|
||||
raw_ostream& GetStream() {
|
||||
return StringStream;
|
||||
}
|
||||
raw_ostream &GetStream() { return StringStream; }
|
||||
};
|
||||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||
WasmYAML::LinkingSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
encodeULEB128(Section.Version, OS);
|
||||
|
||||
|
@ -218,7 +217,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S
|
|||
return 0;
|
||||
}
|
||||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||
WasmYAML::NameSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
if (Section.FunctionNames.size()) {
|
||||
writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
|
||||
|
@ -296,7 +296,7 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||
writeLimits(Import.Memory, OS);
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_TABLE:
|
||||
writeUint8(OS,Import.TableImport.ElemType);
|
||||
writeUint8(OS, Import.TableImport.ElemType);
|
||||
writeLimits(Import.TableImport.TableLimits, OS);
|
||||
break;
|
||||
default:
|
||||
|
@ -428,47 +428,46 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||
int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
||||
uint32_t SectionIndex) {
|
||||
switch (Sec.Type) {
|
||||
case wasm::WASM_SEC_CODE:
|
||||
writeStringRef("reloc.CODE", OS);
|
||||
break;
|
||||
case wasm::WASM_SEC_DATA:
|
||||
writeStringRef("reloc.DATA", OS);
|
||||
break;
|
||||
case wasm::WASM_SEC_CUSTOM: {
|
||||
auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
|
||||
if (!CustomSection->Name.startswith(".debug_")) {
|
||||
llvm_unreachable("not yet implemented (only for debug sections)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
writeStringRef(("reloc." + CustomSection->Name).str(), OS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("not yet implemented");
|
||||
case wasm::WASM_SEC_CODE:
|
||||
writeStringRef("reloc.CODE", OS);
|
||||
break;
|
||||
case wasm::WASM_SEC_DATA:
|
||||
writeStringRef("reloc.DATA", OS);
|
||||
break;
|
||||
case wasm::WASM_SEC_CUSTOM: {
|
||||
auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
|
||||
if (!CustomSection->Name.startswith(".debug_")) {
|
||||
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;
|
||||
}
|
||||
|
||||
encodeULEB128(SectionIndex, OS);
|
||||
encodeULEB128(Sec.Relocations.size(), OS);
|
||||
|
||||
for (auto Reloc: Sec.Relocations) {
|
||||
for (auto Reloc : Sec.Relocations) {
|
||||
writeUint8(OS, Reloc.Type);
|
||||
encodeULEB128(Reloc.Offset, OS);
|
||||
encodeULEB128(Reloc.Index, OS);
|
||||
switch (Reloc.Type) {
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||
case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
|
||||
case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
|
||||
encodeULEB128(Reloc.Addend, OS);
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||
case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
|
||||
case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
|
||||
encodeULEB128(Reloc.Addend, OS);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int WasmWriter::writeWasm(raw_ostream &OS) {
|
||||
// Write headers
|
||||
OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
|
||||
|
|
Loading…
Reference in New Issue