[clang] Add clang atomic control options and attribute (PR #114841)

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Sun Feb 23 17:05:35 PST 2025


================
@@ -1101,6 +1107,187 @@ inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
   *this = FPO.applyOverrides(*this);
 }
 
+// The three atomic code-generation options.
+// The canonical (positive) names are:
+//   "remote_memory", "fine_grained_memory", and "ignore_denormal_mode".
+// In attribute or command-line parsing, a token prefixed with "no_" inverts its
+// value.
+enum class AtomicOptionKind {
+  RemoteMemory,       // true means remote memory is enabled.
+  FineGrainedMemory,  // true means fine-grained memory is enabled.
+  IgnoreDenormalMode, // true means ignore floating-point denormals.
+  LANGOPT_ATOMIC_OPTION_LAST
+};
+
+struct AtomicOptions {
+  // Bitfields for each option.
+  unsigned remote_memory : 1;
+  unsigned fine_grained_memory : 1;
+  unsigned ignore_denormal_mode : 1;
+
+  AtomicOptions()
+      : remote_memory(0), fine_grained_memory(0), ignore_denormal_mode(0) {}
+
+  bool getOption(AtomicOptionKind Kind) const {
+    switch (Kind) {
+    case AtomicOptionKind::RemoteMemory:
+      return remote_memory;
+    case AtomicOptionKind::FineGrainedMemory:
+      return fine_grained_memory;
+    case AtomicOptionKind::IgnoreDenormalMode:
+      return ignore_denormal_mode;
+    default:
+      llvm_unreachable("Invalid AtomicOptionKind");
+    }
+  }
+
+  void setOption(AtomicOptionKind Kind, bool Value) {
+    switch (Kind) {
+    case AtomicOptionKind::RemoteMemory:
+      remote_memory = Value;
+      break;
+    case AtomicOptionKind::FineGrainedMemory:
+      fine_grained_memory = Value;
+      break;
+    case AtomicOptionKind::IgnoreDenormalMode:
+      ignore_denormal_mode = Value;
+      break;
+    default:
+      llvm_unreachable("Invalid AtomicOptionKind");
+    }
+  }
+
+  LLVM_DUMP_METHOD void dump() const {
+    llvm::errs() << "\n remote_memory: " << remote_memory
+                 << "\n fine_grained_memory: " << fine_grained_memory
+                 << "\n ignore_denormal_mode: " << ignore_denormal_mode << "\n";
+  }
+
+  // The canonical names for each option.
+  static constexpr const char *OptionNames[] = {
+      "remote_memory",       // canonical name for RemoteMemory option.
+      "fine_grained_memory", // canonical name for FineGrainedMemory option.
+      "ignore_denormal_mode" // canonical name for IgnoreDenormalMode option.
+  };
+};
+
+/// Represents overrides for atomic options.
+class AtomicOptionsOverride {
+  AtomicOptions Options;
+  // Bitmask for active overrides.
+  unsigned OverrideMask;
+
+  static constexpr unsigned getMask(AtomicOptionKind Kind) {
+    return 1u << static_cast<unsigned>(Kind);
+  }
+
+public:
+  template <typename Func> static void forEachOption(Func &&func) {
+    for (unsigned I = 0; I < static_cast<unsigned>(
+                                 AtomicOptionKind::LANGOPT_ATOMIC_OPTION_LAST);
+         ++I)
+      func(static_cast<AtomicOptionKind>(I));
+  }
+
+  static constexpr unsigned DefaultMask =
+      (1u << static_cast<unsigned>(
+           AtomicOptionKind::LANGOPT_ATOMIC_OPTION_LAST)) -
+      1;
+
+  AtomicOptionsOverride() : Options(), OverrideMask(0) {}
+  AtomicOptionsOverride(AtomicOptions AO)
+      : Options(AO), OverrideMask(DefaultMask) {}
+  AtomicOptionsOverride(AtomicOptions AO, unsigned Mask)
+      : Options(AO), OverrideMask(Mask) {}
+  AtomicOptionsOverride(const LangOptions &LO) : Options(), OverrideMask(0) {
+    setAtomicOverride(AtomicOptionKind::RemoteMemory, LO.AtomicRemoteMemory);
+    setAtomicOverride(AtomicOptionKind::FineGrainedMemory,
+                      LO.AtomicFineGrainedMemory);
+    setAtomicOverride(AtomicOptionKind::IgnoreDenormalMode,
+                      LO.AtomicIgnoreDenormalMode);
+  }
+  // Parses a token (e.g. "fine_grained_memory" or "no_fine_grained_memory").
+  // If the token begins with "no_", the prefix is stripped and the resulting
+  // string is compared against the canonical name. If it matches, Value is set
+  // to false. Otherwise, if the token exactly matches the canonical name, Value
+  // is true.
+  static std::optional<AtomicOptionKind>
+  parseAtomicOverrideKey(llvm::StringRef Key, bool &Value) {
----------------
yxsamliu wrote:

You mean VariadicEnumArgument? Yes using that can avoid the parsing function. will do

https://github.com/llvm/llvm-project/pull/114841


More information about the cfe-commits mailing list