From: Thomas Lively Date: Fri, 29 Mar 2019 00:14:01 +0000 (+0000) Subject: [WebAssembly] Merge used feature sets, update atomics linkage policy X-Git-Tag: llvmorg-10-init~8930 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3f34e1b883351c7d98426b084386a7aa762aa366;p=platform%2Fupstream%2Fllvm.git [WebAssembly] Merge used feature sets, update atomics linkage policy Summary: It does not currently make sense to use WebAssembly features in some functions but not others, so this CL adds an IR pass that takes the union of all used feature sets and applies it to each function in the module. This allows us to prevent atomics from being lowered away if some function has opted in to using them. When atomics is not enabled anywhere, we detect whether there exists any atomic operations or thread local storage that would be stripped and disallow linking with objects that contain atomics if and only if atomics or tls are stripped. When atomics is enabled, mark it as used but do not require it of other objects in the link. These changes allow libraries that do not use atomics to be built once and linked into both single-threaded and multithreaded binaries. Reviewers: aheejin, sbc100, dschuff Subscribers: jgravelle-google, hiraditya, sunfish, jfb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59625 llvm-svn: 357226 --- diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 303fd3ed..7d12dd7 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -14,6 +14,7 @@ #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H #define LLVM_LIB_TARGET_WEBASSEMBLY_MCTARGETDESC_WEBASSEMBLYMCTARGETDESC_H +#include "../WebAssemblySubtarget.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/DataTypes.h" @@ -115,9 +116,6 @@ enum TOF { #define GET_INSTRINFO_ENUM #include "WebAssemblyGenInstrInfo.inc" -#define GET_SUBTARGETINFO_ENUM -#include "WebAssemblyGenSubtargetInfo.inc" - namespace llvm { namespace WebAssembly { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index e412927..2e6de3c 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -33,6 +33,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Metadata.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCStreamer.h" @@ -161,7 +162,7 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { } EmitProducerInfo(M); - EmitTargetFeatures(); + EmitTargetFeatures(M); } void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) { @@ -215,46 +216,40 @@ void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) { } } -void WebAssemblyAsmPrinter::EmitTargetFeatures() { - static const std::pair FeaturePairs[] = { - {WebAssembly::FeatureAtomics, "atomics"}, - {WebAssembly::FeatureBulkMemory, "bulk-memory"}, - {WebAssembly::FeatureExceptionHandling, "exception-handling"}, - {WebAssembly::FeatureNontrappingFPToInt, "nontrapping-fptoint"}, - {WebAssembly::FeatureSignExt, "sign-ext"}, - {WebAssembly::FeatureSIMD128, "simd128"}, - }; - +void WebAssemblyAsmPrinter::EmitTargetFeatures(Module &M) { struct FeatureEntry { uint8_t Prefix; StringRef Name; }; - FeatureBitset UsedFeatures = - static_cast(TM).getUsedFeatures(); - - // Calculate the features and linkage policies to emit + // Read target features and linkage policies from module metadata SmallVector EmittedFeatures; - for (auto &F : FeaturePairs) { + for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) { + std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str(); + Metadata *Policy = M.getModuleFlag(MDKey); + if (Policy == nullptr) + continue; + FeatureEntry Entry; - Entry.Name = F.second; - if (F.first == WebAssembly::FeatureAtomics) { - // "atomics" is special: code compiled without atomics may have had its - // atomics lowered to nonatomic operations. Such code would be dangerous - // to mix with proper atomics, so it is always Required or Disallowed. - Entry.Prefix = UsedFeatures[F.first] - ? wasm::WASM_FEATURE_PREFIX_REQUIRED - : wasm::WASM_FEATURE_PREFIX_DISALLOWED; - EmittedFeatures.push_back(Entry); - } else { - // Other features are marked Used or not mentioned - if (UsedFeatures[F.first]) { - Entry.Prefix = wasm::WASM_FEATURE_PREFIX_USED; - EmittedFeatures.push_back(Entry); - } - } + Entry.Prefix = 0; + Entry.Name = KV.Key; + + if (auto *MD = cast(Policy)) + if (auto *I = cast(MD->getValue())) + Entry.Prefix = I->getZExtValue(); + + // Silently ignore invalid metadata + if (Entry.Prefix != wasm::WASM_FEATURE_PREFIX_USED && + Entry.Prefix != wasm::WASM_FEATURE_PREFIX_REQUIRED && + Entry.Prefix != wasm::WASM_FEATURE_PREFIX_DISALLOWED) + continue; + + EmittedFeatures.push_back(Entry); } + if (EmittedFeatures.size() == 0) + return; + // Emit features and linkage policies into the "target_features" section MCSectionWasm *FeaturesSection = OutContext.getWasmSection( ".custom_section.target_features", SectionKind::getMetadata()); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h index 35e7d8d..963bfbd 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -59,7 +59,7 @@ public: void EmitEndOfAsmFile(Module &M) override; void EmitProducerInfo(Module &M); - void EmitTargetFeatures(); + void EmitTargetFeatures(Module &M); void EmitJumpTableInfo() override; void EmitConstantPool() override; void EmitFunctionBodyStart() override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp index bf2f70c..196a745 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.cpp @@ -44,6 +44,11 @@ WebAssemblySubtarget::WebAssemblySubtarget(const Triple &TT, InstrInfo(initializeSubtargetDependencies(FS)), TSInfo(), TLInfo(TM, *this) {} +bool WebAssemblySubtarget::enableAtomicExpand() const { + // If atomics are disabled, atomic ops are lowered instead of expanded + return hasAtomics(); +} + bool WebAssemblySubtarget::enableMachineScheduler() const { // Disable the MachineScheduler for now. Even with ShouldTrackPressure set and // enableMachineSchedDefaultSched overridden, it appears to have an overall diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h index b6f3e6b..ae1f3fe 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -22,11 +22,16 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include +#define GET_SUBTARGETINFO_ENUM #define GET_SUBTARGETINFO_HEADER #include "WebAssemblyGenSubtargetInfo.inc" namespace llvm { +// Defined in WebAssemblyGenSubtargetInfo.inc. +extern const SubtargetFeatureKV + WebAssemblyFeatureKV[WebAssembly::NumSubtargetFeatures]; + class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { enum SIMDEnum { NoSIMD, @@ -77,6 +82,7 @@ public: return &getInstrInfo()->getRegisterInfo(); } const Triple &getTargetTriple() const { return TargetTriple; } + bool enableAtomicExpand() const override; bool enableMachineScheduler() const override; bool useAA() const override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index 6d9fd00..8a768db 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/LowerAtomic.h" #include "llvm/Transforms/Utils.h" using namespace llvm; @@ -117,10 +118,6 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine( initAsmInfo(); - // Create a subtarget using the unmodified target machine features to - // initialize the used feature set with explicitly enabled features. - getSubtargetImpl(getTargetCPU(), getTargetFeatureString()); - // Note that we don't use setRequiresStructuredCFG(true). It disables // optimizations than we're ok with, and want, such as critical edge // splitting and tail merging. @@ -134,7 +131,6 @@ WebAssemblyTargetMachine::getSubtargetImpl(std::string CPU, auto &I = SubtargetMap[CPU + FS]; if (!I) { I = llvm::make_unique(TargetTriple, CPU, FS, *this); - UsedFeatures |= I->getFeatureBits(); } return I.get(); } @@ -160,21 +156,123 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const { } namespace { -class StripThreadLocal final : public ModulePass { - // The default thread model for wasm is single, where thread-local variables - // are identical to regular globals and should be treated the same. So this - // pass just converts all GlobalVariables to NotThreadLocal + +class CoalesceFeaturesAndStripAtomics final : public ModulePass { + // Take the union of all features used in the module and use it for each + // function individually, since having multiple feature sets in one module + // currently does not make sense for WebAssembly. If atomics are not enabled, + // also strip atomic operations and thread local storage. static char ID; + WebAssemblyTargetMachine *WasmTM; public: - StripThreadLocal() : ModulePass(ID) {} + CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM) + : ModulePass(ID), WasmTM(WasmTM) {} + bool runOnModule(Module &M) override { - for (auto &GV : M.globals()) - GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal); + FeatureBitset Features = coalesceFeatures(M); + + std::string FeatureStr = getFeatureString(Features); + for (auto &F : M) + replaceFeatures(F, FeatureStr); + + bool Stripped = false; + if (!Features[WebAssembly::FeatureAtomics]) { + Stripped |= stripAtomics(M); + Stripped |= stripThreadLocals(M); + } + + recordFeatures(M, Features, Stripped); + + // Conservatively assume we have made some change return true; } + +private: + FeatureBitset coalesceFeatures(const Module &M) { + FeatureBitset Features = + WasmTM + ->getSubtargetImpl(WasmTM->getTargetCPU(), + WasmTM->getTargetFeatureString()) + ->getFeatureBits(); + for (auto &F : M) + Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits(); + return Features; + } + + std::string getFeatureString(const FeatureBitset &Features) { + std::string Ret; + for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) { + if (Features[KV.Value]) + Ret += (StringRef("+") + KV.Key + ",").str(); + } + return Ret; + } + + void replaceFeatures(Function &F, const std::string &Features) { + F.removeFnAttr("target-features"); + F.removeFnAttr("target-cpu"); + F.addFnAttr("target-features", Features); + } + + bool stripAtomics(Module &M) { + // Detect whether any atomics will be lowered, since there is no way to tell + // whether the LowerAtomic pass lowers e.g. stores. + bool Stripped = false; + for (auto &F : M) { + for (auto &B : F) { + for (auto &I : B) { + if (I.isAtomic()) { + Stripped = true; + goto done; + } + } + } + } + + done: + if (!Stripped) + return false; + + LowerAtomicPass Lowerer; + FunctionAnalysisManager FAM; + for (auto &F : M) + Lowerer.run(F, FAM); + + return true; + } + + bool stripThreadLocals(Module &M) { + bool Stripped = false; + for (auto &GV : M.globals()) { + if (GV.getThreadLocalMode() != + GlobalValue::ThreadLocalMode::NotThreadLocal) { + Stripped = true; + GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal); + } + } + return Stripped; + } + + void recordFeatures(Module &M, const FeatureBitset &Features, bool Stripped) { + for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) { + std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str(); + if (KV.Value == WebAssembly::FeatureAtomics && Stripped) { + // "atomics" is special: code compiled without atomics may have had its + // atomics lowered to nonatomic operations. In that case, atomics is + // disallowed to prevent unsafe linking with atomics-enabled objects. + assert(!Features[WebAssembly::FeatureAtomics]); + M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey, + wasm::WASM_FEATURE_PREFIX_DISALLOWED); + } else if (Features[KV.Value]) { + // Otherwise features are marked Used or not mentioned + M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey, + wasm::WASM_FEATURE_PREFIX_USED); + } + } + } }; -char StripThreadLocal::ID = 0; +char CoalesceFeaturesAndStripAtomics::ID = 0; /// WebAssembly Code Generator Pass Configuration Options. class WebAssemblyPassConfig final : public TargetPassConfig { @@ -222,16 +320,11 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) { //===----------------------------------------------------------------------===// void WebAssemblyPassConfig::addIRPasses() { - if (static_cast(TM) - ->getUsedFeatures()[WebAssembly::FeatureAtomics]) { - // Expand some atomic operations. WebAssemblyTargetLowering has hooks which - // control specifically what gets lowered. - addPass(createAtomicExpandPass()); - } else { - // If atomics are not enabled, they get lowered to non-atomics. - addPass(createLowerAtomicPass()); - addPass(new StripThreadLocal()); - } + // Runs LowerAtomicPass if necessary + addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine())); + + // This is a no-op if atomics are not used in the module + addPass(createAtomicExpandPass()); // Add signatures to prototype-less function declarations addPass(createWebAssemblyAddMissingPrototypes()); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h index 0f19010..850e6b9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h @@ -23,7 +23,6 @@ namespace llvm { class WebAssemblyTargetMachine final : public LLVMTargetMachine { std::unique_ptr TLOF; mutable StringMap> SubtargetMap; - mutable FeatureBitset UsedFeatures; public: WebAssemblyTargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -46,8 +45,6 @@ public: return TLOF.get(); } - FeatureBitset getUsedFeatures() const { return UsedFeatures; } - TargetTransformInfo getTargetTransformInfo(const Function &F) override; bool usesPhysRegsForPEI() const override { return false; } diff --git a/llvm/test/CodeGen/WebAssembly/target-features-tls.ll b/llvm/test/CodeGen/WebAssembly/target-features-tls.ll new file mode 100644 index 0000000..a5c08f8 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/target-features-tls.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -mattr=-atomics | FileCheck %s --check-prefixes CHECK,NO-ATOMICS +; RUN: llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS + +; Test that the target features section contains -atomics or +atomics +; for modules that have thread local storage in their source. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +@foo = internal thread_local global i32 0 + +; CHECK-LABEL: .custom_section.target_features,"",@ + +; -atomics +; NO-ATOMICS-NEXT: .int8 1 +; NO-ATOMICS-NEXT: .int8 45 +; NO-ATOMICS-NEXT: .int8 7 +; NO-ATOMICS-NEXT: .ascii "atomics" +; NO-ATOMICS-NEXT: .bss.foo,"",@ + +; +atomics +; ATOMICS-NEXT: .int8 1 +; ATOMICS-NEXT: .int8 43 +; ATOMICS-NEXT: .int8 7 +; ATOMICS-NEXT: .ascii "atomics" +; ATOMICS-NEXT: .tbss.foo,"",@ diff --git a/llvm/test/CodeGen/WebAssembly/target-features.ll b/llvm/test/CodeGen/WebAssembly/target-features.ll index f262657..7ce7fcf 100644 --- a/llvm/test/CodeGen/WebAssembly/target-features.ll +++ b/llvm/test/CodeGen/WebAssembly/target-features.ll @@ -1,38 +1,69 @@ ; RUN: llc < %s | FileCheck %s --check-prefixes CHECK,ATTRS ; RUN: llc < %s -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128 -; RUN; llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS ; RUN: llc < %s -mcpu=bleeding-edge | FileCheck %s --check-prefixes CHECK,BLEEDING-EDGE ; Test that codegen emits target features from the command line or -; function attributes correctly. +; function attributes correctly and that features are enabled for the +; entire module if they are enabled for any function in the module. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -define void @foo() #0 { +define void @foo(i32* %p1) #0 { + %a = atomicrmw min i32* undef, i32 42 seq_cst + %v = fptoui float undef to i32 + store i32 %v, i32* %p1 ret void } -define void @bar() #1 { +define void @bar(i32* %p1) #1 { + %a = atomicrmw min i32* undef, i32 42 seq_cst + %v = fptoui float undef to i32 + store i32 %v, i32* %p1 ret void } -attributes #0 = { "target-features"="+sign-ext" } +attributes #0 = { "target-features"="+atomics" } attributes #1 = { "target-features"="+nontrapping-fptoint" } + +; CHECK-LABEL: foo: + +; Expanded atomicrmw min +; ATTRS: loop +; ATTRS: i32.atomic.rmw.cmpxchg +; SIMD128-NOT: i32.atomic.rmw.cmpxchg +; ATTRS: end_loop + +; nontrapping fptoint +; ATTRS: i32.trunc_sat_f32_u +; SIMD128-NOT: i32.trunc_sat_f32_u +; ATTRS: i32.store + +; `bar` should be the same as `foo` +; CHECK-LABEL: bar: + +; Expanded atomicrmw min +; ATTRS: loop +; ATTRS: i32.atomic.rmw.cmpxchg +; SIMD128-NOT: i32.atomic.rmw.cmpxchg +; ATTRS: end_loop + +; nontrapping fptoint +; ATTRS: i32.trunc_sat_f32_u +; SIMD128-NOT: i32.trunc_sat_f32_u +; ATTRS: i32.store + ; CHECK-LABEL: .custom_section.target_features,"",@ -; -atomics, +sign_ext -; ATTRS-NEXT: .int8 3 -; ATTRS-NEXT: .int8 45 +; +atomics, +nontrapping-fptoint +; ATTRS-NEXT: .int8 2 +; ATTRS-NEXT: .int8 43 ; ATTRS-NEXT: .int8 7 ; ATTRS-NEXT: .ascii "atomics" ; ATTRS-NEXT: .int8 43 ; ATTRS-NEXT: .int8 19 ; ATTRS-NEXT: .ascii "nontrapping-fptoint" -; ATTRS-NEXT: .int8 43 -; ATTRS-NEXT: int8 8 -; ATTRS-NEXT: .ascii "sign-ext" ; -atomics, +simd128 ; SIMD128-NEXT: .int8 2 @@ -43,15 +74,9 @@ attributes #1 = { "target-features"="+nontrapping-fptoint" } ; SIMD128-NEXT: .int8 7 ; SIMD128-NEXT: .ascii "simd128" -; =atomics -; ATOMICS-NEXT: .int8 1 -; ATOMICS-NEXT: .int8 61 -; ATOMICS-NEXT: .int8 7 -; ATOMICS-NEXT: .ascii "atomics" - -; =atomics, +nontrapping-fptoint, +sign-ext, +simd128 +; +atomics, +nontrapping-fptoint, +sign-ext, +simd128 ; BLEEDING-EDGE-NEXT: .int8 4 -; BLEEDING-EDGE-NEXT: .int8 61 +; BLEEDING-EDGE-NEXT: .int8 43 ; BLEEDING-EDGE-NEXT: .int8 7 ; BLEEDING-EDGE-NEXT: .ascii "atomics" ; BLEEDING-EDGE-NEXT: .int8 43 diff --git a/llvm/test/MC/WebAssembly/array-fill.ll b/llvm/test/MC/WebAssembly/array-fill.ll index 9e2eba4..61cdb91 100644 --- a/llvm/test/MC/WebAssembly/array-fill.ll +++ b/llvm/test/MC/WebAssembly/array-fill.ll @@ -24,9 +24,4 @@ target triple = "wasm32-unknown-unknown" ; CHECK-NEXT: Name: .data ; CHECK-NEXT: Alignment: 0 ; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll index d838320..3683d63 100644 --- a/llvm/test/MC/WebAssembly/assembler-binary.ll +++ b/llvm/test/MC/WebAssembly/assembler-binary.ll @@ -87,9 +87,4 @@ entry: ; CHECK-NEXT: Name: bar ; CHECK-NEXT: Flags: [ UNDEFINED ] ; CHECK-NEXT: Function: 0 -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/bss.ll b/llvm/test/MC/WebAssembly/bss.ll index de8b9f8..b3d95a1 100644 --- a/llvm/test/MC/WebAssembly/bss.ll +++ b/llvm/test/MC/WebAssembly/bss.ll @@ -78,9 +78,4 @@ target triple = "wasm32-unknown-unknown" ; CHECK-NEXT: Name: .bss.bar ; CHECK-NEXT: Alignment: 0 ; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/comdat.ll b/llvm/test/MC/WebAssembly/comdat.ll index 0327a8b..1890589 100644 --- a/llvm/test/MC/WebAssembly/comdat.ll +++ b/llvm/test/MC/WebAssembly/comdat.ll @@ -119,9 +119,4 @@ define linkonce_odr i32 @sharedFn() #1 comdat($sharedComdat) { ; CHECK-NEXT: Index: 3 ; CHECK-NEXT: - Kind: DATA ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/debug-info.ll b/llvm/test/MC/WebAssembly/debug-info.ll index f76bba9..fe4a4cf 100644 --- a/llvm/test/MC/WebAssembly/debug-info.ll +++ b/llvm/test/MC/WebAssembly/debug-info.ll @@ -130,12 +130,6 @@ ; CHECK-NEXT: Offset: 1021 ; CHECK-NEXT: Name: producers ; CHECK-NEXT: } -; CHECK-NEXT: Section { -; CHECK-NEXT: Type: CUSTOM (0x0) -; CHECK-NEXT: Size: 10 -; CHECK-NEXT: Offset: 1114 -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: } ; CHECK-NEXT:] ; CHECK-NEXT:Relocations [ ; CHECK-NEXT: Section (6) DATA { diff --git a/llvm/test/MC/WebAssembly/explicit-sections.ll b/llvm/test/MC/WebAssembly/explicit-sections.ll index f43189a..b94190f 100644 --- a/llvm/test/MC/WebAssembly/explicit-sections.ll +++ b/llvm/test/MC/WebAssembly/explicit-sections.ll @@ -70,9 +70,4 @@ target triple = "wasm32-unknown-unknown" ; CHECK-NEXT: Name: .sec2 ; CHECK-NEXT: Alignment: 3 ; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll index 9b384e3..df7ff92 100644 --- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll +++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll @@ -181,9 +181,4 @@ declare void @func3() ; CHECK-NEXT: Symbol: 10 ; CHECK-NEXT: - Priority: 65535 ; CHECK-NEXT: Symbol: 7 -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/visibility.ll b/llvm/test/MC/WebAssembly/visibility.ll index 63b46eb..5bb757b 100644 --- a/llvm/test/MC/WebAssembly/visibility.ll +++ b/llvm/test/MC/WebAssembly/visibility.ll @@ -25,9 +25,4 @@ entry: ; CHECK-NEXT: Name: hiddenVis ; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; CHECK-NEXT: Function: 1 -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/weak-alias.ll b/llvm/test/MC/WebAssembly/weak-alias.ll index cf5783a0..7abdc79 100644 --- a/llvm/test/MC/WebAssembly/weak-alias.ll +++ b/llvm/test/MC/WebAssembly/weak-alias.ll @@ -207,11 +207,6 @@ entry: ; CHECK-NEXT: Name: .data.alias_address ; CHECK-NEXT: Alignment: 3 ; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... ; CHECK-SYMS: SYMBOL TABLE: diff --git a/llvm/test/MC/WebAssembly/weak.ll b/llvm/test/MC/WebAssembly/weak.ll index 2278f97..6a94ee6 100644 --- a/llvm/test/MC/WebAssembly/weak.ll +++ b/llvm/test/MC/WebAssembly/weak.ll @@ -30,9 +30,4 @@ entry: ; CHECK-NEXT: Kind: DATA ; CHECK-NEXT: Name: weak_external_data ; CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ] -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: target_features -; CHECK-NEXT: Features: -; CHECK-NEXT: - Prefix: DISALLOWED -; CHECK-NEXT: Name: atomics ; CHECK-NEXT: ... diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index 9d13467..9ce2b3b 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -149,7 +149,7 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, unsigned N = DefList.size(); if (N == 0) return; - if (N > MAX_SUBTARGET_FEATURES) + if (N + 1 > MAX_SUBTARGET_FEATURES) PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); OS << "namespace " << Target << " {\n"; @@ -169,6 +169,9 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, FeatureMap[Def] = i; } + OS << " " + << "NumSubtargetFeatures = " << N << "\n"; + // Close enumeration and namespace OS << "};\n"; OS << "} // end namespace " << Target << "\n";