[llvm] [Target] Add target-independent TargetVerifier dispatcher (PR #205703)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 27 02:04:38 PDT 2026
================
@@ -0,0 +1,135 @@
+//===-- llvm/Target/TargetVerifier.h - Target IR Verifier -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a target-dependent verification framework that can be
+// instantiated and run from target-independent locations.
+//
+// In contrast to the generic Verifier or Lint, a TargetVerify looks for
+// constructs that are invalid for a *particular* target machine. Each backend
+// provides its own TargetVerify and registers a factory for it (keyed by
+// Triple::ArchType) via registerTargetVerify(), typically from its
+// LLVMInitialize<Target>Target().
+//
+// TargetVerifierPass is the target-independent dispatcher: it reads the
+// module's target triple and runs whichever TargetVerify (if any) was
+// registered for that architecture. Because dispatch happens at run time by
+// triple, the pass can be scheduled from generic, target-independent pipelines
+// (e.g. `opt -passes=target-verifier`); it is simply a no-op for targets that
+// have not registered a verifier.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_TARGETVERIFIER_H
+#define LLVM_TARGET_TARGETVERIFIER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace llvm {
+
+class Function;
+
+/// Base class for a single target's IR verification logic.
+///
+/// A backend subclasses this and implements run() to check a function for
+/// constructs that are invalid for that target. Failed checks are recorded in
+/// \p Messages (and clear \p IsValid) via checkFailed().
+class TargetVerify {
+protected:
+ void writeValues(ArrayRef<const Value *> Vs) {
+ for (const Value *V : Vs) {
+ if (!V)
+ continue;
+ if (isa<Instruction>(V))
+ MessagesStr << *V << '\n';
+ else {
+ V->printAsOperand(MessagesStr, true, Mod);
+ MessagesStr << '\n';
+ }
+ }
+ }
+
+ /// A check failed, so print the condition's message.
+ ///
+ /// This is a convenient place to put a breakpoint to see why something is
+ /// considered invalid for the target.
+ void checkFailed(const Twine &Message) {
+ IsValid = false;
+ MessagesStr << Message << '\n';
+ }
+
+ /// A check failed (with values to print).
+ template <typename T1, typename... Ts>
+ void checkFailed(const Twine &Message, const T1 &V1, const Ts &...Vs) {
+ checkFailed(Message);
+ writeValues({V1, Vs...});
+ }
+
+public:
+ Module *Mod;
+ Triple TT;
+
+ std::string Messages;
+ raw_string_ostream MessagesStr;
+
+ /// Whether every function verified so far is valid for the target.
+ bool IsValid = true;
+
+ TargetVerify(Module *Mod)
+ : Mod(Mod), TT(Mod->getTargetTriple()), MessagesStr(Messages) {}
+ virtual ~TargetVerify() = default;
+
+ /// Run this target's checks on \p F. Returns true if \p F is valid.
+ virtual bool run(Function &F) = 0;
+};
+
+/// Factory that creates a target's TargetVerify for a given module.
+using TargetVerifyFactory = std::function<TargetVerify *(Module &)>;
----------------
aengelke wrote:
Can we avoid the use of std::function if at all possible?
https://github.com/llvm/llvm-project/pull/205703
More information about the llvm-commits
mailing list