9
9
10
10
namespace Carbon ::Check {
11
11
12
- static auto GetFile (Context& context, SemIR::CheckIRId ir_id)
13
- -> const SemIR::File* {
14
- if (ir_id == context.sem_ir ().check_ir_id ()) {
15
- // Common case: the IR is the current file.
16
- return &context.sem_ir ();
17
- }
12
+ namespace {
13
+ struct FileInfo {
14
+ const SemIR::File* sem_ir;
15
+ clang::SourceLocation start_loc;
16
+ };
17
+ } // namespace
18
+
19
+ // Map a CheckIRId into information about the corresponding file in both SemIR
20
+ // and Clang's source manager.
21
+ static auto GetFileInfo (Context& context, SemIR::CheckIRId ir_id) -> FileInfo {
22
+ const SemIR::File* sem_ir = &context.sem_ir ();
23
+ unsigned file_index = 0 ;
18
24
19
25
// If the file is imported, locate it in our imports map.
20
- auto import_id = context.check_ir_map ().Get (ir_id);
21
- CARBON_CHECK (import_id.has_value ());
22
- return context.import_irs ().Get (import_id).sem_ir ;
26
+ if (ir_id != context.sem_ir ().check_ir_id ()) {
27
+ auto import_id = context.check_ir_map ().Get (ir_id);
28
+ CARBON_CHECK (import_id.has_value ());
29
+ file_index = import_id.index + 1 ;
30
+
31
+ sem_ir = context.import_irs ().Get (import_id).sem_ir ;
32
+ CARBON_CHECK (sem_ir, " Node location in nonexistent IR" );
33
+ }
34
+
35
+ // If we've seen this file before, reuse the same FileID.
36
+ auto & file_start_locs = context.cpp_carbon_file_locations ();
37
+ if (file_start_locs.size () <= file_index) {
38
+ file_start_locs.resize (file_index + 1 );
39
+ }
40
+ if (file_start_locs[file_index].isValid ()) {
41
+ return {.sem_ir = sem_ir, .start_loc = file_start_locs[file_index]};
42
+ }
43
+
44
+ // We've not seen this file before. Create a corresponding virtual file in
45
+ // Clang's source manager.
46
+ // TODO: Consider recreating the complete import path instead of only the
47
+ // final entry.
48
+ const auto & source = sem_ir->parse_tree ().tokens ().source ();
49
+ auto & src_mgr = context.ast_context ().getSourceManager ();
50
+ auto file_id = src_mgr.createFileID (
51
+ llvm::MemoryBufferRef (source.text (), source.filename ()));
52
+ auto file_start_loc = src_mgr.getLocForStartOfFile (file_id);
53
+ file_start_locs[file_index] = file_start_loc;
54
+ return {.sem_ir = sem_ir, .start_loc = file_start_loc};
23
55
}
24
56
25
57
auto GetCppLocation (Context& context, SemIR::LocId loc_id)
@@ -37,34 +69,14 @@ auto GetCppLocation(Context& context, SemIR::LocId loc_id)
37
69
absolute_node_ids.back ().clang_source_loc_id ());
38
70
}
39
71
40
- // This is a location in Carbon code; decompose it so we can map it into a
41
- // Clang location.
42
- // TODO: Consider recreating the complete import path instead of only the
43
- // final entry.
72
+ // This is a location in Carbon code; get or create a corresponding file in
73
+ // Clang and build a corresponding location.
44
74
auto absolute_node_id = absolute_node_ids.back ();
45
- const auto * ir = GetFile (context, absolute_node_id.check_ir_id ());
46
- CARBON_CHECK (ir, " Node location points at nonexistent IR" );
75
+ auto [ir, start_loc] = GetFileInfo (context, absolute_node_id.check_ir_id ());
47
76
const auto & tree = ir->parse_tree ();
48
- const auto & source = tree.tokens ().source ();
49
77
auto offset =
50
78
tree.tokens ().GetByteOffset (tree.node_token (absolute_node_id.node_id ()));
51
-
52
- // Get or create a corresponding Clang file.
53
- // TODO: Consider caching a mapping from Carbon ImportIRIds to Clang
54
- // start-of-file SourceLocations.
55
- auto & src_mgr = context.ast_context ().getSourceManager ();
56
- auto file = src_mgr.getFileManager ().getOptionalFileRef (source.filename ());
57
- if (!file) {
58
- file = src_mgr.getFileManager ().getVirtualFileRef (
59
- source.filename (), source.text ().size (), /* ModificationTime=*/ 0 );
60
- }
61
- src_mgr.overrideFileContents (
62
- *file, llvm::MemoryBufferRef (source.text (), source.filename ()));
63
-
64
- // Build a corresponding location.
65
- auto file_id = src_mgr.getOrCreateFileID (
66
- *file, clang::SrcMgr::CharacteristicKind::C_User);
67
- return src_mgr.getLocForStartOfFile (file_id).getLocWithOffset (offset);
79
+ return start_loc.getLocWithOffset (offset);
68
80
}
69
81
70
82
} // namespace Carbon::Check
0 commit comments