]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Import the linear memory and function table.
authorDan Gohman <dan433584@gmail.com>
Wed, 6 Dec 2017 23:57:11 +0000 (23:57 +0000)
committerDan Gohman <dan433584@gmail.com>
Wed, 6 Dec 2017 23:57:11 +0000 (23:57 +0000)
Instead of having .o files contain linear-memory and function table
definitions, use imports. This is more consistent with the stack pointer
being imported, and it's consistent with the linker being the one to
decide whether linear memory and function table are imported or defined
in the linked output. This implements tool-conventions #23.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319989 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/WasmObjectWriter.cpp
test/MC/WebAssembly/external-func-address.ll
test/MC/WebAssembly/func-address.ll
test/MC/WebAssembly/init-fini-array.ll
test/MC/WebAssembly/reloc-code.ll
test/MC/WebAssembly/reloc-data.ll
test/MC/WebAssembly/sections.ll
test/MC/WebAssembly/weak-alias.ll
test/MC/WebAssembly/weak.ll

index 351927d628a28bf412556bfa0241ce95d5fda685..7c50f437cfa9d7bc92346584d47bb8f3fb9f6cca 100644 (file)
@@ -270,10 +270,9 @@ private:
   }
 
   void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
-  void writeImportSection(ArrayRef<WasmImport> Imports);
+  void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
+                          uint32_t NumElements);
   void writeFunctionSection(ArrayRef<WasmFunction> Functions);
-  void writeTableSection(uint32_t NumElements);
-  void writeMemorySection(uint32_t DataSize);
   void writeGlobalSection();
   void writeExportSection(ArrayRef<WasmExport> Exports);
   void writeElemSection(ArrayRef<uint32_t> TableElems);
@@ -661,10 +660,14 @@ void WasmObjectWriter::writeTypeSection(
   endSection(Section);
 }
 
-void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports) {
+void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
+                                          uint32_t DataSize,
+                                          uint32_t NumElements) {
   if (Imports.empty())
     return;
 
+  uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
+
   SectionBookkeeping Section;
   startSection(Section, wasm::WASM_SEC_IMPORT);
 
@@ -683,6 +686,15 @@ void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports) {
       encodeSLEB128(int32_t(Import.Type), getStream());
       encodeULEB128(int32_t(Import.IsMutable), getStream());
       break;
+    case wasm::WASM_EXTERNAL_MEMORY:
+      encodeULEB128(0, getStream()); // flags
+      encodeULEB128(NumPages, getStream()); // initial
+      break;
+    case wasm::WASM_EXTERNAL_TABLE:
+      encodeSLEB128(int32_t(Import.Type), getStream());
+      encodeULEB128(0, getStream()); // flags
+      encodeULEB128(NumElements, getStream()); // initial
+      break;
     default:
       llvm_unreachable("unsupported import kind");
     }
@@ -705,39 +717,6 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
   endSection(Section);
 }
 
-void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
-  // For now, always emit the table section, since indirect calls are not
-  // valid without it. In the future, we could perhaps be more clever and omit
-  // it if there are no indirect calls.
-
-  SectionBookkeeping Section;
-  startSection(Section, wasm::WASM_SEC_TABLE);
-
-  encodeULEB128(1, getStream());                       // The number of tables.
-                                                       // Fixed to 1 for now.
-  encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
-  encodeULEB128(0, getStream());                       // flags
-  encodeULEB128(NumElements, getStream());             // initial
-
-  endSection(Section);
-}
-
-void WasmObjectWriter::writeMemorySection(uint32_t DataSize) {
-  // For now, always emit the memory section, since loads and stores are not
-  // valid without it. In the future, we could perhaps be more clever and omit
-  // it if there are no loads or stores.
-  SectionBookkeeping Section;
-  uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
-
-  startSection(Section, wasm::WASM_SEC_MEMORY);
-  encodeULEB128(1, getStream()); // number of memory spaces
-
-  encodeULEB128(0, getStream()); // flags
-  encodeULEB128(NumPages, getStream()); // initial
-
-  endSection(Section);
-}
-
 void WasmObjectWriter::writeGlobalSection() {
   if (Globals.empty())
     return;
@@ -1085,6 +1064,29 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     }
   }
 
+  // For now, always emit the memory import, since loads and stores are not
+  // valid without it. In the future, we could perhaps be more clever and omit
+  // it if there are no loads or stores.
+  MCSymbolWasm *MemorySym =
+      cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
+  WasmImport MemImport;
+  MemImport.ModuleName = MemorySym->getModuleName();
+  MemImport.FieldName = MemorySym->getName();
+  MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
+  Imports.push_back(MemImport);
+
+  // For now, always emit the table section, since indirect calls are not
+  // valid without it. In the future, we could perhaps be more clever and omit
+  // it if there are no indirect calls.
+  MCSymbolWasm *TableSym =
+      cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
+  WasmImport TableImport;
+  TableImport.ModuleName = TableSym->getModuleName();
+  TableImport.FieldName = TableSym->getName();
+  TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
+  TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
+  Imports.push_back(TableImport);
+
   // Populate FunctionTypeIndices and Imports.
   for (const MCSymbol &S : Asm.symbols()) {
     const auto &WS = static_cast<const MCSymbolWasm &>(S);
@@ -1295,10 +1297,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   writeHeader(Asm);
 
   writeTypeSection(FunctionTypes);
-  writeImportSection(Imports);
+  writeImportSection(Imports, DataSize, TableElems.size());
   writeFunctionSection(Functions);
-  writeTableSection(TableElems.size());
-  writeMemorySection(DataSize);
+  // Skip the "table" section; we import the table instead.
+  // Skip the "memory" section; we import the memory instead.
   writeGlobalSection();
   writeExportSection(Exports);
   // TODO: Start Section
index 53da9805f9871eed175acd1a9d330d0ed12eb760..9386d945ccd55b89dcf81b7ea1f1b0bd00030dd8 100644 (file)
@@ -17,7 +17,11 @@ declare void @f1(i32) #1
 ; CHECK-NEXT:           - I32
 ; CHECK:        - Type:            IMPORT
 ; CHECK-NEXT:     Imports:
-; CHECK-NEXT:       - Module:          env
+; CHECK:            - Module:          env
+; CHECK-NEXT:         Field:           __linear_memory
+; CHECK:            - Module:          env
+; CHECK-NEXT:         Field:           __indirect_function_table
+; CHECK:            - Module:          env
 ; CHECK-NEXT:         Field:           f1
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         SigIndex:        0
index 15c09e0ebd80444b15bb83cbf045d353bdb25a8a..16d38e1ebf24f1750e66b6f00063c7f896fdd4b3 100644 (file)
@@ -28,7 +28,7 @@ entry:
 ; CHECK:   }
 
 ; CHECK: Relocations [
-; CHECK:   Section (8) CODE {
+; CHECK:   Section (6) CODE {
 ; CHECK:     Relocation {
 ; CHECK:       Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0)
 ; CHECK:       Offset: 0x4
index 5cd32ff9bf52363b2dd2a6b4363f0c66242f87b4..b7a1826bdc474ca31cae12e30d98f0324316c6b2 100644 (file)
@@ -14,6 +14,18 @@ declare void @func2()
 ; CHECK:        - Type:            IMPORT
 ; CHECK-NEXT:     Imports:         
 ; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           __linear_memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Memory:
+; CHECK-NEXT:           Initial:         0x00000001
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           __indirect_function_table
+; CHECK-NEXT:         Kind:            TABLE
+; CHECK-NEXT:         Table:
+; CHECK-NEXT:           ElemType:        ANYFUNC
+; CHECK-NEXT:           Limits:
+; CHECK-NEXT:             Initial:         0x00000002
+; CHECK-NEXT:       - Module:          env
 ; CHECK-NEXT:         Field:           func1
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         SigIndex:        0
@@ -21,14 +33,6 @@ declare void @func2()
 ; CHECK-NEXT:         Field:           func2
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         SigIndex:        0
-; CHECK-NEXT:   - Type:            TABLE
-; CHECK-NEXT:     Tables:          
-; CHECK-NEXT:       - ElemType:        ANYFUNC
-; CHECK-NEXT:         Limits:          
-; CHECK-NEXT:           Initial:         0x00000002
-; CHECK-NEXT:   - Type:            MEMORY
-; CHECK-NEXT:     Memories:        
-; CHECK-NEXT:       - Initial:         0x00000001
 ; CHECK-NEXT:   - Type:            GLOBAL
 ; CHECK-NEXT:     Globals:         
 ; CHECK-NEXT:       - Type:            I32
index f007b63ca83e5d988d4623fba3e6317993693aad..e9aff890cff8388861d102de1a01e15d7c2dc9ba 100644 (file)
@@ -22,7 +22,7 @@ entry:
 
 ; CHECK: Format: WASM
 ; CHECK: Relocations [
-; CHECK-NEXT:   Section (8) CODE {
+; CHECK-NEXT:   Section (6) CODE {
 ; CHECK-NEXT:     Relocation {
 ; CHECK-NEXT:       Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB (3)
 ; CHECK-NEXT:       Offset: 0x9
index 519df036751297db47593753ba3b12fa6e866b62..ca78d8b158f76258af70d3abba586e0f1d4d2f30 100644 (file)
@@ -10,7 +10,7 @@
 
 ; CHECK:      Format: WASM
 ; CHECK:      Relocations [
-; CHECK-NEXT:   Section (6) DATA {
+; CHECK-NEXT:   Section (4) DATA {
 ; CHECK-NEXT:     Relocation {
 ; CHECK-NEXT:       Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5)
 ; CHECK-NEXT:       Offset: 0x13
index 85bf081850905d1a6bb0d65106527d035f2cd89c..14c9cc6ab07f343e8db2bd999cccd3b3658fafa2 100644 (file)
@@ -28,17 +28,6 @@ entry:
 ; CHECK:    Type: FUNCTION (0x3)
 ; CHECK:  }
 ; CHECK:  Section {
-; CHECK:    Type: TABLE (0x4)
-; CHECK:  }
-; CHECK:  Section {
-; CHECK:    Type: MEMORY (0x5)
-; CHECK:    Memories [
-; CHECK:      Memory {
-; CHECK:        InitialPages: 1
-; CHECK:      }
-; CHECK:    ]
-; CHECK:  }
-; CHECK:  Section {
 ; CHECK:    Type: GLOBAL (0x6)
 ; CHECK:  }
 ; CHECK:  Section {
index 4129870ce2321674835434e105b1cdbae78e97c6..5c85fc09b03fb1bdf146378c6051c89f7bc6a86b 100644 (file)
@@ -29,16 +29,22 @@ entry:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         ReturnType:      I32
 ; CHECK-NEXT:         ParamTypes:      
+; CHECK-NEXT:   - Type:            IMPORT
+; CHECK-NEXT:     Imports:
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           __linear_memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Memory:
+; CHECK-NEXT:           Initial:         0x00000001
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           __indirect_function_table
+; CHECK-NEXT:         Kind:            TABLE
+; CHECK-NEXT:         Table:
+; CHECK-NEXT:           ElemType:        ANYFUNC
+; CHECK-NEXT:           Limits:
+; CHECK-NEXT:             Initial:         0x00000000
 ; CHECK-NEXT:   - Type:            FUNCTION
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
-; CHECK-NEXT:   - Type:            TABLE
-; CHECK-NEXT:     Tables:          
-; CHECK-NEXT:       - ElemType:        ANYFUNC
-; CHECK-NEXT:         Limits:          
-; CHECK-NEXT:           Initial:         0x00000000
-; CHECK-NEXT:   - Type:            MEMORY
-; CHECK-NEXT:     Memories:        
-; CHECK-NEXT:       - Initial:         0x00000001
 ; CHECK-NEXT:   - Type:            GLOBAL
 ; CHECK-NEXT:     Globals:         
 ; CHECK-NEXT:       - Type:            I32
index f735356902415da1c4e7b9feef84347447a1ce39..af177b53595deb5daf29e8e4be719405251d22ae 100644 (file)
@@ -12,7 +12,11 @@ entry:
 
 ; CHECK:        - Type:            IMPORT
 ; CHECK-NEXT:     Imports:         
-; CHECK-NEXT:       - Module:          env
+; CHECK:            - Module:          env
+; CHECK-NEXT:         Field:           __linear_memory
+; CHECK:            - Module:          env
+; CHECK-NEXT:         Field:           __indirect_function_table
+; CHECK:            - Module:          env
 ; CHECK-NEXT:         Field:           weak_external_data
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         GlobalType:      I32