[WebAssembly] Second phase of implemented extended const proposal

This change continues to lay the ground work for supporting extended
const expressions in the linker.

The included test covers object file reading and writing and the YAML
representation.

Differential Revision: https://reviews.llvm.org/D121349
This commit is contained in:
Sam Clegg 2022-03-09 18:11:44 -08:00
parent 8361c5da30
commit 9504ab32b7
15 changed files with 271 additions and 130 deletions

View File

@ -44,12 +44,13 @@ protected:
inline WasmInitExpr intConst(uint64_t value, bool is64) {
WasmInitExpr ie;
ie.Extended = false;
if (is64) {
ie.Opcode = llvm::wasm::WASM_OPCODE_I64_CONST;
ie.Value.Int64 = static_cast<int64_t>(value);
ie.Inst.Opcode = llvm::wasm::WASM_OPCODE_I64_CONST;
ie.Inst.Value.Int64 = static_cast<int64_t>(value);
} else {
ie.Opcode = llvm::wasm::WASM_OPCODE_I32_CONST;
ie.Value.Int32 = static_cast<int32_t>(value);
ie.Inst.Opcode = llvm::wasm::WASM_OPCODE_I32_CONST;
ie.Inst.Value.Int32 = static_cast<int32_t>(value);
}
return ie;
}

View File

@ -412,10 +412,12 @@ void ObjFile::parse(bool ignoreComdats) {
tableEntries.resize(totalFunctions);
for (const WasmElemSegment &seg : wasmObj->elements()) {
int64_t offset;
if (seg.Offset.Opcode == WASM_OPCODE_I32_CONST)
offset = seg.Offset.Value.Int32;
else if (seg.Offset.Opcode == WASM_OPCODE_I64_CONST)
offset = seg.Offset.Value.Int64;
if (seg.Offset.Extended)
fatal(toString(this) + ": extended init exprs not supported");
else if (seg.Offset.Inst.Opcode == WASM_OPCODE_I32_CONST)
offset = seg.Offset.Inst.Value.Int32;
else if (seg.Offset.Inst.Opcode == WASM_OPCODE_I64_CONST)
offset = seg.Offset.Inst.Value.Int64;
else
fatal(toString(this) + ": invalid table elements");
for (size_t index = 0; index < seg.Functions.size(); index++) {

View File

@ -159,9 +159,10 @@ void DataSection::finalizeContents() {
writeUleb128(os, 0, "memory index");
if ((segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
WasmInitExpr initExpr;
initExpr.Extended = false;
if (config->isPic) {
initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
initExpr.Inst.Value.Global = WasmSym::memoryBase->getGlobalIndex();
} else {
initExpr = intConst(segment->startVA, config->is64.getValueOr(false));
}

View File

@ -542,15 +542,16 @@ void ElemSection::writeBody() {
writeUleb128(os, tableNumber, "table number");
WasmInitExpr initExpr;
initExpr.Extended = false;
if (config->isPic) {
initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
initExpr.Value.Global =
initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
initExpr.Inst.Value.Global =
(config->is64.getValueOr(false) ? WasmSym::tableBase32
: WasmSym::tableBase)
->getGlobalIndex();
} else {
initExpr.Opcode = WASM_OPCODE_I32_CONST;
initExpr.Value.Int32 = config->tableBase;
initExpr.Inst.Opcode = WASM_OPCODE_I32_CONST;
initExpr.Inst.Value.Int32 = config->tableBase;
}
writeInitExpr(os, initExpr);

View File

@ -159,6 +159,11 @@ void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset) {
}
void writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
assert(!initExpr.Extended);
writeInitExprMVP(os, initExpr.Inst);
}
void writeInitExprMVP(raw_ostream &os, const WasmInitExprMVP &initExpr) {
writeU8(os, initExpr.Opcode, "opcode");
switch (initExpr.Opcode) {
case WASM_OPCODE_I32_CONST:

View File

@ -51,6 +51,9 @@ void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset);
void writeInitExpr(raw_ostream &os, const llvm::wasm::WasmInitExpr &initExpr);
void writeInitExprMVP(raw_ostream &os,
const llvm::wasm::WasmInitExprMVP &initExpr);
void writeLimits(raw_ostream &os, const llvm::wasm::WasmLimits &limits);
void writeGlobalType(raw_ostream &os, const llvm::wasm::WasmGlobalType &type);

View File

@ -91,7 +91,7 @@ struct WasmTable {
StringRef SymbolName; // from the "linking" section
};
struct WasmInitExpr {
struct WasmInitExprMVP {
uint8_t Opcode;
union {
int32_t Int32;
@ -102,6 +102,13 @@ struct WasmInitExpr {
} Value;
};
struct WasmInitExpr {
uint8_t Extended; // Set to non-zero if extended const is used (i.e. more than
// one instruction)
WasmInitExprMVP Inst;
ArrayRef<uint8_t> Body;
};
struct WasmGlobalType {
uint8_t Type;
bool Mutable;
@ -285,7 +292,11 @@ enum : unsigned {
WASM_OPCODE_F32_CONST = 0x43,
WASM_OPCODE_F64_CONST = 0x44,
WASM_OPCODE_I32_ADD = 0x6a,
WASM_OPCODE_I32_SUB = 0x6b,
WASM_OPCODE_I32_MUL = 0x6c,
WASM_OPCODE_I64_ADD = 0x7c,
WASM_OPCODE_I64_SUB = 0x7d,
WASM_OPCODE_I64_MUL = 0x7e,
WASM_OPCODE_REF_NULL = 0xd0,
};

View File

@ -62,11 +62,20 @@ struct Export {
uint32_t Index;
};
struct InitExpr {
InitExpr() {}
bool Extended;
union {
wasm::WasmInitExprMVP Inst;
yaml::BinaryRef Body;
};
};
struct ElemSegment {
uint32_t Flags;
uint32_t TableNumber;
ValueType ElemKind;
wasm::WasmInitExpr Offset;
InitExpr Offset;
std::vector<uint32_t> Functions;
};
@ -74,19 +83,20 @@ struct Global {
uint32_t Index;
ValueType Type;
bool Mutable;
wasm::WasmInitExpr InitExpr;
InitExpr InitExpr;
};
struct Import {
Import() {}
StringRef Module;
StringRef Field;
ExportKind Kind;
union {
uint32_t SigIndex;
Global GlobalImport;
Table TableImport;
Limits Memory;
uint32_t TagIndex;
Global GlobalImport;
};
};
@ -114,7 +124,7 @@ struct DataSegment {
uint32_t SectionOffset;
uint32_t InitFlags;
uint32_t MemoryIndex;
wasm::WasmInitExpr Offset;
InitExpr Offset;
yaml::BinaryRef Content;
};
@ -526,8 +536,8 @@ template <> struct MappingTraits<WasmYAML::LocalDecl> {
static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
};
template <> struct MappingTraits<wasm::WasmInitExpr> {
static void mapping(IO &IO, wasm::WasmInitExpr &Expr);
template <> struct MappingTraits<WasmYAML::InitExpr> {
static void mapping(IO &IO, WasmYAML::InitExpr &Expr);
};
template <> struct MappingTraits<WasmYAML::DataSegment> {

View File

@ -931,25 +931,29 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
for (const wasm::WasmGlobal &Global : Globals) {
encodeULEB128(Global.Type.Type, W->OS);
W->OS << char(Global.Type.Mutable);
W->OS << char(Global.InitExpr.Opcode);
switch (Global.Type.Type) {
case wasm::WASM_TYPE_I32:
encodeSLEB128(0, W->OS);
break;
case wasm::WASM_TYPE_I64:
encodeSLEB128(0, W->OS);
break;
case wasm::WASM_TYPE_F32:
writeI32(0);
break;
case wasm::WASM_TYPE_F64:
writeI64(0);
break;
case wasm::WASM_TYPE_EXTERNREF:
writeValueType(wasm::ValType::EXTERNREF);
break;
default:
llvm_unreachable("unexpected type");
if (Global.InitExpr.Extended) {
llvm_unreachable("extected init expressions not supported");
} else {
W->OS << char(Global.InitExpr.Inst.Opcode);
switch (Global.Type.Type) {
case wasm::WASM_TYPE_I32:
encodeSLEB128(0, W->OS);
break;
case wasm::WASM_TYPE_I64:
encodeSLEB128(0, W->OS);
break;
case wasm::WASM_TYPE_F32:
writeI32(0);
break;
case wasm::WASM_TYPE_F64:
writeI64(0);
break;
case wasm::WASM_TYPE_EXTERNREF:
writeValueType(wasm::ValType::EXTERNREF);
break;
default:
llvm_unreachable("unexpected type");
}
}
W->OS << char(wasm::WASM_OPCODE_END);
}
@ -1658,21 +1662,22 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
wasm::WasmGlobal Global;
Global.Type = WS.getGlobalType();
Global.Index = NumGlobalImports + Globals.size();
Global.InitExpr.Extended = false;
switch (Global.Type.Type) {
case wasm::WASM_TYPE_I32:
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
break;
case wasm::WASM_TYPE_I64:
Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_I64_CONST;
break;
case wasm::WASM_TYPE_F32:
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_F32_CONST;
break;
case wasm::WASM_TYPE_F64:
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_F64_CONST;
break;
case wasm::WASM_TYPE_EXTERNREF:
Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_REF_NULL;
break;
default:
llvm_unreachable("unexpected type");

View File

@ -164,23 +164,25 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
static Error readInitExpr(wasm::WasmInitExpr &Expr,
WasmObjectFile::ReadContext &Ctx) {
Expr.Opcode = readOpcode(Ctx);
auto Start = Ctx.Ptr;
switch (Expr.Opcode) {
Expr.Extended = false;
Expr.Inst.Opcode = readOpcode(Ctx);
switch (Expr.Inst.Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
Expr.Value.Int32 = readVarint32(Ctx);
Expr.Inst.Value.Int32 = readVarint32(Ctx);
break;
case wasm::WASM_OPCODE_I64_CONST:
Expr.Value.Int64 = readVarint64(Ctx);
Expr.Inst.Value.Int64 = readVarint64(Ctx);
break;
case wasm::WASM_OPCODE_F32_CONST:
Expr.Value.Float32 = readFloat32(Ctx);
Expr.Inst.Value.Float32 = readFloat32(Ctx);
break;
case wasm::WASM_OPCODE_F64_CONST:
Expr.Value.Float64 = readFloat64(Ctx);
Expr.Inst.Value.Float64 = readFloat64(Ctx);
break;
case wasm::WASM_OPCODE_GLOBAL_GET:
Expr.Value.Global = readULEB128(Ctx);
Expr.Inst.Value.Global = readULEB128(Ctx);
break;
case wasm::WASM_OPCODE_REF_NULL: {
wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
@ -191,15 +193,46 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
break;
}
default:
return make_error<GenericBinaryError>("invalid opcode in init_expr",
object_error::parse_failed);
Expr.Extended = true;
}
uint8_t EndOpcode = readOpcode(Ctx);
if (EndOpcode != wasm::WASM_OPCODE_END) {
return make_error<GenericBinaryError>("invalid init_expr",
object_error::parse_failed);
if (!Expr.Extended) {
uint8_t EndOpcode = readOpcode(Ctx);
if (EndOpcode != wasm::WASM_OPCODE_END)
Expr.Extended = true;
}
if (Expr.Extended) {
Ctx.Ptr = Start;
while (1) {
uint8_t Opcode = readOpcode(Ctx);
switch (Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
case wasm::WASM_OPCODE_GLOBAL_GET:
case wasm::WASM_OPCODE_REF_NULL:
case wasm::WASM_OPCODE_I64_CONST:
case wasm::WASM_OPCODE_F32_CONST:
case wasm::WASM_OPCODE_F64_CONST:
readULEB128(Ctx);
break;
case wasm::WASM_OPCODE_I32_ADD:
case wasm::WASM_OPCODE_I32_SUB:
case wasm::WASM_OPCODE_I32_MUL:
case wasm::WASM_OPCODE_I64_ADD:
case wasm::WASM_OPCODE_I64_SUB:
case wasm::WASM_OPCODE_I64_MUL:
break;
case wasm::WASM_OPCODE_END:
Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
return Error::success();
default:
return make_error<GenericBinaryError>(
Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
object_error::parse_failed);
}
}
}
return Error::success();
}
@ -1441,8 +1474,8 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
object_error::parse_failed);
if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Value.Int32 = 0;
Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Inst.Value.Int32 = 0;
} else {
if (Error Err = readInitExpr(Segment.Offset, Ctx))
return Err;
@ -1501,8 +1534,8 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
return Err;
} else {
Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Data.Offset.Value.Int32 = 0;
Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Data.Offset.Inst.Value.Int32 = 0;
}
uint32_t Size = readVaruint32(Ctx);
if (Size > (size_t)(Ctx.End - Ctx.Ptr))
@ -1600,10 +1633,12 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
// offset within the segment.
uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
} else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
if (Segment.Offset.Extended) {
llvm_unreachable("extended init exprs not supported");
} else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
} else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
} else {
llvm_unreachable("unknown init expr opcode");
}

View File

@ -33,7 +33,7 @@ private:
void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
uint32_t SectionIndex);
void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &InitExpr);
void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
@ -129,29 +129,34 @@ void WasmWriter::reportError(const Twine &Msg) {
}
void WasmWriter::writeInitExpr(raw_ostream &OS,
const wasm::WasmInitExpr &InitExpr) {
writeUint8(OS, InitExpr.Opcode);
switch (InitExpr.Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
encodeSLEB128(InitExpr.Value.Int32, OS);
break;
case wasm::WASM_OPCODE_I64_CONST:
encodeSLEB128(InitExpr.Value.Int64, OS);
break;
case wasm::WASM_OPCODE_F32_CONST:
writeUint32(OS, InitExpr.Value.Float32);
break;
case wasm::WASM_OPCODE_F64_CONST:
writeUint64(OS, InitExpr.Value.Float64);
break;
case wasm::WASM_OPCODE_GLOBAL_GET:
encodeULEB128(InitExpr.Value.Global, OS);
break;
default:
reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
return;
const WasmYAML::InitExpr &InitExpr) {
if (InitExpr.Extended) {
InitExpr.Body.writeAsBinary(OS);
} else {
writeUint8(OS, InitExpr.Inst.Opcode);
switch (InitExpr.Inst.Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
encodeSLEB128(InitExpr.Inst.Value.Int32, OS);
break;
case wasm::WASM_OPCODE_I64_CONST:
encodeSLEB128(InitExpr.Inst.Value.Int64, OS);
break;
case wasm::WASM_OPCODE_F32_CONST:
writeUint32(OS, InitExpr.Inst.Value.Float32);
break;
case wasm::WASM_OPCODE_F64_CONST:
writeUint64(OS, InitExpr.Inst.Value.Float64);
break;
case wasm::WASM_OPCODE_GLOBAL_GET:
encodeULEB128(InitExpr.Inst.Value.Global, OS);
break;
default:
reportError("unknown opcode in init_expr: " +
Twine(InitExpr.Inst.Opcode));
return;
}
writeUint8(OS, wasm::WASM_OPCODE_END);
}
writeUint8(OS, wasm::WASM_OPCODE_END);
}
void WasmWriter::writeSectionContent(raw_ostream &OS,

View File

@ -367,8 +367,7 @@ void MappingTraits<WasmYAML::LocalDecl>::mapping(
void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
WasmYAML::Limits &Limits) {
if (!IO.outputting() || Limits.Flags)
IO.mapOptional("Flags", Limits.Flags);
IO.mapOptional("Flags", Limits.Flags, 0);
IO.mapRequired("Minimum", Limits.Minimum);
if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
IO.mapOptional("Maximum", Limits.Maximum);
@ -376,8 +375,7 @@ void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
void MappingTraits<WasmYAML::ElemSegment>::mapping(
IO &IO, WasmYAML::ElemSegment &Segment) {
if (!IO.outputting() || Segment.Flags)
IO.mapOptional("Flags", Segment.Flags);
IO.mapOptional("Flags", Segment.Flags, 0);
if (!IO.outputting() ||
Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
IO.mapOptional("TableNumber", Segment.TableNumber);
@ -423,32 +421,37 @@ void MappingTraits<WasmYAML::Global>::mapping(IO &IO,
IO.mapRequired("InitExpr", Global.InitExpr);
}
void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
wasm::WasmInitExpr &Expr) {
WasmYAML::Opcode Op = Expr.Opcode;
IO.mapRequired("Opcode", Op);
Expr.Opcode = Op;
switch (Expr.Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
IO.mapRequired("Value", Expr.Value.Int32);
break;
case wasm::WASM_OPCODE_I64_CONST:
IO.mapRequired("Value", Expr.Value.Int64);
break;
case wasm::WASM_OPCODE_F32_CONST:
IO.mapRequired("Value", Expr.Value.Float32);
break;
case wasm::WASM_OPCODE_F64_CONST:
IO.mapRequired("Value", Expr.Value.Float64);
break;
case wasm::WASM_OPCODE_GLOBAL_GET:
IO.mapRequired("Index", Expr.Value.Global);
break;
case wasm::WASM_OPCODE_REF_NULL: {
WasmYAML::ValueType Ty = wasm::WASM_TYPE_EXTERNREF;
IO.mapRequired("Type", Ty);
break;
}
void MappingTraits<WasmYAML::InitExpr>::mapping(IO &IO,
WasmYAML::InitExpr &Expr) {
IO.mapOptional("Extended", Expr.Extended, false);
if (Expr.Extended) {
IO.mapRequired("Body", Expr.Body);
} else {
WasmYAML::Opcode Op = Expr.Inst.Opcode;
IO.mapRequired("Opcode", Op);
Expr.Inst.Opcode = Op;
switch (Expr.Inst.Opcode) {
case wasm::WASM_OPCODE_I32_CONST:
IO.mapRequired("Value", Expr.Inst.Value.Int32);
break;
case wasm::WASM_OPCODE_I64_CONST:
IO.mapRequired("Value", Expr.Inst.Value.Int64);
break;
case wasm::WASM_OPCODE_F32_CONST:
IO.mapRequired("Value", Expr.Inst.Value.Float32);
break;
case wasm::WASM_OPCODE_F64_CONST:
IO.mapRequired("Value", Expr.Inst.Value.Float64);
break;
case wasm::WASM_OPCODE_GLOBAL_GET:
IO.mapRequired("Index", Expr.Inst.Value.Global);
break;
case wasm::WASM_OPCODE_REF_NULL: {
WasmYAML::ValueType Ty = wasm::WASM_TYPE_EXTERNREF;
IO.mapRequired("Type", Ty);
break;
}
}
}
}
@ -464,8 +467,8 @@ void MappingTraits<WasmYAML::DataSegment>::mapping(
if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
IO.mapRequired("Offset", Segment.Offset);
} else {
Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Value.Int32 = 0;
Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Inst.Value.Int32 = 0;
}
IO.mapRequired("Content", Segment.Content);
}

View File

@ -0,0 +1,42 @@
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
--- !WASM
FileHeader:
Version: 0x00000001
Sections:
- Type: GLOBAL
Globals:
- Index: 0
Type: I32
Mutable: false
InitExpr:
# "extended" encoding of init expression:
# (global.get[0x23] 0x1 end[0x0b])
Extended: true
Body: 23010b
- Index: 1
Type: I64
Mutable: false
InitExpr:
# (global.get[0x23] 0x1 i32.const[0x41] 0x2 i32.add[0x6a] end[0x0b])
Extended: true
Body: 230141026a0b
...
# CHECK: --- !WASM
# CHECK: FileHeader:
# CHECK: Version: 0x1
# CHECK: Sections:
# CHECK: - Type: GLOBAL
# CHECK: Globals:
# CHECK: - Index: 0
# CHECK: Type: I32
# CHECK: Mutable: false
# CHECK: InitExpr:
# CHECK: Opcode: GLOBAL_GET
# CHECK: Index: 1
# CHECK: - Index: 1
# CHECK: Type: I64
# CHECK: Mutable: false
# CHECK: InitExpr:
# CHECK: Extended: true
# CHECK: Body: 230141026A0B
# CHECK: ...

View File

@ -179,13 +179,15 @@ void WasmDumper::printSectionHeaders() {
if (!Seg.Name.empty())
W.printString("Name", Seg.Name);
W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
W.printNumber("Offset", Seg.Offset.Value.Int32);
else if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST)
W.printNumber("Offset", Seg.Offset.Value.Int64);
else if (Seg.Offset.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
if (Seg.Offset.Extended)
llvm_unreachable("extended const exprs not supported");
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST)
W.printNumber("Offset", Seg.Offset.Inst.Value.Int32);
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST)
W.printNumber("Offset", Seg.Offset.Inst.Value.Int64);
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
ListScope Group(W, "Offset");
W.printNumber("Global", Seg.Offset.Value.Global);
W.printNumber("Global", Seg.Offset.Inst.Value.Global);
} else
llvm_unreachable("unknown init expr opcode");
}

View File

@ -298,7 +298,12 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
G.Index = Global.Index;
G.Type = Global.Type.Type;
G.Mutable = Global.Type.Mutable;
G.InitExpr = Global.InitExpr;
G.InitExpr.Extended = Global.InitExpr.Extended;
if (Global.InitExpr.Extended) {
G.InitExpr.Body = Global.InitExpr.Body;
} else {
G.InitExpr.Inst = Global.InitExpr.Inst;
}
GlobalSec->Globals.push_back(G);
}
S = std::move(GlobalSec);
@ -329,7 +334,12 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
Seg.Flags = Segment.Flags;
Seg.TableNumber = Segment.TableNumber;
Seg.ElemKind = Segment.ElemKind;
Seg.Offset = Segment.Offset;
Seg.Offset.Extended = Segment.Offset.Extended;
if (Seg.Offset.Extended) {
Seg.Offset.Body = yaml::BinaryRef(Segment.Offset.Body);
} else {
Seg.Offset.Inst = Segment.Offset.Inst;
}
append_range(Seg.Functions, Segment.Functions);
ElemSec->Segments.push_back(Seg);
}
@ -360,7 +370,12 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
Seg.SectionOffset = Segment.SectionOffset;
Seg.InitFlags = Segment.Data.InitFlags;
Seg.MemoryIndex = Segment.Data.MemoryIndex;
Seg.Offset = Segment.Data.Offset;
Seg.Offset.Extended = Segment.Data.Offset.Extended;
if (Seg.Offset.Extended) {
Seg.Offset.Body = yaml::BinaryRef(Segment.Data.Offset.Body);
} else {
Seg.Offset.Inst = Segment.Data.Offset.Inst;
}
Seg.Content = yaml::BinaryRef(Segment.Data.Content);
DataSec->Segments.push_back(Seg);
}