Skip to content

Commit c3536b2

Browse files
sunfishcodeaheejin
andauthored
[WebAssembly] Define call-indirect-overlong and bulk-memory-opt features (#117087)
This defines some new target features. These are subsets of existing features that reflect implementation concerns: - "call-indirect-overlong" - implied by "reference-types"; just the overlong encoding for the `call_indirect` immediate, and not the actual reference types. - "bulk-memory-opt" - implied by "bulk-memory": just `memory.copy` and `memory.fill`, and not the other instructions in the bulk-memory proposal. This is split out from #112035. --------- Co-authored-by: Heejin Ahn <[email protected]>
1 parent f71ea4b commit c3536b2

34 files changed

+190
-69
lines changed

clang/include/clang/Driver/Options.td

+4
Original file line numberDiff line numberDiff line change
@@ -5092,6 +5092,10 @@ def matomics : Flag<["-"], "matomics">, Group<m_wasm_Features_Group>;
50925092
def mno_atomics : Flag<["-"], "mno-atomics">, Group<m_wasm_Features_Group>;
50935093
def mbulk_memory : Flag<["-"], "mbulk-memory">, Group<m_wasm_Features_Group>;
50945094
def mno_bulk_memory : Flag<["-"], "mno-bulk-memory">, Group<m_wasm_Features_Group>;
5095+
def mbulk_memory_opt : Flag<["-"], "mbulk-memory-opt">, Group<m_wasm_Features_Group>;
5096+
def mno_bulk_memory_opt : Flag<["-"], "mno-bulk-memory-opt">, Group<m_wasm_Features_Group>;
5097+
def mcall_indirect_overlong : Flag<["-"], "mcall-indirect-overlong">, Group<m_wasm_Features_Group>;
5098+
def mno_call_indirect_overlong : Flag<["-"], "mno-call-indirect-overlong">, Group<m_wasm_Features_Group>;
50955099
def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Features_Group>;
50965100
def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>;
50975101
def mextended_const : Flag<["-"], "mextended-const">, Group<m_wasm_Features_Group>;

clang/lib/Basic/Targets/WebAssembly.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
4747
return llvm::StringSwitch<bool>(Feature)
4848
.Case("atomics", HasAtomics)
4949
.Case("bulk-memory", HasBulkMemory)
50+
.Case("bulk-memory-opt", HasBulkMemoryOpt)
51+
.Case("call-indirect-overlong", HasCallIndirectOverlong)
5052
.Case("exception-handling", HasExceptionHandling)
5153
.Case("extended-const", HasExtendedConst)
5254
.Case("fp16", HasFP16)
@@ -79,6 +81,8 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
7981
Builder.defineMacro("__wasm_atomics__");
8082
if (HasBulkMemory)
8183
Builder.defineMacro("__wasm_bulk_memory__");
84+
if (HasBulkMemoryOpt)
85+
Builder.defineMacro("__wasm_bulk_memory_opt__");
8286
if (HasExceptionHandling)
8387
Builder.defineMacro("__wasm_exception_handling__");
8488
if (HasExtendedConst)
@@ -155,6 +159,8 @@ bool WebAssemblyTargetInfo::initFeatureMap(
155159
const std::vector<std::string> &FeaturesVec) const {
156160
auto addGenericFeatures = [&]() {
157161
Features["bulk-memory"] = true;
162+
Features["bulk-memory-opt"] = true;
163+
Features["call-indirect-overlong"] = true;
158164
Features["multivalue"] = true;
159165
Features["mutable-globals"] = true;
160166
Features["nontrapping-fptoint"] = true;
@@ -200,6 +206,22 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
200206
HasBulkMemory = false;
201207
continue;
202208
}
209+
if (Feature == "+bulk-memory-opt") {
210+
HasBulkMemoryOpt = true;
211+
continue;
212+
}
213+
if (Feature == "-bulk-memory-opt") {
214+
HasBulkMemoryOpt = false;
215+
continue;
216+
}
217+
if (Feature == "+call-indirect-overlong") {
218+
HasCallIndirectOverlong = true;
219+
continue;
220+
}
221+
if (Feature == "-call-indirect-overlong") {
222+
HasCallIndirectOverlong = false;
223+
continue;
224+
}
203225
if (Feature == "+exception-handling") {
204226
HasExceptionHandling = true;
205227
continue;
@@ -310,6 +332,18 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
310332
<< Feature << "-target-feature";
311333
return false;
312334
}
335+
336+
// bulk-memory-opt is a subset of bulk-memory.
337+
if (HasBulkMemory) {
338+
HasBulkMemoryOpt = true;
339+
}
340+
341+
// The reference-types feature included the change to `call_indirect`
342+
// encodings to support overlong immediates.
343+
if (HasReferenceTypes) {
344+
HasCallIndirectOverlong = true;
345+
}
346+
313347
return true;
314348
}
315349

clang/lib/Basic/Targets/WebAssembly.h

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
5555

5656
bool HasAtomics = false;
5757
bool HasBulkMemory = false;
58+
bool HasBulkMemoryOpt = false;
59+
bool HasCallIndirectOverlong = false;
5860
bool HasExceptionHandling = false;
5961
bool HasExtendedConst = false;
6062
bool HasFP16 = false;

lld/test/wasm/compress-relocs.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llc -filetype=obj %s -o %t.o
2-
; RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o
2+
; RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o
33
; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o
44
; RUN: obj2yaml %t.wasm | FileCheck %s
55
; RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t2.o %t.o

lld/test/wasm/import-table-explicit.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
1+
# RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
22
# RUN: wasm-ld --import-table -o %t.wasm %t.o
33
# RUN: obj2yaml %t.wasm | FileCheck %s
44

lld/test/wasm/invalid-mvp-table-use.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
22
#
33
# If any table is defined or declared besides the __indirect_function_table,
4-
# the compilation unit should be compiled with -mattr=+reference-types,
4+
# the compilation unit should be compiled with -mattr=+call-indirect-overlong,
55
# causing symbol table entries to be emitted for all tables.
66
# RUN: not wasm-ld --no-entry %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
77

lld/test/wasm/lto/Inputs/libcall-archive.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ define void @memcpy() #0 {
55
ret void
66
}
77

8-
attributes #0 = { "target-features"="-bulk-memory" }
8+
attributes #0 = { "target-features"="-bulk-memory,-bulk-memory-opt" }

lld/test/wasm/lto/libcall-archive.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ entry:
1616

1717
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1)
1818

19-
attributes #0 = { "target-features"="-bulk-memory" }
19+
attributes #0 = { "target-features"="-bulk-memory,-bulk-memory-opt" }
2020

2121
; CHECK: - Type: CUSTOM
2222
; CHECK-NEXT: Name: name

lld/test/wasm/lto/stub-library-libcall.s

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_main.o %t/main.s
33
# RUN: llvm-as %S/Inputs/foo.ll -o %t_foo.o
44
# RUN: llvm-as %S/Inputs/libcall.ll -o %t_libcall.o
5-
# RUN: wasm-ld -mllvm -mattr=-bulk-memory %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm
5+
# RUN: wasm-ld -mllvm -mattr=-bulk-memory,-bulk-memory-opt %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm
66
# RUN: obj2yaml %t.wasm | FileCheck %s
77

88
# The function `func_with_libcall` will generate an undefined reference to
@@ -12,7 +12,7 @@
1212
# If %t_foo.o is not included in the link we get an undefined symbol reported
1313
# to the dependency of memcpy on the foo export:
1414

15-
# RUN: not wasm-ld -mllvm -mattr=-bulk-memory %t_main.o %t_libcall.o %p/Inputs/stub.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING %s
15+
# RUN: not wasm-ld -mllvm -mattr=-bulk-memory,-bulk-memory-opt %t_main.o %t_libcall.o %p/Inputs/stub.so -o %t.wasm 2>&1 | FileCheck --check-prefix=MISSING %s
1616
# MISSING: stub.so: undefined symbol: foo. Required by memcpy
1717

1818
#--- main.s

lld/test/wasm/multi-table.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ call_indirect_explicit_tables:
2626
call_indirect table_b, () -> ()
2727
end_function
2828

29-
# RT-MVP: wasm-ld: error: object file not built with 'reference-types' feature conflicts with import of table table_a by file
29+
# RT-MVP: wasm-ld: error: object file not built with 'reference-types' or 'call-indirect-overlong' feature conflicts with import of table table_a by file
3030

3131
# CHECK: --- !WASM
3232
# CHECK-NEXT: FileHeader:

lld/wasm/InputFiles.cpp

+11-10
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,14 @@ static void setRelocs(const std::vector<T *> &chunks,
255255
}
256256
}
257257

258-
// An object file can have two approaches to tables. With the reference-types
259-
// feature enabled, input files that define or use tables declare the tables
260-
// using symbols, and record each use with a relocation. This way when the
261-
// linker combines inputs, it can collate the tables used by the inputs,
262-
// assigning them distinct table numbers, and renumber all the uses as
263-
// appropriate. At the same time, the linker has special logic to build the
264-
// indirect function table if it is needed.
258+
// An object file can have two approaches to tables. With the
259+
// reference-types feature or call-indirect-overlong feature enabled
260+
// (explicitly, or implied by the reference-types feature), input files that
261+
// define or use tables declare the tables using symbols, and record each use
262+
// with a relocation. This way when the linker combines inputs, it can collate
263+
// the tables used by the inputs, assigning them distinct table numbers, and
264+
// renumber all the uses as appropriate. At the same time, the linker has
265+
// special logic to build the indirect function table if it is needed.
265266
//
266267
// However, MVP object files (those that target WebAssembly 1.0, the "minimum
267268
// viable product" version of WebAssembly) neither write table symbols nor
@@ -284,9 +285,9 @@ void ObjFile::addLegacyIndirectFunctionTableIfNeeded(
284285
return;
285286

286287
// It's possible for an input to define tables and also use the indirect
287-
// function table, but forget to compile with -mattr=+reference-types.
288-
// For these newer files, we require symbols for all tables, and
289-
// relocations for all of their uses.
288+
// function table, but forget to compile with -mattr=+call-indirect-overlong
289+
// or -mattr=+reference-types. For these newer files, we require symbols for
290+
// all tables, and relocations for all of their uses.
290291
if (tableSymbolCount != 0) {
291292
error(toString(this) +
292293
": expected one symbol table entry for each of the " +

lld/wasm/SyntheticSections.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,9 @@ void TableSection::addTable(InputTable *table) {
326326
// to assign table number 0 to the indirect function table.
327327
for (const auto *culprit : out.importSec->importedSymbols) {
328328
if (isa<UndefinedTable>(culprit)) {
329-
error("object file not built with 'reference-types' feature "
330-
"conflicts with import of table " +
329+
error("object file not built with 'reference-types' or "
330+
"'call-indirect-overlong' feature conflicts with import of "
331+
"table " +
331332
culprit->getName() + " by file " +
332333
toString(culprit->getFile()));
333334
return;

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

+21-7
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,18 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
276276
: MCTargetAsmParser(Options, STI, MII), Parser(Parser),
277277
Lexer(Parser.getLexer()), Is64(STI.getTargetTriple().isArch64Bit()),
278278
TC(Parser, MII, Is64), SkipTypeCheck(Options.MCNoTypeCheck) {
279-
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
279+
FeatureBitset FBS = ComputeAvailableFeatures(STI.getFeatureBits());
280+
281+
// bulk-memory implies bulk-memory-opt
282+
if (FBS.test(WebAssembly::FeatureBulkMemory)) {
283+
FBS.set(WebAssembly::FeatureBulkMemoryOpt);
284+
}
285+
// reference-types implies call-indirect-overlong
286+
if (FBS.test(WebAssembly::FeatureReferenceTypes)) {
287+
FBS.set(WebAssembly::FeatureCallIndirectOverlong);
288+
}
289+
290+
setAvailableFeatures(FBS);
280291
// Don't type check if this is inline asm, since that is a naked sequence of
281292
// instructions without a function/locals decl.
282293
auto &SM = Parser.getSourceManager();
@@ -291,7 +302,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
291302

292303
DefaultFunctionTable = getOrCreateFunctionTableSymbol(
293304
getContext(), "__indirect_function_table", Is64);
294-
if (!STI->checkFeatures("+reference-types"))
305+
if (!STI->checkFeatures("+call-indirect-overlong") &&
306+
!STI->checkFeatures("+reference-types"))
295307
DefaultFunctionTable->setOmitFromLinkingSection();
296308
}
297309

@@ -531,11 +543,13 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
531543
}
532544

533545
bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
534-
if (STI->checkFeatures("+reference-types")) {
535-
// If the reference-types feature is enabled, there is an explicit table
536-
// operand. To allow the same assembly to be compiled with or without
537-
// reference types, we allow the operand to be omitted, in which case we
538-
// default to __indirect_function_table.
546+
if (STI->checkFeatures("+call-indirect-overlong") ||
547+
STI->checkFeatures("+reference-types")) {
548+
// If the call-indirect-overlong feature is enabled, or implied by the
549+
// reference-types feature, there is an explicit table operand. To allow
550+
// the same assembly to be compiled with or without
551+
// call-indirect-overlong, we allow the operand to be omitted, in which
552+
// case we default to __indirect_function_table.
539553
auto &Tok = Lexer.getTok();
540554
if (Tok.is(AsmToken::Identifier)) {
541555
auto *Sym =

llvm/lib/Target/WebAssembly/WebAssembly.td

+13-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ def FeatureBulkMemory :
2929
SubtargetFeature<"bulk-memory", "HasBulkMemory", "true",
3030
"Enable bulk memory operations">;
3131

32+
def FeatureBulkMemoryOpt :
33+
SubtargetFeature<"bulk-memory-opt", "HasBulkMemoryOpt", "true",
34+
"Enable bulk memory optimization operations">;
35+
36+
def FeatureCallIndirectOverlong :
37+
SubtargetFeature<"call-indirect-overlong", "HasCallIndirectOverlong", "true",
38+
"Enable overlong encoding for call_indirect immediates">;
39+
3240
def FeatureExceptionHandling :
3341
SubtargetFeature<"exception-handling", "HasExceptionHandling", "true",
3442
"Enable Wasm exception handling">;
@@ -114,15 +122,16 @@ def : ProcessorModel<"mvp", NoSchedModel, []>;
114122
// consideration given to available support in relevant engines and tools, and
115123
// the importance of the features.
116124
def : ProcessorModel<"generic", NoSchedModel,
117-
[FeatureBulkMemory, FeatureMultivalue,
125+
[FeatureBulkMemory, FeatureBulkMemoryOpt,
126+
FeatureCallIndirectOverlong, FeatureMultivalue,
118127
FeatureMutableGlobals, FeatureNontrappingFPToInt,
119128
FeatureReferenceTypes, FeatureSignExt]>;
120129

121130
// Latest and greatest experimental version of WebAssembly. Bugs included!
122131
def : ProcessorModel<"bleeding-edge", NoSchedModel,
123-
[FeatureAtomics, FeatureBulkMemory,
124-
FeatureExceptionHandling, FeatureExtendedConst,
125-
FeatureFP16, FeatureMultiMemory,
132+
[FeatureAtomics, FeatureBulkMemory, FeatureBulkMemoryOpt,
133+
FeatureCallIndirectOverlong, FeatureExceptionHandling,
134+
FeatureExtendedConst, FeatureFP16, FeatureMultiMemory,
126135
FeatureMultivalue, FeatureMutableGlobals,
127136
FeatureNontrappingFPToInt, FeatureRelaxedSIMD,
128137
FeatureReferenceTypes, FeatureSIMD128, FeatureSignExt,

llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
895895
// The table into which this call_indirect indexes.
896896
MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(
897897
MF->getContext(), Subtarget);
898-
if (Subtarget->hasReferenceTypes()) {
898+
if (Subtarget->hasCallIndirectOverlong()) {
899899
MIB.addSym(Table);
900900
} else {
901901
// Otherwise for the MVP there is at most one table whose number is 0, but

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB,
768768
MF.getContext(), Subtarget)
769769
: WebAssembly::getOrCreateFunctionTableSymbol(
770770
MF.getContext(), Subtarget);
771-
if (Subtarget->hasReferenceTypes()) {
771+
if (Subtarget->hasCallIndirectOverlong()) {
772772
MIB.addSym(Table);
773773
} else {
774774
// For the MVP there is at most one table whose number is 0, but we can't

llvm/lib/Target/WebAssembly/WebAssemblyInstrBulkMemory.td

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
///
1212
//===----------------------------------------------------------------------===//
1313

14-
// Instruction requiring HasBulkMemory and the bulk memory prefix byte
14+
// Instruction requiring HasBulkMemoryOpt and the bulk memory prefix byte
1515
multiclass BULK_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
1616
list<dag> pattern_r, string asmstr_r = "",
1717
string asmstr_s = "", bits<32> simdop = -1> {
1818
defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s,
1919
!or(0xfc00, !and(0xff, simdop))>,
20-
Requires<[HasBulkMemory]>;
20+
Requires<[HasBulkMemoryOpt]>;
2121
}
2222

2323
// Bespoke types and nodes for bulk memory ops
@@ -89,14 +89,14 @@ defm CPY_A#B : I<(outs), (ins i32imm_op:$src_idx, i32imm_op:$dst_idx,
8989
rc:$dst, rc:$src, rc:$len
9090
)],
9191
"", "", 0>,
92-
Requires<[HasBulkMemory]>;
92+
Requires<[HasBulkMemoryOpt]>;
9393

9494
let usesCustomInserter = 1, isCodeGenOnly = 1, mayStore = 1 in
9595
defm SET_A#B : I<(outs), (ins i32imm_op:$idx, rc:$dst, I32:$value, rc:$size),
9696
(outs), (ins i32imm_op:$idx),
9797
[(wasm_memset (i32 imm:$idx), rc:$dst, I32:$value, rc:$size)],
9898
"", "", 0>,
99-
Requires<[HasBulkMemory]>;
99+
Requires<[HasBulkMemoryOpt]>;
100100

101101
}
102102

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ def HasBulkMemory :
3030
Predicate<"Subtarget->hasBulkMemory()">,
3131
AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
3232

33+
def HasBulkMemoryOpt :
34+
Predicate<"Subtarget->hasBulkMemoryOpt()">,
35+
AssemblerPredicate<(all_of FeatureBulkMemoryOpt), "bulk-memory-opt">;
36+
37+
def HasCallIndirectOverlong :
38+
Predicate<"Subtarget->hasCallIndirectOverlong()">,
39+
AssemblerPredicate<(all_of FeatureCallIndirectOverlong), "call-indirect-overlong">;
40+
3341
def HasExceptionHandling :
3442
Predicate<"Subtarget->hasExceptionHandling()">,
3543
AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;

llvm/lib/Target/WebAssembly/WebAssemblySelectionDAGInfo.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemcpy(
2323
SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,
2424
MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
2525
auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>();
26-
if (!ST.hasBulkMemory())
26+
if (!ST.hasBulkMemoryOpt())
2727
return SDValue();
2828

2929
SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32);
@@ -51,7 +51,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemset(
5151
SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,
5252
MachinePointerInfo DstPtrInfo) const {
5353
auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>();
54-
if (!ST.hasBulkMemory())
54+
if (!ST.hasBulkMemoryOpt())
5555
return SDValue();
5656

5757
SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32);

llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ WebAssemblySubtarget::initializeSubtargetDependencies(StringRef CPU,
3434
CPU = "generic";
3535

3636
ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);
37+
38+
FeatureBitset Bits = getFeatureBits();
39+
40+
// bulk-memory implies bulk-memory-opt
41+
if (HasBulkMemory) {
42+
HasBulkMemoryOpt = true;
43+
Bits.set(WebAssembly::FeatureBulkMemoryOpt);
44+
}
45+
46+
// reference-types implies call-indirect-overlong
47+
if (HasReferenceTypes) {
48+
HasCallIndirectOverlong = true;
49+
Bits.set(WebAssembly::FeatureCallIndirectOverlong);
50+
}
51+
52+
// In case we changed any bits, update `MCSubtargetInfo`'s `FeatureBitset`.
53+
setFeatureBits(Bits);
54+
3755
return *this;
3856
}
3957

0 commit comments

Comments
 (0)