Skip to content

Commit 458599b

Browse files
committed
Add location tracking to IR parser
1 parent 02ade22 commit 458599b

File tree

13 files changed

+440
-76
lines changed

13 files changed

+440
-76
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//===-- AsmParserContext.h --------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_ASMPARSER_ASMPARSER_STATE_H
10+
#define LLVM_ASMPARSER_ASMPARSER_STATE_H
11+
12+
#include "llvm/ADT/DenseMap.h"
13+
#include "llvm/IR/Value.h"
14+
#include <optional>
15+
16+
namespace llvm {
17+
18+
/// Registry of file location information for LLVM IR constructs
19+
///
20+
/// This class provides access to the file location information
21+
/// for various LLVM IR constructs. Currently, it supports Function,
22+
/// BasicBlock and Instruction locations.
23+
///
24+
/// When available, it can answer queries about what is at a given
25+
/// file location, as well as where in a file a given IR construct
26+
/// is.
27+
///
28+
/// This information is optionally emitted by the LLParser while
29+
/// it reads LLVM textual IR.
30+
class AsmParserContext {
31+
public:
32+
std::optional<FileLocRange> getFunctionLocation(const Function *) const;
33+
std::optional<FileLocRange> getBlockLocation(const BasicBlock *) const;
34+
std::optional<FileLocRange> getInstructionLocation(const Instruction *) const;
35+
std::optional<Function *> getFunctionAtLocation(const FileLocRange &) const;
36+
std::optional<Function *> getFunctionAtLocation(const FileLoc &) const;
37+
std::optional<BasicBlock *> getBlockAtLocation(const FileLocRange &) const;
38+
std::optional<BasicBlock *> getBlockAtLocation(const FileLoc &) const;
39+
std::optional<Instruction *>
40+
getInstructionAtLocation(const FileLocRange &) const;
41+
std::optional<Instruction *> getInstructionAtLocation(const FileLoc &) const;
42+
bool addFunctionLocation(Function *, const FileLocRange &);
43+
bool addBlockLocation(BasicBlock *, const FileLocRange &);
44+
bool addInstructionLocation(Instruction *, const FileLocRange &);
45+
46+
private:
47+
DenseMap<Function *, FileLocRange> Functions;
48+
DenseMap<BasicBlock *, FileLocRange> Blocks;
49+
DenseMap<Instruction *, FileLocRange> Instructions;
50+
};
51+
} // namespace llvm
52+
53+
#endif

llvm/include/llvm/AsmParser/LLLexer.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ namespace llvm {
2929
const char *CurPtr;
3030
StringRef CurBuf;
3131

32+
// The line number at `CurPtr-1`, zero-indexed
33+
unsigned CurLineNum = 0;
34+
// The column number at `CurPtr-1`, zero-indexed
35+
unsigned CurColNum = -1;
36+
// The line number of the start of the current token, zero-indexed
37+
unsigned CurTokLineNum = 0;
38+
// The column number of the start of the current token, zero-indexed
39+
unsigned CurTokColNum = 0;
40+
// The line number of the end of the current token, zero-indexed
41+
unsigned PrevTokEndLineNum = -1;
42+
// The column number of the end (exclusive) of the current token,
43+
// zero-indexed
44+
unsigned PrevTokEndColNum = -1;
45+
3246
enum class ErrorPriority {
3347
None, // No error message present.
3448
Parser, // Errors issued by parser.
@@ -62,9 +76,7 @@ namespace llvm {
6276
explicit LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &,
6377
LLVMContext &C);
6478

65-
lltok::Kind Lex() {
66-
return CurKind = LexToken();
67-
}
79+
lltok::Kind Lex() { return CurKind = LexToken(); }
6880

6981
typedef SMLoc LocTy;
7082
LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); }
@@ -79,6 +91,21 @@ namespace llvm {
7991
IgnoreColonInIdentifiers = val;
8092
}
8193

94+
// Get the current line number, zero-indexed
95+
unsigned getLineNum() { return CurLineNum; }
96+
// Get the current column number, zero-indexed
97+
unsigned getColNum() { return CurColNum; }
98+
// Get the line number of the start of the current token, zero-indexed
99+
unsigned getTokLineNum() { return CurTokLineNum; }
100+
// Get the column number of the start of the current token, zero-indexed
101+
unsigned getTokColNum() { return CurTokColNum; }
102+
// Get the line number of the end of the previous token, zero-indexed,
103+
// exclusive
104+
unsigned getPrevTokEndLineNum() { return PrevTokEndLineNum; }
105+
// Get the column number of the end of the previous token, zero-indexed,
106+
// exclusive
107+
unsigned getPrevTokEndColNum() { return PrevTokEndColNum; }
108+
82109
// This returns true as a convenience for the parser functions that return
83110
// true on error.
84111
bool ParseError(LocTy ErrorLoc, const Twine &Msg) {
@@ -94,6 +121,8 @@ namespace llvm {
94121
lltok::Kind LexToken();
95122

96123
int getNextChar();
124+
const char *skipNChars(unsigned N);
125+
void advancePositionTo(const char *Ptr);
97126
void SkipLineComment();
98127
bool SkipCComment();
99128
lltok::Kind ReadString(lltok::Kind kind);

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_ASMPARSER_LLPARSER_H
1414
#define LLVM_ASMPARSER_LLPARSER_H
1515

16+
#include "AsmParserContext.h"
1617
#include "LLLexer.h"
1718
#include "llvm/ADT/StringMap.h"
1819
#include "llvm/AsmParser/NumberedValues.h"
@@ -177,6 +178,9 @@ namespace llvm {
177178
// Map of module ID to path.
178179
std::map<unsigned, StringRef> ModuleIdMap;
179180

181+
/// Keeps track of source locations for Values, BasicBlocks, and Functions
182+
AsmParserContext *ParserContext;
183+
180184
/// Only the llvm-as tool may set this to false to bypass
181185
/// UpgradeDebuginfo so it can generate broken bitcode.
182186
bool UpgradeDebugInfo;
@@ -189,10 +193,11 @@ namespace llvm {
189193
public:
190194
LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *M,
191195
ModuleSummaryIndex *Index, LLVMContext &Context,
192-
SlotMapping *Slots = nullptr)
196+
SlotMapping *Slots = nullptr,
197+
AsmParserContext *ParserContext = nullptr)
193198
: Context(Context), OPLex(F, SM, Err, Context),
194199
Lex(F, SM, Err, Context), M(M), Index(Index), Slots(Slots),
195-
BlockAddressPFS(nullptr) {}
200+
BlockAddressPFS(nullptr), ParserContext(ParserContext) {}
196201
bool Run(
197202
bool UpgradeDebugInfo,
198203
DataLayoutCallbackTy DataLayoutCallback = [](StringRef, StringRef) {

llvm/include/llvm/AsmParser/Parser.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/ADT/STLFunctionalExtras.h"
1717
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/AsmParser/AsmParserContext.h"
1819
#include "llvm/Support/Compiler.h"
1920
#include <memory>
2021
#include <optional>
@@ -62,7 +63,8 @@ parseAssemblyFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
6263
/// parsing.
6364
LLVM_ABI std::unique_ptr<Module>
6465
parseAssemblyString(StringRef AsmString, SMDiagnostic &Err,
65-
LLVMContext &Context, SlotMapping *Slots = nullptr);
66+
LLVMContext &Context, SlotMapping *Slots = nullptr,
67+
AsmParserContext *ParserContext = nullptr);
6668

6769
/// Holds the Module and ModuleSummaryIndex returned by the interfaces
6870
/// that parse both.
@@ -128,9 +130,9 @@ parseSummaryIndexAssemblyString(StringRef AsmString, SMDiagnostic &Err);
128130
LLVM_ABI std::unique_ptr<Module> parseAssembly(
129131
MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context,
130132
SlotMapping *Slots = nullptr,
131-
DataLayoutCallbackTy DataLayoutCallback = [](StringRef, StringRef) {
132-
return std::nullopt;
133-
});
133+
DataLayoutCallbackTy DataLayoutCallback =
134+
[](StringRef, StringRef) { return std::nullopt; },
135+
AsmParserContext *ParserContext = nullptr);
134136

135137
/// Parse LLVM Assembly including the summary index from a MemoryBuffer.
136138
///
@@ -169,9 +171,9 @@ parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err);
169171
LLVM_ABI bool parseAssemblyInto(
170172
MemoryBufferRef F, Module *M, ModuleSummaryIndex *Index, SMDiagnostic &Err,
171173
SlotMapping *Slots = nullptr,
172-
DataLayoutCallbackTy DataLayoutCallback = [](StringRef, StringRef) {
173-
return std::nullopt;
174-
});
174+
DataLayoutCallbackTy DataLayoutCallback =
175+
[](StringRef, StringRef) { return std::nullopt; },
176+
AsmParserContext *ParserContext = nullptr);
175177

176178
/// Parse a type and a constant value in the given string.
177179
///

llvm/include/llvm/IR/Value.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,38 @@ class User;
5555

5656
using ValueName = StringMapEntry<Value *>;
5757

58+
struct FileLoc {
59+
unsigned Line;
60+
unsigned Col;
61+
62+
bool operator<=(const FileLoc &RHS) const {
63+
return Line < RHS.Line || (Line == RHS.Line && Col <= RHS.Col);
64+
}
65+
66+
bool operator<(const FileLoc &RHS) const {
67+
return Line < RHS.Line || (Line == RHS.Line && Col < RHS.Col);
68+
}
69+
70+
FileLoc(unsigned L, unsigned C) : Line(L), Col(C) {}
71+
};
72+
73+
struct FileLocRange {
74+
FileLoc Start;
75+
FileLoc End;
76+
77+
FileLocRange() : Start(0, 0), End(0, 0) {}
78+
79+
FileLocRange(FileLoc S, FileLoc E) : Start(S), End(E) {
80+
assert(Start <= End);
81+
}
82+
83+
bool contains(FileLoc L) const { return Start <= L && L <= End; }
84+
85+
bool contains(FileLocRange LR) const {
86+
return contains(LR.Start) && contains(LR.End);
87+
}
88+
};
89+
5890
//===----------------------------------------------------------------------===//
5991
// Value Class
6092
//===----------------------------------------------------------------------===//

llvm/include/llvm/IRReader/IRReader.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_IRREADER_IRREADER_H
1616

1717
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/AsmParser/AsmParserContext.h"
1819
#include "llvm/Bitcode/BitcodeReader.h"
1920
#include "llvm/Support/Compiler.h"
2021
#include <memory>
@@ -50,19 +51,19 @@ getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
5051
/// for it. Otherwise, attempt to parse it as LLVM Assembly and return
5152
/// a Module for it.
5253
/// \param DataLayoutCallback Override datalayout in the llvm assembly.
53-
LLVM_ABI std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer,
54-
SMDiagnostic &Err,
55-
LLVMContext &Context,
56-
ParserCallbacks Callbacks = {});
54+
LLVM_ABI std::unique_ptr<Module>
55+
parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, LLVMContext &Context,
56+
ParserCallbacks Callbacks = {},
57+
AsmParserContext *ParserContext = nullptr);
5758

5859
/// If the given file holds a bitcode image, return a Module for it.
5960
/// Otherwise, attempt to parse it as LLVM Assembly and return a Module
6061
/// for it.
6162
/// \param DataLayoutCallback Override datalayout in the llvm assembly.
62-
LLVM_ABI std::unique_ptr<Module> parseIRFile(StringRef Filename,
63-
SMDiagnostic &Err,
64-
LLVMContext &Context,
65-
ParserCallbacks Callbacks = {});
63+
LLVM_ABI std::unique_ptr<Module>
64+
parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context,
65+
ParserCallbacks Callbacks = {},
66+
AsmParserContext *ParserContext = nullptr);
6667
}
6768

6869
#endif
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===-- AsmParserContext.cpp ------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/AsmParser/AsmParserContext.h"
10+
11+
namespace llvm {
12+
13+
std::optional<FileLocRange>
14+
AsmParserContext::getFunctionLocation(const Function *F) const {
15+
if (!Functions.contains(F))
16+
return std::nullopt;
17+
return Functions.at(F);
18+
}
19+
20+
std::optional<FileLocRange>
21+
AsmParserContext::getBlockLocation(const BasicBlock *BB) const {
22+
if (!Blocks.contains(BB))
23+
return std::nullopt;
24+
return Blocks.at(BB);
25+
}
26+
27+
std::optional<FileLocRange>
28+
AsmParserContext::getInstructionLocation(const Instruction *I) const {
29+
if (!Instructions.contains(I))
30+
return std::nullopt;
31+
return Instructions.at(I);
32+
}
33+
34+
std::optional<Function *>
35+
AsmParserContext::getFunctionAtLocation(const FileLocRange &Query) const {
36+
for (auto &[F, Loc] : Functions) {
37+
if (Loc.contains(Query))
38+
return F;
39+
}
40+
return std::nullopt;
41+
}
42+
43+
std::optional<Function *>
44+
AsmParserContext::getFunctionAtLocation(const FileLoc &Query) const {
45+
return getFunctionAtLocation(FileLocRange(Query, Query));
46+
}
47+
48+
std::optional<BasicBlock *>
49+
AsmParserContext::getBlockAtLocation(const FileLocRange &Query) const {
50+
for (auto &[BB, Loc] : Blocks) {
51+
if (Loc.contains(Query))
52+
return BB;
53+
}
54+
return std::nullopt;
55+
}
56+
57+
std::optional<BasicBlock *>
58+
AsmParserContext::getBlockAtLocation(const FileLoc &Query) const {
59+
return getBlockAtLocation(FileLocRange(Query, Query));
60+
}
61+
62+
std::optional<Instruction *>
63+
AsmParserContext::getInstructionAtLocation(const FileLocRange &Query) const {
64+
for (auto &[I, Loc] : Instructions) {
65+
if (Loc.contains(Query))
66+
return I;
67+
}
68+
return std::nullopt;
69+
}
70+
71+
std::optional<Instruction *>
72+
AsmParserContext::getInstructionAtLocation(const FileLoc &Query) const {
73+
return getInstructionAtLocation(FileLocRange(Query, Query));
74+
}
75+
76+
bool AsmParserContext::addFunctionLocation(Function *F,
77+
const FileLocRange &Loc) {
78+
return Functions.insert({F, Loc}).second;
79+
}
80+
81+
bool AsmParserContext::addBlockLocation(BasicBlock *BB,
82+
const FileLocRange &Loc) {
83+
return Blocks.insert({BB, Loc}).second;
84+
}
85+
86+
bool AsmParserContext::addInstructionLocation(Instruction *I,
87+
const FileLocRange &Loc) {
88+
return Instructions.insert({I, Loc}).second;
89+
}
90+
91+
} // namespace llvm

llvm/lib/AsmParser/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# AsmParser
22
add_llvm_component_library(LLVMAsmParser
3+
AsmParserContext.cpp
34
LLLexer.cpp
45
LLParser.cpp
56
Parser.cpp

0 commit comments

Comments
 (0)