[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 https://github.com/llvm/llvm-project/pull/112035. --------- Co-authored-by: Heejin Ahn <aheejin@gmail.com>
This commit is contained in:
@@ -5092,6 +5092,10 @@ def matomics : Flag<["-"], "matomics">, Group<m_wasm_Features_Group>;
|
||||
def mno_atomics : Flag<["-"], "mno-atomics">, Group<m_wasm_Features_Group>;
|
||||
def mbulk_memory : Flag<["-"], "mbulk-memory">, Group<m_wasm_Features_Group>;
|
||||
def mno_bulk_memory : Flag<["-"], "mno-bulk-memory">, Group<m_wasm_Features_Group>;
|
||||
def mbulk_memory_opt : Flag<["-"], "mbulk-memory-opt">, Group<m_wasm_Features_Group>;
|
||||
def mno_bulk_memory_opt : Flag<["-"], "mno-bulk-memory-opt">, Group<m_wasm_Features_Group>;
|
||||
def mcall_indirect_overlong : Flag<["-"], "mcall-indirect-overlong">, Group<m_wasm_Features_Group>;
|
||||
def mno_call_indirect_overlong : Flag<["-"], "mno-call-indirect-overlong">, Group<m_wasm_Features_Group>;
|
||||
def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Features_Group>;
|
||||
def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>;
|
||||
def mextended_const : Flag<["-"], "mextended-const">, Group<m_wasm_Features_Group>;
|
||||
|
||||
@@ -47,6 +47,8 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
|
||||
return llvm::StringSwitch<bool>(Feature)
|
||||
.Case("atomics", HasAtomics)
|
||||
.Case("bulk-memory", HasBulkMemory)
|
||||
.Case("bulk-memory-opt", HasBulkMemoryOpt)
|
||||
.Case("call-indirect-overlong", HasCallIndirectOverlong)
|
||||
.Case("exception-handling", HasExceptionHandling)
|
||||
.Case("extended-const", HasExtendedConst)
|
||||
.Case("fp16", HasFP16)
|
||||
@@ -79,6 +81,8 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
|
||||
Builder.defineMacro("__wasm_atomics__");
|
||||
if (HasBulkMemory)
|
||||
Builder.defineMacro("__wasm_bulk_memory__");
|
||||
if (HasBulkMemoryOpt)
|
||||
Builder.defineMacro("__wasm_bulk_memory_opt__");
|
||||
if (HasExceptionHandling)
|
||||
Builder.defineMacro("__wasm_exception_handling__");
|
||||
if (HasExtendedConst)
|
||||
@@ -155,6 +159,8 @@ bool WebAssemblyTargetInfo::initFeatureMap(
|
||||
const std::vector<std::string> &FeaturesVec) const {
|
||||
auto addGenericFeatures = [&]() {
|
||||
Features["bulk-memory"] = true;
|
||||
Features["bulk-memory-opt"] = true;
|
||||
Features["call-indirect-overlong"] = true;
|
||||
Features["multivalue"] = true;
|
||||
Features["mutable-globals"] = true;
|
||||
Features["nontrapping-fptoint"] = true;
|
||||
@@ -200,6 +206,22 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
|
||||
HasBulkMemory = false;
|
||||
continue;
|
||||
}
|
||||
if (Feature == "+bulk-memory-opt") {
|
||||
HasBulkMemoryOpt = true;
|
||||
continue;
|
||||
}
|
||||
if (Feature == "-bulk-memory-opt") {
|
||||
HasBulkMemoryOpt = false;
|
||||
continue;
|
||||
}
|
||||
if (Feature == "+call-indirect-overlong") {
|
||||
HasCallIndirectOverlong = true;
|
||||
continue;
|
||||
}
|
||||
if (Feature == "-call-indirect-overlong") {
|
||||
HasCallIndirectOverlong = false;
|
||||
continue;
|
||||
}
|
||||
if (Feature == "+exception-handling") {
|
||||
HasExceptionHandling = true;
|
||||
continue;
|
||||
@@ -310,6 +332,18 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
|
||||
<< Feature << "-target-feature";
|
||||
return false;
|
||||
}
|
||||
|
||||
// bulk-memory-opt is a subset of bulk-memory.
|
||||
if (HasBulkMemory) {
|
||||
HasBulkMemoryOpt = true;
|
||||
}
|
||||
|
||||
// The reference-types feature included the change to `call_indirect`
|
||||
// encodings to support overlong immediates.
|
||||
if (HasReferenceTypes) {
|
||||
HasCallIndirectOverlong = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
|
||||
|
||||
bool HasAtomics = false;
|
||||
bool HasBulkMemory = false;
|
||||
bool HasBulkMemoryOpt = false;
|
||||
bool HasCallIndirectOverlong = false;
|
||||
bool HasExceptionHandling = false;
|
||||
bool HasExtendedConst = false;
|
||||
bool HasFP16 = false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: llc -filetype=obj %s -o %t.o
|
||||
; RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o
|
||||
; RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/call-indirect.s -o %t2.o
|
||||
; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o
|
||||
; RUN: obj2yaml %t.wasm | FileCheck %s
|
||||
; RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t2.o %t.o
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
|
||||
# RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
|
||||
# RUN: wasm-ld --import-table -o %t.wasm %t.o
|
||||
# RUN: obj2yaml %t.wasm | FileCheck %s
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
|
||||
#
|
||||
# If any table is defined or declared besides the __indirect_function_table,
|
||||
# the compilation unit should be compiled with -mattr=+reference-types,
|
||||
# the compilation unit should be compiled with -mattr=+call-indirect-overlong,
|
||||
# causing symbol table entries to be emitted for all tables.
|
||||
# RUN: not wasm-ld --no-entry %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ define void @memcpy() #0 {
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="-bulk-memory" }
|
||||
attributes #0 = { "target-features"="-bulk-memory,-bulk-memory-opt" }
|
||||
|
||||
@@ -16,7 +16,7 @@ entry:
|
||||
|
||||
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1)
|
||||
|
||||
attributes #0 = { "target-features"="-bulk-memory" }
|
||||
attributes #0 = { "target-features"="-bulk-memory,-bulk-memory-opt" }
|
||||
|
||||
; CHECK: - Type: CUSTOM
|
||||
; CHECK-NEXT: Name: name
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t_main.o %t/main.s
|
||||
# RUN: llvm-as %S/Inputs/foo.ll -o %t_foo.o
|
||||
# RUN: llvm-as %S/Inputs/libcall.ll -o %t_libcall.o
|
||||
# RUN: wasm-ld -mllvm -mattr=-bulk-memory %t_main.o %t_libcall.o %t_foo.o %p/Inputs/stub.so -o %t.wasm
|
||||
# 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
|
||||
# RUN: obj2yaml %t.wasm | FileCheck %s
|
||||
|
||||
# The function `func_with_libcall` will generate an undefined reference to
|
||||
@@ -12,7 +12,7 @@
|
||||
# If %t_foo.o is not included in the link we get an undefined symbol reported
|
||||
# to the dependency of memcpy on the foo export:
|
||||
|
||||
# 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
|
||||
# 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
|
||||
# MISSING: stub.so: undefined symbol: foo. Required by memcpy
|
||||
|
||||
#--- main.s
|
||||
|
||||
@@ -26,7 +26,7 @@ call_indirect_explicit_tables:
|
||||
call_indirect table_b, () -> ()
|
||||
end_function
|
||||
|
||||
# RT-MVP: wasm-ld: error: object file not built with 'reference-types' feature conflicts with import of table table_a by file
|
||||
# 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
|
||||
|
||||
# CHECK: --- !WASM
|
||||
# CHECK-NEXT: FileHeader:
|
||||
|
||||
@@ -255,13 +255,14 @@ static void setRelocs(const std::vector<T *> &chunks,
|
||||
}
|
||||
}
|
||||
|
||||
// An object file can have two approaches to tables. With the reference-types
|
||||
// feature enabled, input files that define or use tables declare the tables
|
||||
// using symbols, and record each use with a relocation. This way when the
|
||||
// linker combines inputs, it can collate the tables used by the inputs,
|
||||
// assigning them distinct table numbers, and renumber all the uses as
|
||||
// appropriate. At the same time, the linker has special logic to build the
|
||||
// indirect function table if it is needed.
|
||||
// An object file can have two approaches to tables. With the
|
||||
// reference-types feature or call-indirect-overlong feature enabled
|
||||
// (explicitly, or implied by the reference-types feature), input files that
|
||||
// define or use tables declare the tables using symbols, and record each use
|
||||
// with a relocation. This way when the linker combines inputs, it can collate
|
||||
// the tables used by the inputs, assigning them distinct table numbers, and
|
||||
// renumber all the uses as appropriate. At the same time, the linker has
|
||||
// special logic to build the indirect function table if it is needed.
|
||||
//
|
||||
// However, MVP object files (those that target WebAssembly 1.0, the "minimum
|
||||
// viable product" version of WebAssembly) neither write table symbols nor
|
||||
@@ -284,9 +285,9 @@ void ObjFile::addLegacyIndirectFunctionTableIfNeeded(
|
||||
return;
|
||||
|
||||
// It's possible for an input to define tables and also use the indirect
|
||||
// function table, but forget to compile with -mattr=+reference-types.
|
||||
// For these newer files, we require symbols for all tables, and
|
||||
// relocations for all of their uses.
|
||||
// function table, but forget to compile with -mattr=+call-indirect-overlong
|
||||
// or -mattr=+reference-types. For these newer files, we require symbols for
|
||||
// all tables, and relocations for all of their uses.
|
||||
if (tableSymbolCount != 0) {
|
||||
error(toString(this) +
|
||||
": expected one symbol table entry for each of the " +
|
||||
|
||||
@@ -326,8 +326,9 @@ void TableSection::addTable(InputTable *table) {
|
||||
// to assign table number 0 to the indirect function table.
|
||||
for (const auto *culprit : out.importSec->importedSymbols) {
|
||||
if (isa<UndefinedTable>(culprit)) {
|
||||
error("object file not built with 'reference-types' feature "
|
||||
"conflicts with import of table " +
|
||||
error("object file not built with 'reference-types' or "
|
||||
"'call-indirect-overlong' feature conflicts with import of "
|
||||
"table " +
|
||||
culprit->getName() + " by file " +
|
||||
toString(culprit->getFile()));
|
||||
return;
|
||||
|
||||
@@ -276,7 +276,18 @@ public:
|
||||
: MCTargetAsmParser(Options, STI, MII), Parser(Parser),
|
||||
Lexer(Parser.getLexer()), Is64(STI.getTargetTriple().isArch64Bit()),
|
||||
TC(Parser, MII, Is64), SkipTypeCheck(Options.MCNoTypeCheck) {
|
||||
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
||||
FeatureBitset FBS = ComputeAvailableFeatures(STI.getFeatureBits());
|
||||
|
||||
// bulk-memory implies bulk-memory-opt
|
||||
if (FBS.test(WebAssembly::FeatureBulkMemory)) {
|
||||
FBS.set(WebAssembly::FeatureBulkMemoryOpt);
|
||||
}
|
||||
// reference-types implies call-indirect-overlong
|
||||
if (FBS.test(WebAssembly::FeatureReferenceTypes)) {
|
||||
FBS.set(WebAssembly::FeatureCallIndirectOverlong);
|
||||
}
|
||||
|
||||
setAvailableFeatures(FBS);
|
||||
// Don't type check if this is inline asm, since that is a naked sequence of
|
||||
// instructions without a function/locals decl.
|
||||
auto &SM = Parser.getSourceManager();
|
||||
@@ -291,7 +302,8 @@ public:
|
||||
|
||||
DefaultFunctionTable = getOrCreateFunctionTableSymbol(
|
||||
getContext(), "__indirect_function_table", Is64);
|
||||
if (!STI->checkFeatures("+reference-types"))
|
||||
if (!STI->checkFeatures("+call-indirect-overlong") &&
|
||||
!STI->checkFeatures("+reference-types"))
|
||||
DefaultFunctionTable->setOmitFromLinkingSection();
|
||||
}
|
||||
|
||||
@@ -531,11 +543,13 @@ public:
|
||||
}
|
||||
|
||||
bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
|
||||
if (STI->checkFeatures("+reference-types")) {
|
||||
// If the reference-types feature is enabled, there is an explicit table
|
||||
// operand. To allow the same assembly to be compiled with or without
|
||||
// reference types, we allow the operand to be omitted, in which case we
|
||||
// default to __indirect_function_table.
|
||||
if (STI->checkFeatures("+call-indirect-overlong") ||
|
||||
STI->checkFeatures("+reference-types")) {
|
||||
// If the call-indirect-overlong feature is enabled, or implied by the
|
||||
// reference-types feature, there is an explicit table operand. To allow
|
||||
// the same assembly to be compiled with or without
|
||||
// call-indirect-overlong, we allow the operand to be omitted, in which
|
||||
// case we default to __indirect_function_table.
|
||||
auto &Tok = Lexer.getTok();
|
||||
if (Tok.is(AsmToken::Identifier)) {
|
||||
auto *Sym =
|
||||
|
||||
@@ -29,6 +29,14 @@ def FeatureBulkMemory :
|
||||
SubtargetFeature<"bulk-memory", "HasBulkMemory", "true",
|
||||
"Enable bulk memory operations">;
|
||||
|
||||
def FeatureBulkMemoryOpt :
|
||||
SubtargetFeature<"bulk-memory-opt", "HasBulkMemoryOpt", "true",
|
||||
"Enable bulk memory optimization operations">;
|
||||
|
||||
def FeatureCallIndirectOverlong :
|
||||
SubtargetFeature<"call-indirect-overlong", "HasCallIndirectOverlong", "true",
|
||||
"Enable overlong encoding for call_indirect immediates">;
|
||||
|
||||
def FeatureExceptionHandling :
|
||||
SubtargetFeature<"exception-handling", "HasExceptionHandling", "true",
|
||||
"Enable Wasm exception handling">;
|
||||
@@ -114,15 +122,16 @@ def : ProcessorModel<"mvp", NoSchedModel, []>;
|
||||
// consideration given to available support in relevant engines and tools, and
|
||||
// the importance of the features.
|
||||
def : ProcessorModel<"generic", NoSchedModel,
|
||||
[FeatureBulkMemory, FeatureMultivalue,
|
||||
[FeatureBulkMemory, FeatureBulkMemoryOpt,
|
||||
FeatureCallIndirectOverlong, FeatureMultivalue,
|
||||
FeatureMutableGlobals, FeatureNontrappingFPToInt,
|
||||
FeatureReferenceTypes, FeatureSignExt]>;
|
||||
|
||||
// Latest and greatest experimental version of WebAssembly. Bugs included!
|
||||
def : ProcessorModel<"bleeding-edge", NoSchedModel,
|
||||
[FeatureAtomics, FeatureBulkMemory,
|
||||
FeatureExceptionHandling, FeatureExtendedConst,
|
||||
FeatureFP16, FeatureMultiMemory,
|
||||
[FeatureAtomics, FeatureBulkMemory, FeatureBulkMemoryOpt,
|
||||
FeatureCallIndirectOverlong, FeatureExceptionHandling,
|
||||
FeatureExtendedConst, FeatureFP16, FeatureMultiMemory,
|
||||
FeatureMultivalue, FeatureMutableGlobals,
|
||||
FeatureNontrappingFPToInt, FeatureRelaxedSIMD,
|
||||
FeatureReferenceTypes, FeatureSIMD128, FeatureSignExt,
|
||||
|
||||
@@ -895,7 +895,7 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) {
|
||||
// The table into which this call_indirect indexes.
|
||||
MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(
|
||||
MF->getContext(), Subtarget);
|
||||
if (Subtarget->hasReferenceTypes()) {
|
||||
if (Subtarget->hasCallIndirectOverlong()) {
|
||||
MIB.addSym(Table);
|
||||
} else {
|
||||
// Otherwise for the MVP there is at most one table whose number is 0, but
|
||||
|
||||
@@ -768,7 +768,7 @@ LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB,
|
||||
MF.getContext(), Subtarget)
|
||||
: WebAssembly::getOrCreateFunctionTableSymbol(
|
||||
MF.getContext(), Subtarget);
|
||||
if (Subtarget->hasReferenceTypes()) {
|
||||
if (Subtarget->hasCallIndirectOverlong()) {
|
||||
MIB.addSym(Table);
|
||||
} else {
|
||||
// For the MVP there is at most one table whose number is 0, but we can't
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Instruction requiring HasBulkMemory and the bulk memory prefix byte
|
||||
// Instruction requiring HasBulkMemoryOpt and the bulk memory prefix byte
|
||||
multiclass BULK_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
|
||||
list<dag> pattern_r, string asmstr_r = "",
|
||||
string asmstr_s = "", bits<32> simdop = -1> {
|
||||
defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s,
|
||||
!or(0xfc00, !and(0xff, simdop))>,
|
||||
Requires<[HasBulkMemory]>;
|
||||
Requires<[HasBulkMemoryOpt]>;
|
||||
}
|
||||
|
||||
// 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,
|
||||
rc:$dst, rc:$src, rc:$len
|
||||
)],
|
||||
"", "", 0>,
|
||||
Requires<[HasBulkMemory]>;
|
||||
Requires<[HasBulkMemoryOpt]>;
|
||||
|
||||
let usesCustomInserter = 1, isCodeGenOnly = 1, mayStore = 1 in
|
||||
defm SET_A#B : I<(outs), (ins i32imm_op:$idx, rc:$dst, I32:$value, rc:$size),
|
||||
(outs), (ins i32imm_op:$idx),
|
||||
[(wasm_memset (i32 imm:$idx), rc:$dst, I32:$value, rc:$size)],
|
||||
"", "", 0>,
|
||||
Requires<[HasBulkMemory]>;
|
||||
Requires<[HasBulkMemoryOpt]>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,14 @@ def HasBulkMemory :
|
||||
Predicate<"Subtarget->hasBulkMemory()">,
|
||||
AssemblerPredicate<(all_of FeatureBulkMemory), "bulk-memory">;
|
||||
|
||||
def HasBulkMemoryOpt :
|
||||
Predicate<"Subtarget->hasBulkMemoryOpt()">,
|
||||
AssemblerPredicate<(all_of FeatureBulkMemoryOpt), "bulk-memory-opt">;
|
||||
|
||||
def HasCallIndirectOverlong :
|
||||
Predicate<"Subtarget->hasCallIndirectOverlong()">,
|
||||
AssemblerPredicate<(all_of FeatureCallIndirectOverlong), "call-indirect-overlong">;
|
||||
|
||||
def HasExceptionHandling :
|
||||
Predicate<"Subtarget->hasExceptionHandling()">,
|
||||
AssemblerPredicate<(all_of FeatureExceptionHandling), "exception-handling">;
|
||||
|
||||
@@ -23,7 +23,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemcpy(
|
||||
SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
|
||||
auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>();
|
||||
if (!ST.hasBulkMemory())
|
||||
if (!ST.hasBulkMemoryOpt())
|
||||
return SDValue();
|
||||
|
||||
SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32);
|
||||
@@ -51,7 +51,7 @@ SDValue WebAssemblySelectionDAGInfo::EmitTargetCodeForMemset(
|
||||
SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo) const {
|
||||
auto &ST = DAG.getMachineFunction().getSubtarget<WebAssemblySubtarget>();
|
||||
if (!ST.hasBulkMemory())
|
||||
if (!ST.hasBulkMemoryOpt())
|
||||
return SDValue();
|
||||
|
||||
SDValue MemIdx = DAG.getConstant(0, DL, MVT::i32);
|
||||
|
||||
@@ -34,6 +34,24 @@ WebAssemblySubtarget::initializeSubtargetDependencies(StringRef CPU,
|
||||
CPU = "generic";
|
||||
|
||||
ParseSubtargetFeatures(CPU, /*TuneCPU*/ CPU, FS);
|
||||
|
||||
FeatureBitset Bits = getFeatureBits();
|
||||
|
||||
// bulk-memory implies bulk-memory-opt
|
||||
if (HasBulkMemory) {
|
||||
HasBulkMemoryOpt = true;
|
||||
Bits.set(WebAssembly::FeatureBulkMemoryOpt);
|
||||
}
|
||||
|
||||
// reference-types implies call-indirect-overlong
|
||||
if (HasReferenceTypes) {
|
||||
HasCallIndirectOverlong = true;
|
||||
Bits.set(WebAssembly::FeatureCallIndirectOverlong);
|
||||
}
|
||||
|
||||
// In case we changed any bits, update `MCSubtargetInfo`'s `FeatureBitset`.
|
||||
setFeatureBits(Bits);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo {
|
||||
|
||||
bool HasAtomics = false;
|
||||
bool HasBulkMemory = false;
|
||||
bool HasBulkMemoryOpt = false;
|
||||
bool HasCallIndirectOverlong = false;
|
||||
bool HasExceptionHandling = false;
|
||||
bool HasExtendedConst = false;
|
||||
bool HasFP16 = false;
|
||||
@@ -95,6 +97,8 @@ public:
|
||||
bool hasAddr64() const { return TargetTriple.isArch64Bit(); }
|
||||
bool hasAtomics() const { return HasAtomics; }
|
||||
bool hasBulkMemory() const { return HasBulkMemory; }
|
||||
bool hasBulkMemoryOpt() const { return HasBulkMemoryOpt; }
|
||||
bool hasCallIndirectOverlong() const { return HasCallIndirectOverlong; }
|
||||
bool hasExceptionHandling() const { return HasExceptionHandling; }
|
||||
bool hasExtendedConst() const { return HasExtendedConst; }
|
||||
bool hasFP16() const { return HasFP16; }
|
||||
|
||||
@@ -116,7 +116,7 @@ MCSymbolWasm *WebAssembly::getOrCreateFunctionTableSymbol(
|
||||
Sym->setUndefined();
|
||||
}
|
||||
// MVP object files can't have symtab entries for tables.
|
||||
if (!(Subtarget && Subtarget->hasReferenceTypes()))
|
||||
if (!(Subtarget && Subtarget->hasCallIndirectOverlong()))
|
||||
Sym->setOmitFromLinkingSection();
|
||||
return Sym;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ MCSymbolWasm *WebAssembly::getOrCreateFuncrefCallTableSymbol(
|
||||
Sym->setTableType(TableType);
|
||||
}
|
||||
// MVP object files can't have symtab entries for tables.
|
||||
if (!(Subtarget && Subtarget->hasReferenceTypes()))
|
||||
if (!(Subtarget && Subtarget->hasCallIndirectOverlong()))
|
||||
Sym->setOmitFromLinkingSection();
|
||||
return Sym;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types -O2 | FileCheck --check-prefixes=CHECK,NOREF %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=+reference-types -O2 | FileCheck --check-prefixes=CHECK,REF %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types,-call-indirect-overlong -O2 | FileCheck --check-prefixes=CHECK,NOREF %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=+call-indirect-overlong -O2 | FileCheck --check-prefixes=CHECK,REF %s
|
||||
; RUN: llc < %s -asm-verbose=false -O2 --filetype=obj | obj2yaml | FileCheck --check-prefix=OBJ %s
|
||||
|
||||
; Test that compilation units with call_indirect but without any
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
; REQUIRES: asserts
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,bulk-memory | FileCheck %s
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,bulk-memory
|
||||
; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory | FileCheck %s --check-prefix=NOOPT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS
|
||||
; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt | FileCheck %s --check-prefix=NOOPT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
; REQUIRES: asserts
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,bulk-memory | FileCheck %s
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,bulk-memory
|
||||
; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -verify-machineinstrs -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory | FileCheck %s --check-prefix=NOOPT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS
|
||||
; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -verify-machineinstrs -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt | FileCheck %s --check-prefix=NOOPT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT
|
||||
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -wasm-enable-eh -wasm-enable-exnref -exception-model=wasm -mattr=+exception-handling,-bulk-memory,-bulk-memory-opt -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mattr=-sign-ext,-bulk-memory | FileCheck %s
|
||||
; RUN: llc < %s -mattr=-sign-ext,-bulk-memory,-bulk-memory-opt | FileCheck %s
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
@@ -21,7 +21,7 @@ define i8 @not_use_extend8_s(i8 %v, i8 %x) {
|
||||
ret i8 %a
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory," }
|
||||
attributes #0 = { "target-features"="+bulk-memory-opt" }
|
||||
|
||||
declare void @llvm.memset.p0.i32(ptr, i8, i32, i1)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types -O2 | FileCheck %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types,-call-indirect-overlong -O2 | FileCheck %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=+reference-types -O2 | FileCheck --check-prefix=REF %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types -O2 --filetype=obj | obj2yaml | FileCheck --check-prefix=YAML %s
|
||||
; RUN: llc < %s -asm-verbose=false -mattr=-reference-types,-call-indirect-overlong -O2 --filetype=obj | obj2yaml | FileCheck --check-prefix=YAML %s
|
||||
|
||||
; This tests pointer features that may codegen differently in wasm64.
|
||||
|
||||
|
||||
@@ -7,7 +7,11 @@ define void @reference-types() {
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: .int8 1
|
||||
; CHECK: .section .custom_section.target_features,"",@
|
||||
; CHECK-NEXT: .int8 2
|
||||
; CHECK-NEXT: .int8 43
|
||||
; CHECK-NEXT: .int8 22
|
||||
; CHECK-NEXT: .ascii "call-indirect-overlong"
|
||||
; CHECK-NEXT: .int8 43
|
||||
; CHECK-NEXT: .int8 15
|
||||
; CHECK-NEXT: .ascii "reference-types"
|
||||
|
||||
@@ -55,11 +55,14 @@ attributes #2 = { "target-features"="+reference-types" }
|
||||
; Features in function attributes:
|
||||
; +atomics, +nontrapping-fptoint, +reference-types
|
||||
; CHECK-LABEL: .custom_section.target_features,"",@
|
||||
; CHECK-NEXT: .int8 3
|
||||
; CHECK-NEXT: .int8 4
|
||||
; CHECK-NEXT: .int8 43
|
||||
; CHECK-NEXT: .int8 7
|
||||
; CHECK-NEXT: .ascii "atomics"
|
||||
; CHECK-NEXT: .int8 43
|
||||
; CHECK-NEXT: .int8 22
|
||||
; CHECK-NEXT: .ascii "call-indirect-overlong"
|
||||
; CHECK-NEXT: .int8 43
|
||||
; CHECK-NEXT: .int8 19
|
||||
; CHECK-NEXT: .ascii "nontrapping-fptoint"
|
||||
; CHECK-NEXT: .int8 43
|
||||
@@ -69,11 +72,14 @@ attributes #2 = { "target-features"="+reference-types" }
|
||||
; Features in function attributes + features specified by -mattr= option:
|
||||
; +atomics, +nontrapping-fptoint, +reference-types, +simd128
|
||||
; SIMD128-LABEL: .custom_section.target_features,"",@
|
||||
; SIMD128-NEXT: .int8 4
|
||||
; SIMD128-NEXT: .int8 5
|
||||
; SIMD128-NEXT: .int8 43
|
||||
; SIMD128-NEXT: .int8 7
|
||||
; SIMD128-NEXT: .ascii "atomics"
|
||||
; SIMD128-NEXT: .int8 43
|
||||
; SIMD128-NEXT: .int8 22
|
||||
; SIMD128-NEXT: .ascii "call-indirect-overlong"
|
||||
; SIMD128-NEXT: .int8 43
|
||||
; SIMD128-NEXT: .int8 19
|
||||
; SIMD128-NEXT: .ascii "nontrapping-fptoint"
|
||||
; SIMD128-NEXT: .int8 43
|
||||
|
||||
@@ -11,13 +11,19 @@ target triple = "wasm32-unknown-unknown"
|
||||
; mvp: should not contain the target features section
|
||||
; MVP-NOT: .custom_section.target_features,"",@
|
||||
|
||||
; generic: +multivalue, +mutable-globals, +reference-types, +sign-ext
|
||||
; generic: +call-indirect-overlong, +multivalue, +mutable-globals, +reference-types, +sign-ext
|
||||
; GENERIC-LABEL: .custom_section.target_features,"",@
|
||||
; GENERIC-NEXT: .int8 6
|
||||
; GENERIC-NEXT: .int8 8
|
||||
; GENERIC-NEXT: .int8 43
|
||||
; GENERIC-NEXT: .int8 11
|
||||
; GENERIC-NEXT: .ascii "bulk-memory"
|
||||
; GENERIC-NEXT: .int8 43
|
||||
; GENERIC-NEXT: .int8 15
|
||||
; GENERIC-NEXT: .ascii "bulk-memory-opt"
|
||||
; GENERIC-NEXT: .int8 43
|
||||
; GENERIC-NEXT: .int8 22
|
||||
; GENERIC-NEXT: .ascii "call-indirect-overlong"
|
||||
; GENERIC-NEXT: .int8 43
|
||||
; GENERIC-NEXT: .int8 10
|
||||
; GENERIC-NEXT: .ascii "multivalue"
|
||||
; GENERIC-NEXT: .int8 43
|
||||
@@ -33,12 +39,13 @@ target triple = "wasm32-unknown-unknown"
|
||||
; GENERIC-NEXT: .int8 8
|
||||
; GENERIC-NEXT: .ascii "sign-ext"
|
||||
|
||||
; bleeding-edge: +atomics, +bulk-memory, +exception-handling, +extended-const,
|
||||
; +fp16, +multimemory, +multivalue, +mutable-globals,
|
||||
; +nontrapping-fptoint, +relaxed-simd, +reference-types,
|
||||
; +simd128, +sign-ext, +tail-call
|
||||
; bleeding-edge: +atomics, +bulk-memory, +bulk-memory-opt,
|
||||
; +call-indirect-overlong, +exception-handling,
|
||||
; +extended-const, +fp16, +multimemory, +multivalue,
|
||||
; +mutable-globals, +nontrapping-fptoint, +relaxed-simd,
|
||||
; +reference-types, +simd128, +sign-ext, +tail-call
|
||||
; BLEEDING-EDGE-LABEL: .section .custom_section.target_features,"",@
|
||||
; BLEEDING-EDGE-NEXT: .int8 14
|
||||
; BLEEDING-EDGE-NEXT: .int8 16
|
||||
; BLEEDING-EDGE-NEXT: .int8 43
|
||||
; BLEEDING-EDGE-NEXT: .int8 7
|
||||
; BLEEDING-EDGE-NEXT: .ascii "atomics"
|
||||
@@ -46,6 +53,12 @@ target triple = "wasm32-unknown-unknown"
|
||||
; BLEEDING-EDGE-NEXT: .int8 11
|
||||
; BLEEDING-EDGE-NEXT: .ascii "bulk-memory"
|
||||
; BLEEDING-EDGE-NEXT: .int8 43
|
||||
; BLEEDING-EDGE-NEXT: .int8 15
|
||||
; BLEEDING-EDGE-NEXT: .ascii "bulk-memory-opt"
|
||||
; BLEEDING-EDGE-NEXT: .int8 43
|
||||
; BLEEDING-EDGE-NEXT: .int8 22
|
||||
; BLEEDING-EDGE-NEXT: .ascii "call-indirect-overlong"
|
||||
; BLEEDING-EDGE-NEXT: .int8 43
|
||||
; BLEEDING-EDGE-NEXT: .int8 18
|
||||
; BLEEDING-EDGE-NEXT: .ascii "exception-handling"
|
||||
; BLEEDING-EDGE-NEXT: .int8 43
|
||||
|
||||
@@ -21,11 +21,14 @@ target triple = "wasm32-unknown-unknown"
|
||||
|
||||
; +bulk-memory
|
||||
; BULK-MEM-LABEL: .custom_section.target_features,"",@
|
||||
; BULK-MEM-NEXT: .int8 2
|
||||
; BULK-MEM-NEXT: .int8 3
|
||||
; BULK-MEM-NEXT: .int8 43
|
||||
; BULK-MEM-NEXT: .int8 7
|
||||
; BULK-MEM-NEXT: .ascii "atomics"
|
||||
; BULK-MEM-NEXT: .int8 43
|
||||
; BULK-MEM-NEXT: .int8 11
|
||||
; BULK-MEM-NEXT: .ascii "bulk-memory"
|
||||
; BULK-MEM-NEXT: .int8 43
|
||||
; BULK-MEM-NEXT: .int8 15
|
||||
; BULK-MEM-NEXT: .ascii "bulk-memory-opt"
|
||||
; BULK-MEM-NEXT: .tbss.foo,"T",@
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: llc %s -mattr=-bulk-memory -o - | FileCheck %s
|
||||
; RUN: llc %s -mattr=-bulk-memory -o - | llvm-mc -triple=wasm32-unknown-unknown | FileCheck %s
|
||||
; RUN: llc %s -mattr=-bulk-memory,-bulk-memory-opt -o - | FileCheck %s
|
||||
; RUN: llc %s -mattr=-bulk-memory,-bulk-memory-opt -o - | llvm-mc -triple=wasm32-unknown-unknown | FileCheck %s
|
||||
|
||||
; ModuleID = 'test.c'
|
||||
source_filename = "test.c"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; RUN: llc -filetype=obj %s -mattr=-reference-types -o - | llvm-readobj --symbols - | FileCheck %s
|
||||
; RUN: llc -filetype=obj %s -mattr=+reference-types -o - | llvm-readobj --symbols - | FileCheck --check-prefix=REF %s
|
||||
; RUN: llc -filetype=obj %s -mattr=-reference-types,-call-indirect-overlong -o - | llvm-readobj --symbols - | FileCheck %s
|
||||
; RUN: llc -filetype=obj %s -mattr=+reference-types,-call-indirect-overlong -o - | llvm-readobj --symbols - | FileCheck --check-prefix=REF %s
|
||||
|
||||
target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
; RUN: llc -filetype=obj -mattr=-bulk-memory %s -o - | obj2yaml | FileCheck %s
|
||||
; RUN: llc -filetype=obj -mattr=-bulk-memory,-bulk-memory-opt %s -o - | obj2yaml | FileCheck %s
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user