[llvm] [Instrumentor] Add spellcheck for instrumentor properties (PR #205416)
Ethan Luis McDonough via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 24 21:27:21 PDT 2026
https://github.com/EthanLuisMcDonough updated https://github.com/llvm/llvm-project/pull/205416
>From a41df7afe72a6c917386446e4bfd2c7532c018d4 Mon Sep 17 00:00:00 2001
From: Ethan Luis McDonough <ethanluismcdonough at gmail.com>
Date: Tue, 23 Jun 2026 14:31:40 -0500
Subject: [PATCH 1/2] Add spellcheck for instrumentor properties
---
.../Transforms/IPO/InstrumentorConfigFile.cpp | 57 ++++++++++++++++---
.../Instrumentor/bad_spelling.ll | 7 +++
.../Instrumentor/bad_spelling_config.json | 30 ++++++++++
3 files changed, 86 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
create mode 100644 llvm/test/Instrumentation/Instrumentor/bad_spelling_config.json
diff --git a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
index 1038badc189a6..f93febaa56e5e 100644
--- a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
+++ b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
@@ -112,6 +112,20 @@ void writeConfigToJSON(InstrumentationConfig &IConf, StringRef OutputFile,
J.objectEnd();
}
+template <typename Map>
+static StringRef closestOption(const Map &Options, StringRef Missing) {
+ uint32_t MaxEdit = 5;
+ StringRef Closest;
+ for (auto Key : Options.keys()) {
+ auto EditDist = Missing.edit_distance_insensitive(Key, true, MaxEdit);
+ if (EditDist < MaxEdit) {
+ Closest = Key;
+ MaxEdit = EditDist;
+ }
+ }
+ return Closest;
+}
+
bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
LLVMContext &Ctx, vfs::FileSystem &FS) {
if (InputFile.empty())
@@ -182,10 +196,15 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
break;
}
} else if (!StringRef(ObjIt.first).ends_with(".description")) {
- Ctx.diagnose(DiagnosticInfoInstrumentation(
- Twine("configuration key '") + StringRef(ObjIt.first) +
- Twine("' not found and ignored"),
- DS_Warning));
+ Twine NoMatchingMsg = Twine("configuration key '") +
+ StringRef(ObjIt.first) +
+ Twine("' not found and ignored");
+ StringRef Closest = closestOption(BCOMap, ObjIt.first);
+ Twine Diag =
+ NoMatchingMsg + (Closest.empty() ? Twine()
+ : Twine("; did you mean '") +
+ Closest + Twine("'?"));
+ Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
}
}
continue;
@@ -202,16 +221,27 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
}
auto *IO = IChoiceMap.lookup(ObjIt.first);
if (!IO) {
- Ctx.diagnose(DiagnosticInfoInstrumentation(
+ Twine NoMatchingMsg =
Twine("malformed JSON configuration, expected an object matching "
- "an instrumentor choice, got ") +
- StringRef(ObjIt.first),
- DS_Warning));
+ "an instrumentor choice, got '") +
+ StringRef(ObjIt.first) + Twine("'");
+ StringRef Closest = closestOption(IChoiceMap, ObjIt.first);
+ Twine Diag = NoMatchingMsg +
+ (Closest.empty()
+ ? Twine()
+ : Twine("; did you mean '") + Closest + Twine("'?"));
+ Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
continue;
}
SeenIOs.insert(IO);
StringMap<bool> ValueMap, ReplaceMap;
StringRef FilterStr;
+ StringSet<> IOOpts;
+ IOOpts.insert("enabled");
+ IOOpts.insert("filter");
+ for (auto &IRArg : IO->IRTArgs) {
+ IOOpts.insert(IRArg.Name);
+ }
for (auto &InnerObjIt : *InnerObj) {
auto Name = StringRef(InnerObjIt.first);
if (Name == "filter") {
@@ -222,6 +252,17 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
} else {
ValueMap[Name] = InnerObjIt.second.getAsBoolean().value_or(false);
}
+ if (!IOOpts.contains(Name)) {
+ Twine NoMatchingMsg = Twine("unrecognized JSON property '") +
+ StringRef(Name) + ("' in configuration for '") +
+ IO->getName() + Twine("'");
+ StringRef Closest = closestOption(IOOpts, Name);
+ Twine Diag =
+ NoMatchingMsg + (Closest.empty() ? Twine()
+ : Twine("; did you mean '") +
+ Closest + Twine("'?"));
+ Ctx.diagnose(DiagnosticInfoInstrumentation(Diag, DS_Warning));
+ }
}
IO->Enabled = ValueMap["enabled"];
IO->Filter = FilterStr;
diff --git a/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll b/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
new file mode 100644
index 0000000000000..92f2701a18522
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
@@ -0,0 +1,7 @@
+; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-files=%S/bad_spelling_config.json -S 2>&1 | FileCheck %s
+
+; CHECK: warning: configuration key 'gpu_enabeld' not found and ignored; did you mean 'gpu_enabled'?
+; CHECK: warning: malformed JSON configuration, expected an object matching an instrumentor choice, got 'numerci'; did you mean 'numeric'?
+; CHECK: warning: unrecognized JSON property 'zzzzzz' in configuration for 'numeric'
+; CHECK: warning: unrecognized JSON property 'opocde' in configuration for 'numeric'; did you mean 'opcode'?
+; CHECK: warning: unrecognized JSON property 'enabld' in configuration for 'numeric'; did you mean 'enabled'?
diff --git a/llvm/test/Instrumentation/Instrumentor/bad_spelling_config.json b/llvm/test/Instrumentation/Instrumentor/bad_spelling_config.json
new file mode 100644
index 0000000000000..f0fa47ca0b4a5
--- /dev/null
+++ b/llvm/test/Instrumentation/Instrumentor/bad_spelling_config.json
@@ -0,0 +1,30 @@
+{
+ "configuration": {
+ "runtime_prefix": "__instrumentor_",
+ "gpu_enabeld": false
+ },
+ "instruction_pre": {
+ "numeric": {
+ "enabld": true,
+ "type_id": true,
+ "size": true,
+ "opocde": true,
+ "left": true,
+ "right": true,
+ "zzzzzz": false,
+ "id": true
+ }
+ },
+ "instruction_post": {
+ "numerci": {
+ "enabled": true,
+ "type_id": true,
+ "size": true,
+ "opcode": true,
+ "left": true,
+ "right": true,
+ "result": true,
+ "id": true
+ }
+ }
+}
>From f71308eb227c4137eddc1b51cda4daaa0c1dfc35 Mon Sep 17 00:00:00 2001
From: Ethan Luis McDonough <ethanluismcdonough at gmail.com>
Date: Wed, 24 Jun 2026 20:25:57 -0500
Subject: [PATCH 2/2] Minor adjustments
---
llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp | 6 +++---
llvm/test/Instrumentation/Instrumentor/bad_spelling.ll | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
index f93febaa56e5e..f045509cc798e 100644
--- a/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
+++ b/llvm/lib/Transforms/IPO/InstrumentorConfigFile.cpp
@@ -15,6 +15,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/ErrorHandling.h"
@@ -116,7 +117,7 @@ template <typename Map>
static StringRef closestOption(const Map &Options, StringRef Missing) {
uint32_t MaxEdit = 5;
StringRef Closest;
- for (auto Key : Options.keys()) {
+ for (const auto &Key : Options.keys()) {
auto EditDist = Missing.edit_distance_insensitive(Key, true, MaxEdit);
if (EditDist < MaxEdit) {
Closest = Key;
@@ -239,9 +240,8 @@ bool readConfigFromJSON(InstrumentationConfig &IConf, StringRef InputFile,
StringSet<> IOOpts;
IOOpts.insert("enabled");
IOOpts.insert("filter");
- for (auto &IRArg : IO->IRTArgs) {
+ for (auto &IRArg : IO->IRTArgs)
IOOpts.insert(IRArg.Name);
- }
for (auto &InnerObjIt : *InnerObj) {
auto Name = StringRef(InnerObjIt.first);
if (Name == "filter") {
diff --git a/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll b/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
index 92f2701a18522..4b1808b78624f 100644
--- a/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
+++ b/llvm/test/Instrumentation/Instrumentor/bad_spelling.ll
@@ -1,7 +1,7 @@
; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-files=%S/bad_spelling_config.json -S 2>&1 | FileCheck %s
-; CHECK: warning: configuration key 'gpu_enabeld' not found and ignored; did you mean 'gpu_enabled'?
; CHECK: warning: malformed JSON configuration, expected an object matching an instrumentor choice, got 'numerci'; did you mean 'numeric'?
-; CHECK: warning: unrecognized JSON property 'zzzzzz' in configuration for 'numeric'
-; CHECK: warning: unrecognized JSON property 'opocde' in configuration for 'numeric'; did you mean 'opcode'?
-; CHECK: warning: unrecognized JSON property 'enabld' in configuration for 'numeric'; did you mean 'enabled'?
+; CHECK-NEXT: warning: configuration key 'gpu_enabeld' not found and ignored; did you mean 'gpu_enabled'?
+; CHECK-NEXT: warning: unrecognized JSON property 'opocde' in configuration for 'numeric'; did you mean 'opcode'?
+; CHECK-NEXT: warning: unrecognized JSON property 'zzzzzz' in configuration for 'numeric'
+; CHECK-NEXT: warning: unrecognized JSON property 'enabld' in configuration for 'numeric'; did you mean 'enabled'?
\ No newline at end of file
More information about the llvm-commits
mailing list