Skip to content

Commit 79aad89

Browse files
committed
[WebAssembly] Add support for externalref to MC and wasm-ld
This allows code for handling externref values to be processed by the assembler and linker. Differential Revision: https://reviews.llvm.org/D81977
1 parent a9c478a commit 79aad89

File tree

8 files changed

+112
-0
lines changed

8 files changed

+112
-0
lines changed

lld/test/wasm/externref.s

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o %s
2+
# RUN: wasm-ld %t.o -o %t.wasm
3+
# RUN: obj2yaml %t.wasm | FileCheck %s
4+
5+
# Tests use of externref type, including storing it in a global
6+
7+
.globaltype my_global, externref
8+
9+
.globl read_externref
10+
read_externref:
11+
.functype read_externref () -> (externref)
12+
global.get my_global
13+
end_function
14+
15+
.globl write_externref
16+
write_externref:
17+
.functype write_externref (externref) -> ()
18+
local.get 0
19+
global.set my_global
20+
end_function
21+
22+
my_global:
23+
24+
.globl _start
25+
_start:
26+
.functype _start () -> ()
27+
call read_externref
28+
call write_externref
29+
end_function
30+
31+
# CHECK: - Type: GLOBAL
32+
# CHECK-NEXT: Globals:
33+
# CHECK-NEXT: - Index: 0
34+
# CHECK-NEXT: Type: I32
35+
# CHECK-NEXT: Mutable: true
36+
# CHECK-NEXT: InitExpr:
37+
# CHECK-NEXT: Opcode: I32_CONST
38+
# CHECK-NEXT: Value: 66560
39+
# CHECK-NEXT: - Index: 1
40+
# CHECK-NEXT: Type: EXTERNREF
41+
# CHECK-NEXT: Mutable: true
42+
# CHECK-NEXT: InitExpr:
43+
# CHECK-NEXT: Opcode: REF_NULL
44+
# CHECK-NEXT: Type: EXTERNREF

lld/wasm/WriterUtils.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ std::string toString(ValType type) {
3232
return "v128";
3333
case ValType::EXNREF:
3434
return "exnref";
35+
case ValType::EXTERNREF:
36+
return "externref";
3537
}
3638
llvm_unreachable("Invalid wasm::ValType");
3739
}
@@ -155,6 +157,9 @@ void writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
155157
case WASM_OPCODE_GLOBAL_GET:
156158
writeUleb128(os, initExpr.Value.Global, "literal (global index)");
157159
break;
160+
case WASM_OPCODE_REF_NULL:
161+
writeValueType(os, ValType::EXTERNREF, "literal (externref type)");
162+
break;
158163
default:
159164
fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
160165
}

llvm/include/llvm/BinaryFormat/Wasm.h

+3
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ enum : unsigned {
232232
WASM_TYPE_V128 = 0x7B,
233233
WASM_TYPE_FUNCREF = 0x70,
234234
WASM_TYPE_EXNREF = 0x68,
235+
WASM_TYPE_EXTERNREF = 0x6F,
235236
WASM_TYPE_FUNC = 0x60,
236237
WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
237238
};
@@ -258,6 +259,7 @@ enum : unsigned {
258259
WASM_OPCODE_F32_CONST = 0x43,
259260
WASM_OPCODE_F64_CONST = 0x44,
260261
WASM_OPCODE_I32_ADD = 0x6a,
262+
WASM_OPCODE_REF_NULL = 0xd0,
261263
};
262264

263265
// Opcodes used in synthetic functions.
@@ -355,6 +357,7 @@ enum class ValType {
355357
F64 = WASM_TYPE_F64,
356358
V128 = WASM_TYPE_V128,
357359
EXNREF = WASM_TYPE_EXNREF,
360+
EXTERNREF = WASM_TYPE_EXTERNREF,
358361
};
359362

360363
struct WasmSignature {

llvm/lib/MC/WasmObjectWriter.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,9 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
833833
case wasm::WASM_TYPE_F64:
834834
writeI64(0);
835835
break;
836+
case wasm::WASM_TYPE_EXTERNREF:
837+
writeValueType(wasm::ValType::EXTERNREF);
838+
break;
836839
default:
837840
llvm_unreachable("unexpected type");
838841
}
@@ -1462,6 +1465,9 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
14621465
case wasm::WASM_TYPE_F64:
14631466
Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
14641467
break;
1468+
case wasm::WASM_TYPE_EXTERNREF:
1469+
Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
1470+
break;
14651471
default:
14661472
llvm_unreachable("unexpected type");
14671473
}

llvm/lib/Object/WasmObjectFile.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
184184
case wasm::WASM_OPCODE_GLOBAL_GET:
185185
Expr.Value.Global = readULEB128(Ctx);
186186
break;
187+
case wasm::WASM_OPCODE_REF_NULL: {
188+
wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
189+
if (Ty != wasm::ValType::EXTERNREF) {
190+
return make_error<GenericBinaryError>("Invalid type for ref.null",
191+
object_error::parse_failed);
192+
}
193+
break;
194+
}
187195
default:
188196
return make_error<GenericBinaryError>("Invalid opcode in init_expr",
189197
object_error::parse_failed);

llvm/lib/ObjectYAML/WasmYAML.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,11 @@ void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
433433
case wasm::WASM_OPCODE_GLOBAL_GET:
434434
IO.mapRequired("Index", Expr.Value.Global);
435435
break;
436+
case wasm::WASM_OPCODE_REF_NULL: {
437+
WasmYAML::ValueType Ty = wasm::WASM_TYPE_EXTERNREF;
438+
IO.mapRequired("Type", Ty);
439+
break;
440+
}
436441
}
437442
}
438443

@@ -559,6 +564,8 @@ void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
559564
ECase(F64);
560565
ECase(V128);
561566
ECase(FUNCREF);
567+
ECase(EXNREF);
568+
ECase(EXTERNREF);
562569
ECase(FUNC);
563570
#undef ECase
564571
}
@@ -583,6 +590,7 @@ void ScalarEnumerationTraits<WasmYAML::Opcode>::enumeration(
583590
ECase(F64_CONST);
584591
ECase(F32_CONST);
585592
ECase(GLOBAL_GET);
593+
ECase(REF_NULL);
586594
#undef ECase
587595
}
588596

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
322322
return wasm::ValType::V128;
323323
if (Type == "exnref")
324324
return wasm::ValType::EXNREF;
325+
if (Type == "externref")
326+
return wasm::ValType::EXTERNREF;
325327
return Optional<wasm::ValType>();
326328
}
327329

llvm/test/MC/WebAssembly/externref.s

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s
2+
3+
# Tests use of externref type, including storing it in a global
4+
5+
.globaltype my_global, externref
6+
7+
.globl read_externref
8+
read_externref:
9+
.functype read_externref () -> (externref)
10+
global.get my_global
11+
end_function
12+
13+
.globl write_externref
14+
write_externref:
15+
.functype write_externref (externref) -> ()
16+
local.get 0
17+
global.set my_global
18+
end_function
19+
20+
.globl call_with_ref
21+
call_with_ref:
22+
.functype call_with_ref () -> ()
23+
call read_externref
24+
call write_externref
25+
end_function
26+
27+
my_global:
28+
29+
# CHECK: - Type: GLOBAL
30+
# CHECK-NEXT: Globals:
31+
# CHECK-NEXT: - Index: 0
32+
# CHECK-NEXT: Type: EXTERNREF
33+
# CHECK-NEXT: Mutable: true
34+
# CHECK-NEXT: InitExpr:
35+
# CHECK-NEXT: Opcode: REF_NULL
36+
# CHECK-NEXT: Type: EXTERNREF

0 commit comments

Comments
 (0)