1 // go-linemap.cc -- GCC implementation of Linemap.
2 
3 // Copyright 2011 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6 
7 #include "go-linemap.h"
8 
9 #include "go-gcc.h"
10 
11 // This class implements the Linemap interface defined by the
12 // frontend.
13 
14 class Gcc_linemap : public Linemap
15 {
16  public:
Gcc_linemap()17   Gcc_linemap()
18     : Linemap(),
19       in_file_(false)
20   { }
21 
22   void
23   start_file(const char* file_name, unsigned int line_begin);
24 
25   void
26   start_line(unsigned int line_number, unsigned int line_size);
27 
28   Location
29   get_location(unsigned int column);
30 
31   void
32   stop();
33 
34   std::string
35   to_string(Location);
36 
37   std::string
38   location_file(Location);
39 
40   int
41   location_line(Location);
42 
43  protected:
44   Location
45   get_predeclared_location();
46 
47   Location
48   get_unknown_location();
49 
50   bool
51   is_predeclared(Location);
52 
53   bool
54   is_unknown(Location);
55 
56  private:
57   // Whether we are currently reading a file.
58   bool in_file_;
59 };
60 
61 Linemap* Linemap::instance_ = NULL;
62 
63 // Start getting locations from a new file.
64 
65 void
start_file(const char * file_name,unsigned line_begin)66 Gcc_linemap::start_file(const char *file_name, unsigned line_begin)
67 {
68   if (this->in_file_)
69     linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
70   linemap_add(line_table, LC_ENTER, 0, file_name, line_begin);
71   this->in_file_ = true;
72 }
73 
74 // Stringify a location
75 
76 std::string
to_string(Location location)77 Gcc_linemap::to_string(Location location)
78 {
79   const line_map_ordinary *lmo;
80   location_t resolved_location;
81 
82   // Screen out unknown and predeclared locations; produce output
83   // only for simple file:line locations.
84   resolved_location =
85       linemap_resolve_location (line_table, location.gcc_location(),
86                                 LRK_SPELLING_LOCATION, &lmo);
87   if (lmo == NULL || resolved_location < RESERVED_LOCATION_COUNT)
88     return "";
89   const char *path = LINEMAP_FILE (lmo);
90   if (!path)
91     return "";
92 
93   // Strip the source file down to the base file, to reduce clutter.
94   std::stringstream ss;
95   ss << lbasename(path) << ":" << SOURCE_LINE (lmo, location.gcc_location());
96   return ss.str();
97 }
98 
99 // Return the file name for a given location.
100 
101 std::string
location_file(Location loc)102 Gcc_linemap::location_file(Location loc)
103 {
104   return LOCATION_FILE(loc.gcc_location());
105 }
106 
107 // Return the line number for a given location.
108 
109 int
location_line(Location loc)110 Gcc_linemap::location_line(Location loc)
111 {
112   return LOCATION_LINE(loc.gcc_location());
113 }
114 
115 // Stop getting locations.
116 
117 void
stop()118 Gcc_linemap::stop()
119 {
120   linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
121   this->in_file_ = false;
122 }
123 
124 // Start a new line.
125 
126 void
start_line(unsigned lineno,unsigned linesize)127 Gcc_linemap::start_line(unsigned lineno, unsigned linesize)
128 {
129   linemap_line_start(line_table, lineno, linesize);
130 }
131 
132 // Get a location.
133 
134 Location
get_location(unsigned column)135 Gcc_linemap::get_location(unsigned column)
136 {
137   return Location(linemap_position_for_column(line_table, column));
138 }
139 
140 // Get the unknown location.
141 
142 Location
get_unknown_location()143 Gcc_linemap::get_unknown_location()
144 {
145   return Location(UNKNOWN_LOCATION);
146 }
147 
148 // Get the predeclared location.
149 
150 Location
get_predeclared_location()151 Gcc_linemap::get_predeclared_location()
152 {
153   return Location(BUILTINS_LOCATION);
154 }
155 
156 // Return whether a location is the predeclared location.
157 
158 bool
is_predeclared(Location loc)159 Gcc_linemap::is_predeclared(Location loc)
160 {
161   return loc.gcc_location() == BUILTINS_LOCATION;
162 }
163 
164 // Return whether a location is the unknown location.
165 
166 bool
is_unknown(Location loc)167 Gcc_linemap::is_unknown(Location loc)
168 {
169   return loc.gcc_location() == UNKNOWN_LOCATION;
170 }
171 
172 // Return the Linemap to use for the gcc backend.
173 
174 Linemap*
go_get_linemap()175 go_get_linemap()
176 {
177   return new Gcc_linemap;
178 }
179