Skip to content

Commit a96d828

Browse files
committed
[WebAssembly] Implementation of intrinsic for ref.null and HeapType removal
This patch implements the intrinsic for ref.null. In the process of implementing int_wasm_ref_null_func() and int_wasm_ref_null_extern() intrinsics, it removes the redundant HeapType. This also causes the textual assembler syntax for ref.null to change. Instead of receiving an argument: `func` or `extern`, the instruction mnemonic is either ref.null_func or ref.null_extern, without the need for a further operand. Reviewed By: tlively Differential Revision: https://reviews.llvm.org/D114979
1 parent 3ec6b1b commit a96d828

20 files changed

+74
-112
lines changed

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ def llvm_v16f64_ty : LLVMType<v16f64>; // 16 x double
332332

333333
def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here
334334

335+
def llvm_externref_ty : LLVMType<externref>;
336+
def llvm_funcref_ty : LLVMType<funcref>;
337+
335338
//===----------------------------------------------------------------------===//
336339
// Intrinsic Definitions.
337340
//===----------------------------------------------------------------------===//

llvm/include/llvm/IR/IntrinsicsWebAssembly.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
2323
[llvm_i32_ty, LLVMMatchType<0>],
2424
[]>;
2525

26+
//===----------------------------------------------------------------------===//
27+
// ref.null intrinsics
28+
//===----------------------------------------------------------------------===//
29+
def int_wasm_ref_null_extern : Intrinsic<[llvm_externref_ty], [], [IntrNoMem]>;
30+
def int_wasm_ref_null_func : Intrinsic<[llvm_funcref_ty], [], [IntrNoMem]>;
31+
2632
//===----------------------------------------------------------------------===//
2733
// Trapping float-to-int conversions
2834
//===----------------------------------------------------------------------===//

llvm/lib/IR/Function.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,8 @@ enum IIT_Info {
982982
IIT_AMX = 51,
983983
IIT_PPCF128 = 52,
984984
IIT_V3 = 53,
985+
IIT_EXTERNREF = 54,
986+
IIT_FUNCREF = 55
985987
};
986988

987989
static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
@@ -1097,6 +1099,14 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
10971099
OutputTable.push_back(IITDescriptor::getVector(1024, IsScalableVector));
10981100
DecodeIITType(NextElt, Infos, Info, OutputTable);
10991101
return;
1102+
case IIT_EXTERNREF:
1103+
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 10));
1104+
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0));
1105+
return;
1106+
case IIT_FUNCREF:
1107+
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 20));
1108+
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8));
1109+
return;
11001110
case IIT_PTR:
11011111
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0));
11021112
DecodeIITType(NextElt, Infos, Info, OutputTable);

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
571571
// proper nesting.
572572
bool ExpectBlockType = false;
573573
bool ExpectFuncType = false;
574-
bool ExpectHeapType = false;
575574
std::unique_ptr<WebAssemblyOperand> FunctionTable;
576575
if (Name == "block") {
577576
push(Block);
@@ -624,8 +623,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
624623
if (parseFunctionTableOperand(&FunctionTable))
625624
return true;
626625
ExpectFuncType = true;
627-
} else if (Name == "ref.null") {
628-
ExpectHeapType = true;
629626
}
630627

631628
if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
@@ -670,15 +667,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
670667
return error("Unknown block type: ", Id);
671668
addBlockTypeOperand(Operands, NameLoc, BT);
672669
Parser.Lex();
673-
} else if (ExpectHeapType) {
674-
auto HeapType = WebAssembly::parseHeapType(Id.getString());
675-
if (HeapType == WebAssembly::HeapType::Invalid) {
676-
return error("Expected a heap type: ", Id);
677-
}
678-
Operands.push_back(std::make_unique<WebAssemblyOperand>(
679-
WebAssemblyOperand::Integer, Id.getLoc(), Id.getEndLoc(),
680-
WebAssemblyOperand::IntOp{static_cast<int64_t>(HeapType)}));
681-
Parser.Lex();
682670
} else {
683671
// Assume this identifier is a label.
684672
const MCExpr *Val;

llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -241,28 +241,6 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
241241
}
242242
break;
243243
}
244-
// heap_type operands, for e.g. ref.null:
245-
case WebAssembly::OPERAND_HEAPTYPE: {
246-
int64_t Val;
247-
uint64_t PrevSize = Size;
248-
if (!nextLEB(Val, Bytes, Size, true))
249-
return MCDisassembler::Fail;
250-
if (Val < 0 && Size == PrevSize + 1) {
251-
// The HeapType encoding is like BlockType, in that encodings that
252-
// decode as negative values indicate ValTypes. In practice we expect
253-
// either wasm::ValType::EXTERNREF or wasm::ValType::FUNCREF here.
254-
//
255-
// The positive SLEB values are reserved for future expansion and are
256-
// expected to be type indices in the typed function references
257-
// proposal, and should disassemble as MCSymbolRefExpr as in BlockType
258-
// above.
259-
MI.addOperand(MCOperand::createImm(Val & 0x7f));
260-
} else {
261-
MI.addOperand(
262-
MCOperand::createImm(int64_t(WebAssembly::HeapType::Invalid)));
263-
}
264-
break;
265-
}
266244
// FP operands.
267245
case WebAssembly::OPERAND_F32IMM: {
268246
if (!parseImmediate<float>(MI, Size, Bytes))

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -366,26 +366,3 @@ void WebAssemblyInstPrinter::printWebAssemblySignatureOperand(const MCInst *MI,
366366
}
367367
}
368368
}
369-
370-
void WebAssemblyInstPrinter::printWebAssemblyHeapTypeOperand(const MCInst *MI,
371-
unsigned OpNo,
372-
raw_ostream &O) {
373-
const MCOperand &Op = MI->getOperand(OpNo);
374-
if (Op.isImm()) {
375-
switch (Op.getImm()) {
376-
case long(wasm::ValType::EXTERNREF):
377-
O << "extern";
378-
break;
379-
case long(wasm::ValType::FUNCREF):
380-
O << "func";
381-
break;
382-
default:
383-
O << "unsupported_heap_type_value";
384-
break;
385-
}
386-
} else {
387-
// Typed function references and other subtypes of funcref and externref
388-
// currently unimplemented.
389-
O << "unsupported_heap_type_operand";
390-
}
391-
}

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ class WebAssemblyInstPrinter final : public MCInstPrinter {
4747
raw_ostream &O);
4848
void printWebAssemblySignatureOperand(const MCInst *MI, unsigned OpNo,
4949
raw_ostream &O);
50-
void printWebAssemblyHeapTypeOperand(const MCInst *MI, unsigned OpNo,
51-
raw_ostream &O);
5250

5351
// Autogenerated by tblgen.
5452
std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,6 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
106106
encodeSLEB128(int64_t(MO.getImm()), OS);
107107
break;
108108
case WebAssembly::OPERAND_SIGNATURE:
109-
case WebAssembly::OPERAND_HEAPTYPE:
110-
OS << uint8_t(MO.getImm());
111-
break;
112109
case WebAssembly::OPERAND_VEC_I8IMM:
113110
support::endian::write<uint8_t>(OS, MO.getImm(), support::little);
114111
break;

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ enum OperandType {
7878
OPERAND_BRLIST,
7979
/// 32-bit unsigned table number.
8080
OPERAND_TABLE,
81-
/// heap type immediate for ref.null.
82-
OPERAND_HEAPTYPE,
8381
};
8482
} // end namespace WebAssembly
8583

llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,6 @@ Optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
4141
return Optional<wasm::ValType>();
4242
}
4343

44-
WebAssembly::HeapType WebAssembly::parseHeapType(StringRef Type) {
45-
return StringSwitch<WebAssembly::HeapType>(Type)
46-
.Case("extern", WebAssembly::HeapType::Externref)
47-
.Case("func", WebAssembly::HeapType::Funcref)
48-
.Default(WebAssembly::HeapType::Invalid);
49-
}
50-
5144
WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) {
5245
// Multivalue block types are handled separately in parseSignature
5346
return StringSwitch<WebAssembly::BlockType>(Type)

llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,9 @@ enum class BlockType : unsigned {
4141
Multivalue = 0xffff,
4242
};
4343

44-
/// Used as immediate MachineOperands for heap types, e.g. for ref.null.
45-
enum class HeapType : unsigned {
46-
Invalid = 0x00,
47-
Externref = unsigned(wasm::ValType::EXTERNREF),
48-
Funcref = unsigned(wasm::ValType::FUNCREF),
49-
};
50-
5144
// Convert StringRef to ValType / HealType / BlockType
5245

5346
Optional<wasm::ValType> parseType(StringRef Type);
54-
HeapType parseHeapType(StringRef Type);
5547
BlockType parseBlockType(StringRef Type);
5648
MVT parseMVT(StringRef Type);
5749

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,7 @@ LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB,
644644
Register RegFuncref =
645645
MF.getRegInfo().createVirtualRegister(&WebAssembly::FUNCREFRegClass);
646646
MachineInstr *RefNull =
647-
BuildMI(MF, DL, TII.get(WebAssembly::REF_NULL_FUNCREF), RegFuncref)
648-
.addImm(static_cast<int32_t>(WebAssembly::HeapType::Funcref));
647+
BuildMI(MF, DL, TII.get(WebAssembly::REF_NULL_FUNCREF), RegFuncref);
649648
BB->insertAfter(Const0->getIterator(), RefNull);
650649

651650
MachineInstr *TableSet =

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,6 @@ def Signature : Operand<i32> {
202202
let PrintMethod = "printWebAssemblySignatureOperand";
203203
}
204204

205-
let OperandType = "OPERAND_HEAPTYPE" in
206-
def HeapType : Operand<i32> {
207-
let PrintMethod = "printWebAssemblyHeapTypeOperand";
208-
}
209-
210205
let OperandType = "OPERAND_TYPEINDEX" in
211206
def TypeIndex : Operand<i32>;
212207

llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
///
1212
//===----------------------------------------------------------------------===//
1313

14-
multiclass REF_I<WebAssemblyRegClass rc, ValueType vt> {
15-
defm REF_NULL_#rc : I<(outs rc:$res), (ins HeapType:$heaptype),
16-
(outs), (ins HeapType:$heaptype),
17-
[],
18-
"ref.null\t$res, $heaptype",
19-
"ref.null\t$heaptype",
20-
0xd0>,
14+
multiclass REF_I<WebAssemblyRegClass rc, ValueType vt, string ht> {
15+
defm REF_NULL_#rc : I<(outs rc:$dst), (ins),
16+
(outs), (ins),
17+
[(set rc:$dst, (!cast<Intrinsic>("int_wasm_ref_null_" # ht)))],
18+
"ref.null_" # ht # "$dst",
19+
"ref.null_" # ht,
20+
!cond(!eq(ht, "func") : 0xd070,
21+
!eq(ht, "extern") : 0xd06f)>,
2122
Requires<[HasReferenceTypes]>;
2223
defm SELECT_#rc: I<(outs rc:$dst), (ins rc:$lhs, rc:$rhs, I32:$cond),
2324
(outs), (ins),
@@ -28,8 +29,8 @@ multiclass REF_I<WebAssemblyRegClass rc, ValueType vt> {
2829
Requires<[HasReferenceTypes]>;
2930
}
3031

31-
defm "" : REF_I<FUNCREF, funcref>;
32-
defm "" : REF_I<EXTERNREF, externref>;
32+
defm "" : REF_I<FUNCREF, funcref, "func">;
33+
defm "" : REF_I<EXTERNREF, externref, "extern">;
3334

3435
foreach rc = [FUNCREF, EXTERNREF] in {
3536
def : Pat<(select (i32 (setne I32:$cond, 0)), rc:$lhs, rc:$rhs),

llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,6 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI,
275275
SmallVector<wasm::ValType, 4>());
276276
break;
277277
}
278-
} else if (Info.OperandType == WebAssembly::OPERAND_HEAPTYPE) {
279-
assert(static_cast<WebAssembly::HeapType>(MO.getImm()) !=
280-
WebAssembly::HeapType::Invalid);
281-
// With typed function references, this will need a case for type
282-
// index operands. Otherwise, fall through.
283278
}
284279
}
285280
MCOp = MCOperand::createImm(MO.getImm());

llvm/test/CodeGen/WebAssembly/funcref-call.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ define void @call_funcref(%funcref %ref) {
1818
; CHECK-NEXT: i32.const 0
1919
; CHECK-NEXT: call_indirect __funcref_call_table, () -> ()
2020
; CHECK-NEXT: i32.const 0
21-
; CHECK-NEXT: ref.null func
21+
; CHECK-NEXT: ref.null_func
2222
; CHECK-NEXT: table.set __funcref_call_table
2323
; CHECK-NEXT: end_function
2424

llvm/test/CodeGen/WebAssembly/funcref-table_call.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ define void @call_funcref_from_table(i32 %i) {
2323
; CHECK-NEXT: i32.const 0
2424
; CHECK-NEXT: call_indirect __funcref_call_table, () -> ()
2525
; CHECK-NEXT: i32.const 0
26-
; CHECK-NEXT: ref.null func
26+
; CHECK-NEXT: ref.null_func
2727
; CHECK-NEXT: table.set __funcref_call_table
2828
; CHECK-NEXT: end_function
2929

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s
2+
3+
%extern = type opaque
4+
%externref = type %extern addrspace(10)* ;; addrspace 10 is nonintegral
5+
%funcref = type i8 addrspace(20)* ;; addrspace 20 is nonintegral
6+
7+
declare %externref @llvm.wasm.ref.null.extern() nounwind
8+
declare %funcref @llvm.wasm.ref.null.func() nounwind
9+
10+
define %externref @get_null_extern() {
11+
; CHECK-LABEL: get_null_extern:
12+
; CHECK-NEXT: .functype get_null_extern () -> (externref)
13+
; CHECK-NEXT: ref.null_extern
14+
; CHECK-NEXT: end_function
15+
%null = call %externref @llvm.wasm.ref.null.extern()
16+
ret %externref %null
17+
}
18+
19+
define %funcref @get_null_func() {
20+
; CHECK-LABEL: get_null_func:
21+
; CHECK-NEXT: .functype get_null_func () -> (funcref)
22+
; CHECK-NEXT: ref.null_func
23+
; CHECK-NEXT: end_function
24+
%null = call %funcref @llvm.wasm.ref.null.func()
25+
ret %funcref %null
26+
}

llvm/test/MC/WebAssembly/reference-types.s

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
# RUN: llvm-mc -show-encoding -triple=wasm64-unknown-unknown -mattr=+reference-types < %s | FileCheck %s
33

44
# CHECK-LABEL: ref_null_test:
5-
# CHECK: ref.null func # encoding: [0xd0,0x70]
6-
# CHECK: ref.null extern # encoding: [0xd0,0x6f]
5+
# CHECK: ref.null_func # encoding: [0xd0,0x70]
6+
# CHECK: ref.null_extern # encoding: [0xd0,0x6f]
77
ref_null_test:
88
.functype ref_null_test () -> ()
9-
ref.null func
9+
ref.null_func
1010
drop
11-
ref.null extern
11+
ref.null_extern
1212
drop
1313
end_function
1414

@@ -31,13 +31,13 @@ ref_sig_test_externref:
3131
# CHECK: externref.select # encoding: [0x1b]
3232
ref_select_test:
3333
.functype ref_select_test () -> ()
34-
ref.null func
35-
ref.null func
34+
ref.null_func
35+
ref.null_func
3636
i32.const 0
3737
funcref.select
3838
drop
39-
ref.null extern
40-
ref.null extern
39+
ref.null_extern
40+
ref.null_extern
4141
i32.const 0
4242
externref.select
4343
drop
@@ -50,8 +50,8 @@ ref_block_test:
5050
.functype ref_block_test () -> (externref, funcref)
5151
block funcref
5252
block externref
53-
ref.null extern
53+
ref.null_extern
5454
end_block
55-
ref.null func
55+
ref.null_func
5656
end_block
5757
end_function

llvm/utils/TableGen/IntrinsicEmitter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ enum IIT_Info {
252252
IIT_AMX = 51,
253253
IIT_PPCF128 = 52,
254254
IIT_V3 = 53,
255+
IIT_EXTERNREF = 54,
256+
IIT_FUNCREF = 55
255257
};
256258

257259
static void EncodeFixedValueType(MVT::SimpleValueType VT,
@@ -285,6 +287,10 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
285287
case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT);
286288
// MVT::isVoid is used to represent varargs here.
287289
case MVT::isVoid: return Sig.push_back(IIT_VARARG);
290+
case MVT::externref:
291+
return Sig.push_back(IIT_EXTERNREF);
292+
case MVT::funcref:
293+
return Sig.push_back(IIT_FUNCREF);
288294
}
289295
}
290296

0 commit comments

Comments
 (0)