[llvm] [AsmParser] Track value references and function arguments (PR #174566)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 28 03:04:24 PST 2026


Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,
Albert =?utf-8?q?Havliček?= <ahavlicek at azul.com>,Bertik23
 <39457484+Bertik23 at users.noreply.github.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/174566 at github.com>


https://github.com/Bertik23 updated https://github.com/llvm/llvm-project/pull/174566

>From 536a246e8ac39dcfce94f4c7b34960c0313d8e4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 09:50:58 +0000
Subject: [PATCH 01/12] Store value references in AsmParserContext

---
 .../include/llvm/AsmParser/AsmParserContext.h | 16 ++++++++++++++++
 llvm/lib/AsmParser/AsmParserContext.cpp       | 19 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/llvm/include/llvm/AsmParser/AsmParserContext.h b/llvm/include/llvm/AsmParser/AsmParserContext.h
index 8f7823a9ae07c..912c765c521ba 100644
--- a/llvm/include/llvm/AsmParser/AsmParserContext.h
+++ b/llvm/include/llvm/AsmParser/AsmParserContext.h
@@ -54,6 +54,13 @@ class AsmParserContext {
   IMap::Allocator IAllocator;
   IMap InstructionsInverse = IMap(IAllocator);
 
+  using VMap =
+      IntervalMap<FileLoc, Value *,
+                  IntervalMapImpl::NodeSizer<FileLoc, Value *>::LeafSize,
+                  IntervalMapHalfOpenInfo<FileLoc>>;
+  VMap::Allocator VAllocator;
+  VMap ReferencedValues = VMap(VAllocator);
+
 public:
   LLVM_ABI std::optional<FileLocRange>
   getFunctionLocation(const Function *) const;
@@ -85,9 +92,18 @@ class AsmParserContext {
   /// If no instruction occupies the queried location, or the record is missing,
   /// a nullptr is returned.
   Instruction *getInstructionAtLocation(const FileLoc &) const;
+  /// Get value referenced at the requested location.
+  /// If no value occupies the queried location, or the record is missing,
+  /// a nullptr is returned.
+  Value *getValueReferencedAtLocation(const FileLoc &) const;
+  /// Get value referenced at the requested location range.
+  /// If no value occupies the queried location, or the record is missing,
+  /// a nullptr is returned.
+  Value *getValueReferencedAtLocation(const FileLocRange &) const;
   bool addFunctionLocation(Function *, const FileLocRange &);
   bool addBlockLocation(BasicBlock *, const FileLocRange &);
   bool addInstructionLocation(Instruction *, const FileLocRange &);
+  bool addValueReferenceAtLocation(Value *, const FileLocRange &);
 };
 } // namespace llvm
 
diff --git a/llvm/lib/AsmParser/AsmParserContext.cpp b/llvm/lib/AsmParser/AsmParserContext.cpp
index 453e6994d2b9e..9b6294556f185 100644
--- a/llvm/lib/AsmParser/AsmParserContext.cpp
+++ b/llvm/lib/AsmParser/AsmParserContext.cpp
@@ -68,6 +68,19 @@ AsmParserContext::getInstructionAtLocation(const FileLoc &Query) const {
   return InstructionsInverse.lookup(Query, nullptr);
 }
 
+Value *AsmParserContext::getValueReferencedAtLocation(
+    const FileLocRange &Query) const {
+  auto It = ReferencedValues.find(Query.Start);
+  if (It.stop() <= Query.End)
+    return *It;
+  return nullptr;
+}
+
+Value *
+AsmParserContext::getValueReferencedAtLocation(const FileLoc &Query) const {
+  return ReferencedValues.lookup(Query, nullptr);
+}
+
 bool AsmParserContext::addFunctionLocation(Function *F,
                                            const FileLocRange &Loc) {
   bool Inserted = Functions.insert({F, Loc}).second;
@@ -92,4 +105,10 @@ bool AsmParserContext::addInstructionLocation(Instruction *I,
   return Inserted;
 }
 
+bool AsmParserContext::addValueReferenceAtLocation(Value *V,
+                                                   const FileLocRange &Loc) {
+  ReferencedValues.insert(Loc.Start, Loc.End, V);
+  return true;
+}
+
 } // namespace llvm

>From a03f7a81983ecbc5883bdbea953e5fc384e075c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:02:50 +0000
Subject: [PATCH 02/12] Store function arguments in AsmParserContext

---
 llvm/include/llvm/AsmParser/AsmParserContext.h | 18 ++++++++++++++++++
 llvm/lib/AsmParser/AsmParserContext.cpp        | 13 +++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/llvm/include/llvm/AsmParser/AsmParserContext.h b/llvm/include/llvm/AsmParser/AsmParserContext.h
index 912c765c521ba..023d50017cf27 100644
--- a/llvm/include/llvm/AsmParser/AsmParserContext.h
+++ b/llvm/include/llvm/AsmParser/AsmParserContext.h
@@ -39,6 +39,15 @@ class AsmParserContext {
   DenseMap<Function *, FileLocRange> Functions;
   FMap::Allocator FAllocator;
   FMap FunctionsInverse = FMap(FAllocator);
+
+  DenseMap<Argument *, FileLocRange> FunctionArguments;
+  using FAMap =
+      IntervalMap<FileLoc, Argument *,
+                  IntervalMapImpl::NodeSizer<FileLoc, Argument *>::LeafSize,
+                  IntervalMapHalfOpenInfo<FileLoc>>;
+  FAMap::Allocator FAAllocator;
+  FAMap FunctionArgumentsInverse = FAMap(FAAllocator);
+
   DenseMap<BasicBlock *, FileLocRange> Blocks;
   using BBMap =
       IntervalMap<FileLoc, BasicBlock *,
@@ -79,6 +88,14 @@ class AsmParserContext {
   /// Get the block at the requested location range.
   /// If no single block occupies the queried range, or the record is missing, a
   /// nullptr is returned.
+  Argument *getFunctionArgumentAtLocation(const FileLocRange &) const;
+  /// Get the function at the requested location.
+  /// If no function occupies the queried location, or the record is missing, a
+  /// nullptr is returned.
+  Argument *getFunctionArgumentAtLocation(const FileLoc &) const;
+  /// Get the block at the requested location range.
+  /// If no single block occupies the queried range, or the record is missing, a
+  /// nullptr is returned.
   BasicBlock *getBlockAtLocation(const FileLocRange &) const;
   /// Get the block at the requested location.
   /// If no block occupies the queried location, or the record is missing, a
@@ -101,6 +118,7 @@ class AsmParserContext {
   /// a nullptr is returned.
   Value *getValueReferencedAtLocation(const FileLocRange &) const;
   bool addFunctionLocation(Function *, const FileLocRange &);
+  bool addFunctionArgumentLocation(Argument *, const FileLocRange &);
   bool addBlockLocation(BasicBlock *, const FileLocRange &);
   bool addInstructionLocation(Instruction *, const FileLocRange &);
   bool addValueReferenceAtLocation(Value *, const FileLocRange &);
diff --git a/llvm/lib/AsmParser/AsmParserContext.cpp b/llvm/lib/AsmParser/AsmParserContext.cpp
index 9b6294556f185..ce847b164ccbb 100644
--- a/llvm/lib/AsmParser/AsmParserContext.cpp
+++ b/llvm/lib/AsmParser/AsmParserContext.cpp
@@ -43,6 +43,19 @@ Function *AsmParserContext::getFunctionAtLocation(const FileLoc &Query) const {
   return FunctionsInverse.lookup(Query, nullptr);
 }
 
+Argument *AsmParserContext::getFunctionArgumentAtLocation(
+    const FileLocRange &Query) const {
+  auto It = FunctionArgumentsInverse.find(Query.Start);
+  if (It.stop() <= Query.End)
+    return *It;
+  return nullptr;
+}
+
+Argument *
+AsmParserContext::getFunctionArgumentAtLocation(const FileLoc &Query) const {
+  return FunctionArgumentsInverse.lookup(Query, nullptr);
+}
+
 BasicBlock *
 AsmParserContext::getBlockAtLocation(const FileLocRange &Query) const {
   auto It = BlocksInverse.find(Query.Start);

>From ad617793d86ca44413b52d216dfbdaca168cba52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:15:40 +0000
Subject: [PATCH 03/12] Pass function argument locations to ParserContext

---
 llvm/include/llvm/AsmParser/LLParser.h |  6 ++++--
 llvm/lib/AsmParser/LLParser.cpp        | 10 +++++++++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 9eb31d7e0a451..c36c338255ce8 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -612,10 +612,12 @@ namespace llvm {
     struct ArgInfo {
       LocTy Loc;
       Type *Ty;
+      FileLocRange IdentLoc;
       AttributeSet Attrs;
       std::string Name;
-      ArgInfo(LocTy L, Type *ty, AttributeSet Attr, const std::string &N)
-          : Loc(L), Ty(ty), Attrs(Attr), Name(N) {}
+      ArgInfo(LocTy L, Type *ty, FileLocRange IdentLoc, AttributeSet Attr,
+              const std::string &N)
+          : Loc(L), Ty(ty), IdentLoc(IdentLoc), Attrs(Attr), Name(N) {}
     };
     bool parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
                            SmallVectorImpl<unsigned> &UnnamedArgNums,
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 03b808c4fdeef..df76598e1363a 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3401,16 +3401,22 @@ bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
         return error(TypeLoc, "argument can not have void type");
 
       std::string Name;
+      FileLoc NameStart;
+      FileLoc NameEnd;
       if (Lex.getKind() == lltok::LocalVar) {
         Name = Lex.getStrVal();
+        NameStart = Lex.getTokLineColumnPos();
         Lex.Lex();
+        NameEnd = Lex.getPrevTokEndLineColumnPos();
       } else {
         unsigned ArgID;
         if (Lex.getKind() == lltok::LocalVarID) {
           ArgID = Lex.getUIntVal();
+          NameStart = Lex.getTokLineColumnPos();
           if (checkValueID(TypeLoc, "argument", "%", CurValID, ArgID))
             return true;
           Lex.Lex();
+          NameEnd = Lex.getPrevTokEndLineColumnPos();
         } else {
           ArgID = CurValID;
         }
@@ -3421,7 +3427,7 @@ bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
       if (!FunctionType::isValidArgumentType(ArgTy))
         return error(TypeLoc, "invalid type for function argument");
 
-      ArgList.emplace_back(TypeLoc, ArgTy,
+      ArgList.emplace_back(TypeLoc, ArgTy, FileLocRange(NameStart, NameEnd),
                            AttributeSet::get(ArgTy->getContext(), Attrs),
                            std::move(Name));
     } while (EatIfPresent(lltok::comma));
@@ -6933,6 +6939,8 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
   // Add all of the arguments we parsed to the function.
   Function::arg_iterator ArgIt = Fn->arg_begin();
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) {
+    if (ParserContext)
+      ParserContext->addFunctionArgumentLocation(&*ArgIt, ArgList[i].IdentLoc);
     // If the argument has a name, insert it into the argument symbol table.
     if (ArgList[i].Name.empty()) continue;
 

>From a53fe92c0732fe5b4371e87625d2c2e6e5971864 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:24:08 +0000
Subject: [PATCH 04/12] Pass value references locations to ParserContext

---
 llvm/lib/AsmParser/LLParser.cpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index df76598e1363a..84c8149fbd64d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6691,8 +6691,13 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
 bool LLParser::parseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
   V = nullptr;
   ValID ID;
-  return parseValID(ID, PFS, Ty) ||
-         convertValIDToValue(Ty, ID, V, PFS);
+
+  FileLoc Start = Lex.getTokLineColumnPos();
+  bool Ret = parseValID(ID, PFS, Ty) || convertValIDToValue(Ty, ID, V, PFS);
+  FileLoc End = Lex.getPrevTokEndLineColumnPos();
+  if (ParserContext)
+    ParserContext->addValueReferenceAtLocation(V, FileLocRange(Start, End));
+  return Ret;
 }
 
 bool LLParser::parseTypeAndValue(Value *&V, PerFunctionState *PFS) {

>From 773224a6b259177e2d89c2dcf1c1003ed0e197ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:45:07 +0000
Subject: [PATCH 05/12] Implement forgotten function

---
 llvm/lib/AsmParser/AsmParserContext.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/lib/AsmParser/AsmParserContext.cpp b/llvm/lib/AsmParser/AsmParserContext.cpp
index ce847b164ccbb..ab9af50f552cc 100644
--- a/llvm/lib/AsmParser/AsmParserContext.cpp
+++ b/llvm/lib/AsmParser/AsmParserContext.cpp
@@ -102,6 +102,14 @@ bool AsmParserContext::addFunctionLocation(Function *F,
   return Inserted;
 }
 
+bool AsmParserContext::addFunctionArgumentLocation(Argument *FA,
+                                                   const FileLocRange &Loc) {
+  bool Inserted = FunctionArguments.insert({FA, Loc}).second;
+  if (Inserted)
+    FunctionArgumentsInverse.insert(Loc.Start, Loc.End, FA);
+  return Inserted;
+}
+
 bool AsmParserContext::addBlockLocation(BasicBlock *BB,
                                         const FileLocRange &Loc) {
   bool Inserted = Blocks.insert({BB, Loc}).second;

>From 3850c75197f8b86c7fd6da59f90bf973dd4b8183 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:47:05 +0000
Subject: [PATCH 06/12] getFunctionArgumentLocation

---
 llvm/include/llvm/AsmParser/AsmParserContext.h | 2 ++
 llvm/lib/AsmParser/AsmParserContext.cpp        | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/llvm/include/llvm/AsmParser/AsmParserContext.h b/llvm/include/llvm/AsmParser/AsmParserContext.h
index 023d50017cf27..53f611348f7d6 100644
--- a/llvm/include/llvm/AsmParser/AsmParserContext.h
+++ b/llvm/include/llvm/AsmParser/AsmParserContext.h
@@ -74,6 +74,8 @@ class AsmParserContext {
   LLVM_ABI std::optional<FileLocRange>
   getFunctionLocation(const Function *) const;
   LLVM_ABI std::optional<FileLocRange>
+  getFunctionArgumentLocation(const Argument *) const;
+  LLVM_ABI std::optional<FileLocRange>
   getBlockLocation(const BasicBlock *) const;
   LLVM_ABI std::optional<FileLocRange>
   getInstructionLocation(const Instruction *) const;
diff --git a/llvm/lib/AsmParser/AsmParserContext.cpp b/llvm/lib/AsmParser/AsmParserContext.cpp
index ab9af50f552cc..a5f2ddf1219b2 100644
--- a/llvm/lib/AsmParser/AsmParserContext.cpp
+++ b/llvm/lib/AsmParser/AsmParserContext.cpp
@@ -17,6 +17,13 @@ AsmParserContext::getFunctionLocation(const Function *F) const {
   return std::nullopt;
 }
 
+std::optional<FileLocRange>
+AsmParserContext::getFunctionArgumentLocation(const Argument *F) const {
+  if (auto FIt = FunctionArguments.find(F); FIt != FunctionArguments.end())
+    return FIt->second;
+  return std::nullopt;
+}
+
 std::optional<FileLocRange>
 AsmParserContext::getBlockLocation(const BasicBlock *BB) const {
   if (auto BBIt = Blocks.find(BB); BBIt != Blocks.end())

>From 1261024cb0dbb24d141d3c289f9fdaf53d9d44ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 10:47:53 +0000
Subject: [PATCH 07/12] Tests value references and function arguments

---
 llvm/unittests/AsmParser/AsmParserTest.cpp | 23 +++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index f67ed150817f2..351fd5260d7bf 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -495,9 +495,9 @@ TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) {
   } while (false)
 
 TEST(AsmParserTest, ParserObjectLocations) {
-  StringRef Source = "define i32 @main() {\n"
+  StringRef Source = "define i32 @main(i32 %arg) {\n"
                      "entry:\n"
-                     "    %a = add i32 1, 2\n"
+                     "    %a = add i32 1, %arg\n"
                      "    ret i32 %a\n"
                      "}\n";
   LLVMContext Ctx;
@@ -527,7 +527,7 @@ TEST(AsmParserTest, ParserObjectLocations) {
             ParserContext.getBlockAtLocation(*MaybeEntryBBLoc));
 
   SmallVector<FileLocRange> InstructionLocations = {
-      FileLocRange(FileLoc{2, 4}, FileLoc{2, 21}),
+      FileLocRange(FileLoc{2, 4}, FileLoc{2, 24}),
       FileLocRange(FileLoc{3, 4}, FileLoc{3, 14})};
 
   for (const auto &[Inst, ExpectedLoc] : zip(EntryBB, InstructionLocations)) {
@@ -538,6 +538,23 @@ TEST(AsmParserTest, ParserObjectLocations) {
     ASSERT_EQ(ParserContext.getInstructionAtLocation(MaybeInstLoc->Start),
               ParserContext.getInstructionAtLocation(*MaybeInstLoc));
   }
+
+  SmallVector<FileLocRange> FunctionArgumentLocations = {
+      FileLocRange(FileLoc{0, 21}, FileLoc{0, 25}),
+  };
+  for (const auto &[Arg, ExpectedLoc] :
+       zip(MainFn->args(), FunctionArgumentLocations)) {
+    auto MaybeArgLoc = ParserContext.getFunctionArgumentLocation(&Arg);
+    ASSERT_TRUE(MaybeArgLoc.has_value());
+    auto ArgLoc = MaybeArgLoc.value();
+    ASSERT_EQ_LOC(ArgLoc, ExpectedLoc);
+    ASSERT_EQ(ParserContext.getFunctionArgumentAtLocation(ArgLoc.Start),
+              ParserContext.getFunctionArgumentAtLocation(ArgLoc));
+  }
+  ASSERT_EQ(&*MainFn->arg_begin(),
+            ParserContext.getValueReferencedAtLocation(FileLoc(2, 22)));
+  ASSERT_EQ(&*EntryBB.begin(),
+            ParserContext.getValueReferencedAtLocation(FileLoc(3, 13)));
 }
 
 } // end anonymous namespace

>From f7fb5c39b90229184b45242efd148d06ce704914 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 14:19:11 +0000
Subject: [PATCH 08/12] Fix unnamed function arguments

---
 llvm/include/llvm/AsmParser/LLParser.h |  6 +++---
 llvm/lib/AsmParser/LLParser.cpp        | 27 +++++++++++++++-----------
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index c36c338255ce8..d7a772268ae8e 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -612,11 +612,11 @@ namespace llvm {
     struct ArgInfo {
       LocTy Loc;
       Type *Ty;
-      FileLocRange IdentLoc;
+      std::optional<FileLocRange> IdentLoc;
       AttributeSet Attrs;
       std::string Name;
-      ArgInfo(LocTy L, Type *ty, FileLocRange IdentLoc, AttributeSet Attr,
-              const std::string &N)
+      ArgInfo(LocTy L, Type *ty, std::optional<FileLocRange> IdentLoc,
+              AttributeSet Attr, const std::string &N)
           : Loc(L), Ty(ty), IdentLoc(IdentLoc), Attrs(Attr), Name(N) {}
     };
     bool parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 84c8149fbd64d..5f4bbb6e7cadd 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -3401,24 +3401,26 @@ bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
         return error(TypeLoc, "argument can not have void type");
 
       std::string Name;
-      FileLoc NameStart;
-      FileLoc NameEnd;
+      FileLoc IdentStart;
+      FileLoc IdentEnd;
+      bool Unnamed = false;
       if (Lex.getKind() == lltok::LocalVar) {
         Name = Lex.getStrVal();
-        NameStart = Lex.getTokLineColumnPos();
+        IdentStart = Lex.getTokLineColumnPos();
         Lex.Lex();
-        NameEnd = Lex.getPrevTokEndLineColumnPos();
+        IdentEnd = Lex.getPrevTokEndLineColumnPos();
       } else {
         unsigned ArgID;
         if (Lex.getKind() == lltok::LocalVarID) {
           ArgID = Lex.getUIntVal();
-          NameStart = Lex.getTokLineColumnPos();
+          IdentStart = Lex.getTokLineColumnPos();
           if (checkValueID(TypeLoc, "argument", "%", CurValID, ArgID))
             return true;
           Lex.Lex();
-          NameEnd = Lex.getPrevTokEndLineColumnPos();
+          IdentEnd = Lex.getPrevTokEndLineColumnPos();
         } else {
           ArgID = CurValID;
+          Unnamed = true;
         }
         UnnamedArgNums.push_back(ArgID);
         CurValID = ArgID + 1;
@@ -3427,9 +3429,11 @@ bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
       if (!FunctionType::isValidArgumentType(ArgTy))
         return error(TypeLoc, "invalid type for function argument");
 
-      ArgList.emplace_back(TypeLoc, ArgTy, FileLocRange(NameStart, NameEnd),
-                           AttributeSet::get(ArgTy->getContext(), Attrs),
-                           std::move(Name));
+      ArgList.emplace_back(
+          TypeLoc, ArgTy,
+          Unnamed ? std::nullopt
+                  : std::make_optional(FileLocRange(IdentStart, IdentEnd)),
+          AttributeSet::get(ArgTy->getContext(), Attrs), std::move(Name));
     } while (EatIfPresent(lltok::comma));
   }
 
@@ -6944,8 +6948,9 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
   // Add all of the arguments we parsed to the function.
   Function::arg_iterator ArgIt = Fn->arg_begin();
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) {
-    if (ParserContext)
-      ParserContext->addFunctionArgumentLocation(&*ArgIt, ArgList[i].IdentLoc);
+    if (ParserContext && ArgList[i].IdentLoc)
+      ParserContext->addFunctionArgumentLocation(&*ArgIt,
+                                                 ArgList[i].IdentLoc.value());
     // If the argument has a name, insert it into the argument symbol table.
     if (ArgList[i].Name.empty()) continue;
 

>From 84db52621b8ff9787245fddadb7dfc495f9f1418 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Tue, 6 Jan 2026 14:26:44 +0000
Subject: [PATCH 09/12] Add test for unnamed arguments

---
 llvm/unittests/AsmParser/AsmParserTest.cpp | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index 351fd5260d7bf..f5ea544660013 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -495,7 +495,7 @@ TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) {
   } while (false)
 
 TEST(AsmParserTest, ParserObjectLocations) {
-  StringRef Source = "define i32 @main(i32 %arg) {\n"
+  StringRef Source = "define i32 @main(i32 %arg, i64) {\n"
                      "entry:\n"
                      "    %a = add i32 1, %arg\n"
                      "    ret i32 %a\n"
@@ -539,15 +539,16 @@ TEST(AsmParserTest, ParserObjectLocations) {
               ParserContext.getInstructionAtLocation(*MaybeInstLoc));
   }
 
-  SmallVector<FileLocRange> FunctionArgumentLocations = {
-      FileLocRange(FileLoc{0, 21}, FileLoc{0, 25}),
-  };
+  SmallVector<std::optional<FileLocRange>> FunctionArgumentLocations = {
+      FileLocRange(FileLoc{0, 21}, FileLoc{0, 25}), std::nullopt};
   for (const auto &[Arg, ExpectedLoc] :
        zip(MainFn->args(), FunctionArgumentLocations)) {
     auto MaybeArgLoc = ParserContext.getFunctionArgumentLocation(&Arg);
-    ASSERT_TRUE(MaybeArgLoc.has_value());
+    ASSERT_EQ(MaybeArgLoc.has_value(), ExpectedLoc.has_value());
+    if (!ExpectedLoc.has_value())
+      continue;
     auto ArgLoc = MaybeArgLoc.value();
-    ASSERT_EQ_LOC(ArgLoc, ExpectedLoc);
+    ASSERT_EQ_LOC(ArgLoc, ExpectedLoc.value());
     ASSERT_EQ(ParserContext.getFunctionArgumentAtLocation(ArgLoc.Start),
               ParserContext.getFunctionArgumentAtLocation(ArgLoc));
   }

>From 230e1885e848d8701a34f39cacc18888e504b9a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Wed, 7 Jan 2026 14:58:28 +0000
Subject: [PATCH 10/12] Join Argument and Instruction maps and their API

---
 .../include/llvm/AsmParser/AsmParserContext.h | 42 +++-----------
 llvm/lib/AsmParser/AsmParserContext.cpp       | 55 +++++--------------
 llvm/lib/AsmParser/LLParser.cpp               |  6 +-
 llvm/unittests/AsmParser/AsmParserTest.cpp    | 13 +++--
 4 files changed, 34 insertions(+), 82 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/AsmParserContext.h b/llvm/include/llvm/AsmParser/AsmParserContext.h
index 53f611348f7d6..f08bc80612813 100644
--- a/llvm/include/llvm/AsmParser/AsmParserContext.h
+++ b/llvm/include/llvm/AsmParser/AsmParserContext.h
@@ -40,14 +40,6 @@ class AsmParserContext {
   FMap::Allocator FAllocator;
   FMap FunctionsInverse = FMap(FAllocator);
 
-  DenseMap<Argument *, FileLocRange> FunctionArguments;
-  using FAMap =
-      IntervalMap<FileLoc, Argument *,
-                  IntervalMapImpl::NodeSizer<FileLoc, Argument *>::LeafSize,
-                  IntervalMapHalfOpenInfo<FileLoc>>;
-  FAMap::Allocator FAAllocator;
-  FAMap FunctionArgumentsInverse = FAMap(FAAllocator);
-
   DenseMap<BasicBlock *, FileLocRange> Blocks;
   using BBMap =
       IntervalMap<FileLoc, BasicBlock *,
@@ -55,30 +47,23 @@ class AsmParserContext {
                   IntervalMapHalfOpenInfo<FileLoc>>;
   BBMap::Allocator BBAllocator;
   BBMap BlocksInverse = BBMap(BBAllocator);
-  DenseMap<Instruction *, FileLocRange> Instructions;
-  using IMap =
-      IntervalMap<FileLoc, Instruction *,
-                  IntervalMapImpl::NodeSizer<FileLoc, Instruction *>::LeafSize,
-                  IntervalMapHalfOpenInfo<FileLoc>>;
-  IMap::Allocator IAllocator;
-  IMap InstructionsInverse = IMap(IAllocator);
-
+  DenseMap<Value *, FileLocRange> InstructionsAndArguments;
   using VMap =
       IntervalMap<FileLoc, Value *,
                   IntervalMapImpl::NodeSizer<FileLoc, Value *>::LeafSize,
                   IntervalMapHalfOpenInfo<FileLoc>>;
   VMap::Allocator VAllocator;
+  VMap InstructionsAndArgumentsInverse = VMap(VAllocator);
+
   VMap ReferencedValues = VMap(VAllocator);
 
 public:
   LLVM_ABI std::optional<FileLocRange>
   getFunctionLocation(const Function *) const;
   LLVM_ABI std::optional<FileLocRange>
-  getFunctionArgumentLocation(const Argument *) const;
-  LLVM_ABI std::optional<FileLocRange>
   getBlockLocation(const BasicBlock *) const;
   LLVM_ABI std::optional<FileLocRange>
-  getInstructionLocation(const Instruction *) const;
+  getInstructionOrArgumentLocation(const Value *) const;
   /// Get the function at the requested location range.
   /// If no single function occupies the queried range, or the record is
   /// missing, a nullptr is returned.
@@ -90,14 +75,6 @@ class AsmParserContext {
   /// Get the block at the requested location range.
   /// If no single block occupies the queried range, or the record is missing, a
   /// nullptr is returned.
-  Argument *getFunctionArgumentAtLocation(const FileLocRange &) const;
-  /// Get the function at the requested location.
-  /// If no function occupies the queried location, or the record is missing, a
-  /// nullptr is returned.
-  Argument *getFunctionArgumentAtLocation(const FileLoc &) const;
-  /// Get the block at the requested location range.
-  /// If no single block occupies the queried range, or the record is missing, a
-  /// nullptr is returned.
   BasicBlock *getBlockAtLocation(const FileLocRange &) const;
   /// Get the block at the requested location.
   /// If no block occupies the queried location, or the record is missing, a
@@ -106,12 +83,12 @@ class AsmParserContext {
   /// Get the instruction at the requested location range.
   /// If no single instruction occupies the queried range, or the record is
   /// missing, a nullptr is returned.
-  Instruction *getInstructionAtLocation(const FileLocRange &) const;
-  /// Get the instruction at the requested location.
+  Value *getInstructionOrArgumentAtLocation(const FileLocRange &) const;
+  /// Get the instruction or function argument at the requested location.
   /// If no instruction occupies the queried location, or the record is missing,
   /// a nullptr is returned.
-  Instruction *getInstructionAtLocation(const FileLoc &) const;
-  /// Get value referenced at the requested location.
+  Value *getInstructionOrArgumentAtLocation(const FileLoc &) const;
+  /// Get value referenced or function argument at the requested location.
   /// If no value occupies the queried location, or the record is missing,
   /// a nullptr is returned.
   Value *getValueReferencedAtLocation(const FileLoc &) const;
@@ -120,9 +97,8 @@ class AsmParserContext {
   /// a nullptr is returned.
   Value *getValueReferencedAtLocation(const FileLocRange &) const;
   bool addFunctionLocation(Function *, const FileLocRange &);
-  bool addFunctionArgumentLocation(Argument *, const FileLocRange &);
   bool addBlockLocation(BasicBlock *, const FileLocRange &);
-  bool addInstructionLocation(Instruction *, const FileLocRange &);
+  bool addInstructionOrArgumentLocation(Value *, const FileLocRange &);
   bool addValueReferenceAtLocation(Value *, const FileLocRange &);
 };
 } // namespace llvm
diff --git a/llvm/lib/AsmParser/AsmParserContext.cpp b/llvm/lib/AsmParser/AsmParserContext.cpp
index a5f2ddf1219b2..fdc9940bb44b3 100644
--- a/llvm/lib/AsmParser/AsmParserContext.cpp
+++ b/llvm/lib/AsmParser/AsmParserContext.cpp
@@ -17,13 +17,6 @@ AsmParserContext::getFunctionLocation(const Function *F) const {
   return std::nullopt;
 }
 
-std::optional<FileLocRange>
-AsmParserContext::getFunctionArgumentLocation(const Argument *F) const {
-  if (auto FIt = FunctionArguments.find(F); FIt != FunctionArguments.end())
-    return FIt->second;
-  return std::nullopt;
-}
-
 std::optional<FileLocRange>
 AsmParserContext::getBlockLocation(const BasicBlock *BB) const {
   if (auto BBIt = Blocks.find(BB); BBIt != Blocks.end())
@@ -32,8 +25,10 @@ AsmParserContext::getBlockLocation(const BasicBlock *BB) const {
 }
 
 std::optional<FileLocRange>
-AsmParserContext::getInstructionLocation(const Instruction *I) const {
-  if (auto IIt = Instructions.find(I); IIt != Instructions.end())
+AsmParserContext::getInstructionOrArgumentLocation(const Value *IA) const {
+  assert(isa<Instruction>(IA) || isa<Argument>(IA));
+  if (auto IIt = InstructionsAndArguments.find(IA);
+      IIt != InstructionsAndArguments.end())
     return IIt->second;
   return std::nullopt;
 }
@@ -50,19 +45,6 @@ Function *AsmParserContext::getFunctionAtLocation(const FileLoc &Query) const {
   return FunctionsInverse.lookup(Query, nullptr);
 }
 
-Argument *AsmParserContext::getFunctionArgumentAtLocation(
-    const FileLocRange &Query) const {
-  auto It = FunctionArgumentsInverse.find(Query.Start);
-  if (It.stop() <= Query.End)
-    return *It;
-  return nullptr;
-}
-
-Argument *
-AsmParserContext::getFunctionArgumentAtLocation(const FileLoc &Query) const {
-  return FunctionArgumentsInverse.lookup(Query, nullptr);
-}
-
 BasicBlock *
 AsmParserContext::getBlockAtLocation(const FileLocRange &Query) const {
   auto It = BlocksInverse.find(Query.Start);
@@ -75,17 +57,17 @@ BasicBlock *AsmParserContext::getBlockAtLocation(const FileLoc &Query) const {
   return BlocksInverse.lookup(Query, nullptr);
 }
 
-Instruction *
-AsmParserContext::getInstructionAtLocation(const FileLocRange &Query) const {
-  auto It = InstructionsInverse.find(Query.Start);
+Value *AsmParserContext::getInstructionOrArgumentAtLocation(
+    const FileLocRange &Query) const {
+  auto It = InstructionsAndArgumentsInverse.find(Query.Start);
   if (It.stop() <= Query.End)
     return *It;
   return nullptr;
 }
 
-Instruction *
-AsmParserContext::getInstructionAtLocation(const FileLoc &Query) const {
-  return InstructionsInverse.lookup(Query, nullptr);
+Value *AsmParserContext::getInstructionOrArgumentAtLocation(
+    const FileLoc &Query) const {
+  return InstructionsAndArgumentsInverse.lookup(Query, nullptr);
 }
 
 Value *AsmParserContext::getValueReferencedAtLocation(
@@ -109,14 +91,6 @@ bool AsmParserContext::addFunctionLocation(Function *F,
   return Inserted;
 }
 
-bool AsmParserContext::addFunctionArgumentLocation(Argument *FA,
-                                                   const FileLocRange &Loc) {
-  bool Inserted = FunctionArguments.insert({FA, Loc}).second;
-  if (Inserted)
-    FunctionArgumentsInverse.insert(Loc.Start, Loc.End, FA);
-  return Inserted;
-}
-
 bool AsmParserContext::addBlockLocation(BasicBlock *BB,
                                         const FileLocRange &Loc) {
   bool Inserted = Blocks.insert({BB, Loc}).second;
@@ -125,11 +99,12 @@ bool AsmParserContext::addBlockLocation(BasicBlock *BB,
   return Inserted;
 }
 
-bool AsmParserContext::addInstructionLocation(Instruction *I,
-                                              const FileLocRange &Loc) {
-  bool Inserted = Instructions.insert({I, Loc}).second;
+bool AsmParserContext::addInstructionOrArgumentLocation(
+    Value *IA, const FileLocRange &Loc) {
+  assert(isa<Instruction>(IA) || isa<Argument>(IA));
+  bool Inserted = InstructionsAndArguments.insert({IA, Loc}).second;
   if (Inserted)
-    InstructionsInverse.insert(Loc.Start, Loc.End, I);
+    InstructionsAndArgumentsInverse.insert(Loc.Start, Loc.End, IA);
   return Inserted;
 }
 
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 5f4bbb6e7cadd..04b0eb733206b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6949,8 +6949,8 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine,
   Function::arg_iterator ArgIt = Fn->arg_begin();
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) {
     if (ParserContext && ArgList[i].IdentLoc)
-      ParserContext->addFunctionArgumentLocation(&*ArgIt,
-                                                 ArgList[i].IdentLoc.value());
+      ParserContext->addInstructionOrArgumentLocation(
+          &*ArgIt, ArgList[i].IdentLoc.value());
     // If the argument has a name, insert it into the argument symbol table.
     if (ArgList[i].Name.empty()) continue;
 
@@ -7160,7 +7160,7 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) {
       BB->insertDbgRecordBefore(DR.release(), Inst->getIterator());
     TrailingDbgRecord.clear();
     if (ParserContext) {
-      ParserContext->addInstructionLocation(
+      ParserContext->addInstructionOrArgumentLocation(
           Inst, FileLocRange(InstStart, Lex.getPrevTokEndLineColumnPos()));
     }
   } while (!Inst->isTerminator());
diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index f5ea544660013..1ef1fa36ebdcf 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -531,26 +531,27 @@ TEST(AsmParserTest, ParserObjectLocations) {
       FileLocRange(FileLoc{3, 4}, FileLoc{3, 14})};
 
   for (const auto &[Inst, ExpectedLoc] : zip(EntryBB, InstructionLocations)) {
-    auto MaybeInstLoc = ParserContext.getInstructionLocation(&Inst);
+    auto MaybeInstLoc = ParserContext.getInstructionOrArgumentLocation(&Inst);
     ASSERT_TRUE(MaybeMainLoc.has_value());
     auto InstLoc = MaybeInstLoc.value();
     ASSERT_EQ_LOC(InstLoc, ExpectedLoc);
-    ASSERT_EQ(ParserContext.getInstructionAtLocation(MaybeInstLoc->Start),
-              ParserContext.getInstructionAtLocation(*MaybeInstLoc));
+    ASSERT_EQ(
+        ParserContext.getInstructionOrArgumentAtLocation(MaybeInstLoc->Start),
+        ParserContext.getInstructionOrArgumentAtLocation(*MaybeInstLoc));
   }
 
   SmallVector<std::optional<FileLocRange>> FunctionArgumentLocations = {
       FileLocRange(FileLoc{0, 21}, FileLoc{0, 25}), std::nullopt};
   for (const auto &[Arg, ExpectedLoc] :
        zip(MainFn->args(), FunctionArgumentLocations)) {
-    auto MaybeArgLoc = ParserContext.getFunctionArgumentLocation(&Arg);
+    auto MaybeArgLoc = ParserContext.getInstructionOrArgumentLocation(&Arg);
     ASSERT_EQ(MaybeArgLoc.has_value(), ExpectedLoc.has_value());
     if (!ExpectedLoc.has_value())
       continue;
     auto ArgLoc = MaybeArgLoc.value();
     ASSERT_EQ_LOC(ArgLoc, ExpectedLoc.value());
-    ASSERT_EQ(ParserContext.getFunctionArgumentAtLocation(ArgLoc.Start),
-              ParserContext.getFunctionArgumentAtLocation(ArgLoc));
+    ASSERT_EQ(ParserContext.getInstructionOrArgumentAtLocation(ArgLoc.Start),
+              ParserContext.getInstructionOrArgumentAtLocation(ArgLoc));
   }
   ASSERT_EQ(&*MainFn->arg_begin(),
             ParserContext.getValueReferencedAtLocation(FileLoc(2, 22)));

>From 7f3093a1c3549fa95b9bfccee5d08fbf05daa916 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <ahavlicek at azul.com>
Date: Wed, 7 Jan 2026 15:01:55 +0000
Subject: [PATCH 11/12] Fix comment typo

---
 llvm/include/llvm/AsmParser/AsmParserContext.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/AsmParser/AsmParserContext.h b/llvm/include/llvm/AsmParser/AsmParserContext.h
index f08bc80612813..665d56883d753 100644
--- a/llvm/include/llvm/AsmParser/AsmParserContext.h
+++ b/llvm/include/llvm/AsmParser/AsmParserContext.h
@@ -80,7 +80,7 @@ class AsmParserContext {
   /// If no block occupies the queried location, or the record is missing, a
   /// nullptr is returned.
   BasicBlock *getBlockAtLocation(const FileLoc &) const;
-  /// Get the instruction at the requested location range.
+  /// Get the instruction or function argument at the requested location range.
   /// If no single instruction occupies the queried range, or the record is
   /// missing, a nullptr is returned.
   Value *getInstructionOrArgumentAtLocation(const FileLocRange &) const;
@@ -88,7 +88,7 @@ class AsmParserContext {
   /// If no instruction occupies the queried location, or the record is missing,
   /// a nullptr is returned.
   Value *getInstructionOrArgumentAtLocation(const FileLoc &) const;
-  /// Get value referenced or function argument at the requested location.
+  /// Get value referenced at the requested location.
   /// If no value occupies the queried location, or the record is missing,
   /// a nullptr is returned.
   Value *getValueReferencedAtLocation(const FileLoc &) const;

>From ec2d0de409a9149c5f885dd3fef9008a753f4701 Mon Sep 17 00:00:00 2001
From: Bertik23 <39457484+Bertik23 at users.noreply.github.com>
Date: Wed, 28 Jan 2026 12:04:10 +0100
Subject: [PATCH 12/12] Add value to context only if succesfully parsed

Co-authored-by: Nikita Popov <github at npopov.com>
---
 llvm/lib/AsmParser/LLParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 04b0eb733206b..d622f2d9d3f7c 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6699,7 +6699,7 @@ bool LLParser::parseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
   FileLoc Start = Lex.getTokLineColumnPos();
   bool Ret = parseValID(ID, PFS, Ty) || convertValIDToValue(Ty, ID, V, PFS);
   FileLoc End = Lex.getPrevTokEndLineColumnPos();
-  if (ParserContext)
+  if (!Ret && ParserContext)
     ParserContext->addValueReferenceAtLocation(V, FileLocRange(Start, End));
   return Ret;
 }



More information about the llvm-commits mailing list