diff --git a/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/llvm/include/llvm/BinaryFormat/WasmRelocs.def --- a/llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ b/llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -22,3 +22,4 @@ WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB64, 17) WASM_RELOC(R_WASM_TABLE_INDEX_SLEB64, 18) WASM_RELOC(R_WASM_TABLE_INDEX_I64, 19) +WASM_RELOC(R_WASM_TABLE_NUMBER_LEB, 20) diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td --- a/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/llvm/include/llvm/CodeGen/ValueTypes.td @@ -194,6 +194,9 @@ def isVoid : ValueType<0 , 159>; // Produces no value def untyped: ValueType<8 , 160>; // Produces an untyped value def exnref : ValueType<0 , 161>; // WebAssembly's exnref type +def funcref : ValueType<0 , 162>; // WebAssembly's funcref type +def externref : ValueType<0 , 163>; // WebAssembly's externref type + def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -51,6 +51,8 @@ return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION; } + bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; } + bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; } bool isTypeGlobal() const { @@ -222,6 +224,7 @@ bool isValidEventIndex(uint32_t Index) const; bool isDefinedEventIndex(uint32_t Index) const; bool isValidFunctionSymbol(uint32_t Index) const; + bool isValidTableSymbol(uint32_t Index) const; bool isValidGlobalSymbol(uint32_t Index) const; bool isValidEventSymbol(uint32_t Index) const; bool isValidDataSymbol(uint32_t Index) const; diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h --- a/llvm/include/llvm/Support/MachineValueType.h +++ b/llvm/include/llvm/Support/MachineValueType.h @@ -245,9 +245,11 @@ // will be determined by the opcode. exnref = 161, // WebAssembly's exnref type + funcref = 162, // WebAssembly's funcref type + externref = 163, // WebAssembly's externref type FIRST_VALUETYPE = 1, // This is always the beginning of the list. - LAST_VALUETYPE = 162, // This always remains at the end of the list. + LAST_VALUETYPE = 164, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -943,7 +945,9 @@ case v1024f32: return TypeSize::Fixed(32768); case v2048i32: case v2048f32: return TypeSize::Fixed(65536); - case exnref: return TypeSize::Fixed(0); // opaque type + case exnref: + case funcref: + case externref: return TypeSize::Fixed(0); // opaque type } } diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -158,15 +158,17 @@ if (isFloatingPoint()) return "f" + utostr(getSizeInBits()); llvm_unreachable("Invalid EVT!"); - case MVT::bf16: return "bf16"; - case MVT::ppcf128: return "ppcf128"; - case MVT::isVoid: return "isVoid"; - case MVT::Other: return "ch"; - case MVT::Glue: return "glue"; - case MVT::x86mmx: return "x86mmx"; - case MVT::Metadata:return "Metadata"; - case MVT::Untyped: return "Untyped"; - case MVT::exnref : return "exnref"; + case MVT::bf16: return "bf16"; + case MVT::ppcf128: return "ppcf128"; + case MVT::isVoid: return "isVoid"; + case MVT::Other: return "ch"; + case MVT::Glue: return "glue"; + case MVT::x86mmx: return "x86mmx"; + case MVT::Metadata: return "Metadata"; + case MVT::Untyped: return "Untyped"; + case MVT::exnref: return "exnref"; + case MVT::funcref: return "funcref"; + case MVT::externref: return "externref"; } } diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -559,6 +559,7 @@ case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_TABLE_NUMBER_LEB: // Provisional value is function/global/event Wasm index assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space"); return WasmIndices[RelEntry.Symbol]; @@ -663,6 +664,7 @@ case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_MEMORY_ADDR_LEB: case wasm::R_WASM_EVENT_INDEX_LEB: + case wasm::R_WASM_TABLE_NUMBER_LEB: writePatchableLEB<5>(Stream, Value, Offset); break; case wasm::R_WASM_MEMORY_ADDR_LEB64: diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -552,6 +552,7 @@ case wasm::R_WASM_SECTION_OFFSET_I32: case wasm::R_WASM_EVENT_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: + case wasm::R_WASM_TABLE_NUMBER_LEB: return true; default: return false; @@ -585,6 +586,7 @@ case wasm::R_WASM_SECTION_OFFSET_I32: case wasm::R_WASM_EVENT_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: + case wasm::R_WASM_TABLE_NUMBER_LEB: // For wasm section, its offset at 0 -- ignoring Value return A; default: diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -822,6 +822,11 @@ return make_error("Bad relocation function index", object_error::parse_failed); break; + case wasm::R_WASM_TABLE_NUMBER_LEB: + if (!isValidTableSymbol(Reloc.Index)) + return make_error("Bad relocation table index", + object_error::parse_failed); + break; case wasm::R_WASM_TYPE_INDEX_LEB: if (Reloc.Index >= Signatures.size()) return make_error("Bad relocation type index", @@ -1181,6 +1186,10 @@ return Index < Symbols.size() && Symbols[Index].isTypeFunction(); } +bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeTable(); +} + bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); } diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -198,6 +198,7 @@ case WebAssembly::OPERAND_LOCAL: case WebAssembly::OPERAND_GLOBAL: case WebAssembly::OPERAND_FUNCTION32: + case WebAssembly::OPERAND_TABLE: case WebAssembly::OPERAND_OFFSET32: case WebAssembly::OPERAND_OFFSET64: case WebAssembly::OPERAND_P2ALIGN: diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -151,6 +151,7 @@ PaddedSize = 10; break; case WebAssembly::OPERAND_FUNCTION32: + case WebAssembly::OPERAND_TABLE: case WebAssembly::OPERAND_OFFSET32: case WebAssembly::OPERAND_SIGNATURE: case WebAssembly::OPERAND_TYPEINDEX: diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -76,6 +76,8 @@ OPERAND_EVENT, /// A list of branch targets for br_list. OPERAND_BRLIST, + /// 32-bit unsigned table number. + OPERAND_TABLE, }; } // end namespace WebAssembly diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -102,6 +102,8 @@ return wasm::R_WASM_FUNCTION_INDEX_LEB; if (SymA.isEvent()) return wasm::R_WASM_EVENT_INDEX_LEB; + if (SymA.isTable()) + return wasm::R_WASM_TABLE_NUMBER_LEB; return wasm::R_WASM_MEMORY_ADDR_LEB; case WebAssembly::fixup_uleb128_i64: assert(SymA.isData()); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -115,6 +115,10 @@ return WebAssembly::LOCAL_GET_V128; if (RC == &WebAssembly::EXNREFRegClass) return WebAssembly::LOCAL_GET_EXNREF; + if (RC == &WebAssembly::FUNCREFRegClass) + return WebAssembly::LOCAL_GET_FUNCREF; + if (RC == &WebAssembly::EXTERNREFRegClass) + return WebAssembly::LOCAL_GET_EXTERNREF; llvm_unreachable("Unexpected register class"); } @@ -132,6 +136,10 @@ return WebAssembly::LOCAL_SET_V128; if (RC == &WebAssembly::EXNREFRegClass) return WebAssembly::LOCAL_SET_EXNREF; + if (RC == &WebAssembly::FUNCREFRegClass) + return WebAssembly::LOCAL_SET_FUNCREF; + if (RC == &WebAssembly::EXTERNREFRegClass) + return WebAssembly::LOCAL_SET_EXTERNREF; llvm_unreachable("Unexpected register class"); } @@ -149,6 +157,10 @@ return WebAssembly::LOCAL_TEE_V128; if (RC == &WebAssembly::EXNREFRegClass) return WebAssembly::LOCAL_TEE_EXNREF; + if (RC == &WebAssembly::FUNCREFRegClass) + return WebAssembly::LOCAL_TEE_FUNCREF; + if (RC == &WebAssembly::EXTERNREFRegClass) + return WebAssembly::LOCAL_TEE_EXTERNREF; llvm_unreachable("Unexpected register class"); } @@ -166,6 +178,10 @@ return MVT::v16i8; if (RC == &WebAssembly::EXNREFRegClass) return MVT::exnref; + if (RC == &WebAssembly::FUNCREFRegClass) + return MVT::funcref; + if (RC == &WebAssembly::EXTERNREFRegClass) + return MVT::externref; llvm_unreachable("unrecognized register class"); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -129,6 +129,8 @@ case MVT::f32: case MVT::f64: case MVT::exnref: + case MVT::funcref: + case MVT::externref: return VT; case MVT::f16: return MVT::f32; @@ -809,6 +811,12 @@ case MVT::exnref: ResultReg = createResultReg(&WebAssembly::EXNREFRegClass); break; + case MVT::funcref: + ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass); + break; + case MVT::externref: + ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass); + break; default: return false; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -163,6 +163,9 @@ let OperandType = "OPERAND_FUNCTION32" in def function32_op : Operand; +let OperandType = "OPERAND_TABLE" in +def table32_op : Operand; + let OperandType = "OPERAND_OFFSET32" in def offset32_op : Operand; @@ -237,6 +240,8 @@ defm "": ARGUMENT; defm "": ARGUMENT; defm "": ARGUMENT; +defm "": ARGUMENT; +defm "": ARGUMENT; // local.get and local.set are not generated by instruction selection; they // are implied by virtual register uses and defs. @@ -307,6 +312,8 @@ defm "" : LOCAL; defm "" : LOCAL, Requires<[HasSIMD128]>; defm "" : LOCAL, Requires<[HasExceptionHandling]>; +defm "" : LOCAL, Requires<[HasReferenceTypes]>; +defm "" : LOCAL, Requires<[HasReferenceTypes]>; let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), @@ -365,3 +372,4 @@ include "WebAssemblyInstrSIMD.td" include "WebAssemblyInstrRef.td" include "WebAssemblyInstrBulkMemory.td" +include "WebAssemblyInstrTable.td" diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td @@ -0,0 +1,64 @@ +// WebAssemblyInstrTable.td - WebAssembly Table codegen support -*- tablegen -*- +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// WebAssembly Table operand code-gen constructs. +/// Instructions that handle tables +//===----------------------------------------------------------------------===// + + +multiclass TABLE { + defm TABLE_GET_#rt : I<(outs rt:$res), (ins table32_op:$table), + (outs), (ins table32_op:$table), + [], + "table.get\t$res, $table", + "table.get\t$table", + 0x25>; + + defm TABLE_SET_#rt : I<(outs), (ins table32_op:$table, rt:$val, I32:$i), + (outs), (ins table32_op:$table), + [], + "table.set\t$table, $val, $i", + "table.set\t$table", + 0x26>; + + defm TABLE_GROW_#rt : I<(outs I32:$sz), (ins table32_op:$table, I32:$n, rt:$val), + (outs), (ins table32_op:$table), + [], + "table.grow\t$sz, $table, $n, $val", + "table.grow\t$table", + 0xfc0f>; + + defm TABLE_FILL_#rt : I<(outs), (ins table32_op:$table, I32:$n, rt:$val, I32:$i), + (outs), (ins table32_op:$table), + [], + "table.fill\t$table, $n, $val, $i", + "table.fill\t$table", + 0xfc11>; + +} + +defm "" : TABLE, Requires<[HasReferenceTypes]>; +defm "" : TABLE, Requires<[HasReferenceTypes]>; + +defm TABLE_SIZE : I<(outs I32:$sz), (ins table32_op:$table), + (outs), (ins table32_op:$table), + [], + "table.size\t$sz, $table", + "table.size\t$table", + 0xfc10>, + Requires<[HasReferenceTypes]>; + + +defm TABLE_COPY : I<(outs), (ins table32_op:$table1, table32_op:$table2, I32:$n, I32:$s, I32:$d), + (outs), (ins table32_op:$table1, table32_op:$table2), + [], + "table.copy\t$table1, $table2, $n, $s, $d", + "table.copy\t$table1, $table2", + 0xfc0e>, + Requires<[HasReferenceTypes]>; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td @@ -44,6 +44,8 @@ def V128_0: WebAssemblyReg<"%v128">; def EXNREF_0 : WebAssemblyReg<"%exnref.0">; +def FUNCREF_0 : WebAssemblyReg<"%funcref.0">; +def EXTERNREF_0 : WebAssemblyReg<"%externref.0">; // The value stack "register". This is an opaque entity which serves to order // uses and defs that must remain in LIFO order. @@ -65,3 +67,5 @@ def V128 : WebAssemblyRegClass<[v4f32, v2f64, v2i64, v4i32, v16i8, v8i16], 128, (add V128_0)>; def EXNREF : WebAssemblyRegClass<[exnref], 0, (add EXNREF_0)>; +def FUNCREF : WebAssemblyRegClass<[funcref], 0, (add FUNCREF_0)>; +def EXTERNREF : WebAssemblyRegClass<[externref], 0, (add EXTERNREF_0)>; diff --git a/llvm/test/MC/WebAssembly/tables.s b/llvm/test/MC/WebAssembly/tables.s --- a/llvm/test/MC/WebAssembly/tables.s +++ b/llvm/test/MC/WebAssembly/tables.s @@ -1,19 +1,123 @@ -# RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s -# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck -check-prefix=BIN %s +# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s +# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck -check-prefix=ENC %s +# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+reference-types -filetype=obj < %s | obj2yaml | FileCheck -check-prefix=BIN %s -# Test creating several empty tables +# Creating several empty tables -.tabletype foo, externref +# CHECK: .tabletype foo, externref +# CHECK: foo: + .tabletype foo, externref foo: + +# CHECK: bar: +# CHECK-NEXT: .tabletype bar, funcref bar: -.tabletype bar, funcref + .tabletype bar, funcref -# CHECK: .tabletype foo, externref -# CHECK: foo: +table1: + .tabletype table1, funcref +table2: + .tabletype table2, funcref -# CHECK: bar: -# CHECK-NEXT: .tabletype bar, funcref +# Table instructions + +# CHECK: copy_tables: +# CHECK-NEXT: .functype copy_tables (i32, i32) -> () +# CHECK-NEXT: local.get 0 +# CHECK-NEXT: local.get 1 +# CHECK: table.size table1 +# CHECK: table.copy table1, table2 +# CHECK-NEXT: end_function +# CHECK-NEXT:.Ltmp0: +# CHECK-NEXT: .size copy_tables, .Ltmp0-copy_tables +copy_tables: + .functype copy_tables (i32, i32) -> () + local.get 0 + local.get 1 + + # ENC: table.size table1 # encoding: [0xfc,0x10,0x80'A',0x80'A',0x80'A',0x80'A',A] + table.size table1 + + # ENC: table.copy table1, table2 # encoding: [0xfc,0x0e,0x80'A',0x80'A',0x80'A',0x80'A',A,0x80'B',0x80'B',0x80'B',0x80'B',B] + table.copy table1, table2 + end_function + +# CHECK: table_get: +# CHECK-NEXT: .functype table_get (i32) -> (externref) +# CHECK-NEXT: local.get 0 +# CHECK: table.get foo +# CHECK-NEXT: end_function +# CHECK-NEXT: .Ltmp1: +# CHECK-NEXT: .size table_get, .Ltmp1-table_get +table_get: + .functype table_get (i32) -> (externref) + local.get 0 + + # ENC: table.get foo # encoding: [0x25,0x80'A',0x80'A',0x80'A',0x80'A',A] + table.get foo + end_function + +# CHECK: table_set: +# CHECK-NEXT: .functype table_set (i32, externref) -> () +# CHECK-NEXT: local.get 0 +# CHECK-NEXT: local.get 1 +# CHECK: table.set foo +# CHECK-NEXT: end_function +# CHECK-NEXT: .Ltmp2: +# CHECK-NEXT: .size table_set, .Ltmp2-table_set +table_set: + .functype table_set (i32, externref) -> () + local.get 0 + local.get 1 + + # ENC: table.set foo # encoding: [0x26,0x80'A',0x80'A',0x80'A',0x80'A',A] + table.set foo + end_function + +# CHECK: table_grow: +# CHECK-NEXT: .functype table_grow (i32) -> (i32) +# CHECK-NEXT: i32.const 0 +# CHECK-NEXT: table.get foo +# CHECK-NEXT: local.get 0 +# CHECK: table.grow foo +# CHECK-NEXT: local.get 0 +# CHECK-NEXT: i32.add +# CHECK-NEXT: end_function +# CHECK-NEXT: .Ltmp3: +# CHECK-NEXT: .size table_grow, .Ltmp3-table_grow +table_grow: + .functype table_grow (i32) -> (i32) + i32.const 0 + table.get foo + local.get 0 + + # ENC: table.grow foo # encoding: [0xfc,0x0f,0x80'A',0x80'A',0x80'A',0x80'A',A] + table.grow foo + local.get 0 + i32.add + end_function + +# CHECK: table_fill: +# CHECK-NEXT: .functype table_fill (i32, i32) -> () +# CHECK-NEXT: local.get 0 +# CHECK-NEXT: i32.const 0 +# CHECK-NEXT: table.get table1 +# CHECK-NEXT: local.get 1 +# CHECK: table.fill table1 +# CHECK-NEXT: end_function +# CHECK-NEXT: .Ltmp4: +# CHECK-NEXT: .size table_fill, .Ltmp4-table_fill +table_fill: + .functype table_fill (i32, i32) -> () + local.get 0 + i32.const 0 + table.get table1 + local.get 1 + + # ENC: table.fill table1 # encoding: [0xfc,0x11,0x80'A',0x80'A',0x80'A',0x80'A',A] + table.fill table1 + end_function # BIN: - Type: TABLE # BIN-NEXT: Tables: @@ -26,6 +130,52 @@ # BIN-NEXT: Limits: # BIN-NEXT: Initial: 0x00000000 +# BIN: - Type: CODE +# BIN-NEXT: Relocations: +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 2 +# BIN-NEXT: Offset: 0x00000009 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 2 +# BIN-NEXT: Offset: 0x00000010 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 3 +# BIN-NEXT: Offset: 0x00000015 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 0 +# BIN-NEXT: Offset: 0x00000020 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 0 +# BIN-NEXT: Offset: 0x0000002D +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 0 +# BIN-NEXT: Offset: 0x00000038 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 0 +# BIN-NEXT: Offset: 0x00000041 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 2 +# BIN-NEXT: Offset: 0x00000051 +# BIN-NEXT: - Type: R_WASM_TABLE_NUMBER_LEB +# BIN-NEXT: Index: 2 +# BIN-NEXT: Offset: 0x0000005A +# BIN-NEXT: Functions: +# BIN-NEXT: - Index: 0 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 20002001FC108380808000FC0E838080800084808080000B +# BIN-NEXT: - Index: 1 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 20002581808080000B +# BIN-NEXT: - Index: 2 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 200020012681808080000B +# BIN-NEXT: - Index: 3 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 41002581808080002000FC0F818080800020006A0B +# BIN-NEXT: - Index: 4 +# BIN-NEXT: Locals: [] +# BIN-NEXT: Body: 200041002583808080002001FC1183808080000B + # BIN: - Type: CUSTOM # BIN-NEXT: Name: linking # BIN-NEXT: Version: 2 diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -226,6 +226,10 @@ case MVT::iPTRAny: return "MVT::iPTRAny"; case MVT::Untyped: return "MVT::Untyped"; case MVT::exnref: return "MVT::exnref"; + case MVT::funcref: + return "MVT::funcref"; + case MVT::externref: + return "MVT::externref"; default: llvm_unreachable("ILLEGAL VALUE TYPE!"); } }