[lld] 9504ab3 - [WebAssembly] Second phase of implemented extended const proposal

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 14 08:55:57 PDT 2022


Author: Sam Clegg
Date: 2022-03-14T08:55:47-07:00
New Revision: 9504ab32b76646116585cae4298f700cf46721ab

URL: https://github.com/llvm/llvm-project/commit/9504ab32b76646116585cae4298f700cf46721ab
DIFF: https://github.com/llvm/llvm-project/commit/9504ab32b76646116585cae4298f700cf46721ab.diff

LOG: [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

Added: 
    llvm/test/ObjectYAML/wasm/extended_const_expressions.yaml

Modified: 
    lld/wasm/InputElement.h
    lld/wasm/InputFiles.cpp
    lld/wasm/OutputSections.cpp
    lld/wasm/SyntheticSections.cpp
    lld/wasm/WriterUtils.cpp
    lld/wasm/WriterUtils.h
    llvm/include/llvm/BinaryFormat/Wasm.h
    llvm/include/llvm/ObjectYAML/WasmYAML.h
    llvm/lib/MC/WasmObjectWriter.cpp
    llvm/lib/Object/WasmObjectFile.cpp
    llvm/lib/ObjectYAML/WasmEmitter.cpp
    llvm/lib/ObjectYAML/WasmYAML.cpp
    llvm/tools/llvm-readobj/WasmDumper.cpp
    llvm/tools/obj2yaml/wasm2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/lld/wasm/InputElement.h b/lld/wasm/InputElement.h
index d1262de68666c..6c8f41db0290a 100644
--- a/lld/wasm/InputElement.h
+++ b/lld/wasm/InputElement.h
@@ -44,12 +44,13 @@ class InputElement {
 
 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;
 }

diff  --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index ebff723520291..f887b6158cb10 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -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++) {

diff  --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 379648a6b708a..a9c2db255b677 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -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));
       }

diff  --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 2142b0261ae40..a0a8d597118d3 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -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);
 

diff  --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp
index c0e908f9a9eee..03c66e82fcd31 100644
--- a/lld/wasm/WriterUtils.cpp
+++ b/lld/wasm/WriterUtils.cpp
@@ -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:

diff  --git a/lld/wasm/WriterUtils.h b/lld/wasm/WriterUtils.h
index 4cbd9a4135e17..2be79d1d86e97 100644
--- a/lld/wasm/WriterUtils.h
+++ b/lld/wasm/WriterUtils.h
@@ -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);

diff  --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 0bc8c4e167d85..23773b1af9d70 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -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,
 };
 

diff  --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index e3a1ba0d58a68..76da5582e4cfa 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -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> {

diff  --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 27023f103d993..f891f948891b7 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -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");

diff  --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 1122f42dfb67a..8e317b06e9b6b 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -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");
     }

diff  --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp
index 401bc92207f9c..0787f099a4d10 100644
--- a/llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -33,7 +33,7 @@ class WasmWriter {
   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,

diff  --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index 3f0172ebf361d..08deaa4eba183 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -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);
 }

diff  --git a/llvm/test/ObjectYAML/wasm/extended_const_expressions.yaml b/llvm/test/ObjectYAML/wasm/extended_const_expressions.yaml
new file mode 100644
index 0000000000000..60db925c1710b
--- /dev/null
+++ b/llvm/test/ObjectYAML/wasm/extended_const_expressions.yaml
@@ -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: ...

diff  --git a/llvm/tools/llvm-readobj/WasmDumper.cpp b/llvm/tools/llvm-readobj/WasmDumper.cpp
index b4d726016437e..cf80a2d13d2db 100644
--- a/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -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");
       }

diff  --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index e4a56524e36bc..3a34c7ef45288 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -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);
       }


        


More information about the llvm-commits mailing list