annotate gcc/go/gofrontend/import.cc @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // import.cc -- Go frontend import declarations.
kono
parents:
diff changeset
2
kono
parents:
diff changeset
3 // Copyright 2009 The Go Authors. All rights reserved.
kono
parents:
diff changeset
4 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
5 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 #include "go-system.h"
kono
parents:
diff changeset
8
kono
parents:
diff changeset
9 #include "filenames.h"
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 #include "go-c.h"
kono
parents:
diff changeset
12 #include "go-diagnostics.h"
kono
parents:
diff changeset
13 #include "gogo.h"
kono
parents:
diff changeset
14 #include "lex.h"
kono
parents:
diff changeset
15 #include "types.h"
kono
parents:
diff changeset
16 #include "export.h"
kono
parents:
diff changeset
17 #include "import.h"
kono
parents:
diff changeset
18
kono
parents:
diff changeset
19 #ifndef O_BINARY
kono
parents:
diff changeset
20 #define O_BINARY 0
kono
parents:
diff changeset
21 #endif
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 // The list of paths we search for import files.
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 static std::vector<std::string> search_path;
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 // Add a directory to the search path. This is called from the option
kono
parents:
diff changeset
28 // handling language hook.
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 GO_EXTERN_C
kono
parents:
diff changeset
31 void
kono
parents:
diff changeset
32 go_add_search_path(const char* path)
kono
parents:
diff changeset
33 {
kono
parents:
diff changeset
34 search_path.push_back(std::string(path));
kono
parents:
diff changeset
35 }
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 // Find import data. This searches the file system for FILENAME and
kono
parents:
diff changeset
38 // returns a pointer to a Stream object to read the data that it
kono
parents:
diff changeset
39 // exports. If the file is not found, it returns NULL.
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 // When FILENAME is not an absolute path and does not start with ./ or
kono
parents:
diff changeset
42 // ../, we use the search path provided by -I and -L options.
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 // When FILENAME does start with ./ or ../, we use
kono
parents:
diff changeset
45 // RELATIVE_IMPORT_PATH as a prefix.
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 // When FILENAME does not exist, we try modifying FILENAME to find the
kono
parents:
diff changeset
48 // file. We use the first of these which exists:
kono
parents:
diff changeset
49 // * We append ".gox".
kono
parents:
diff changeset
50 // * We turn the base of FILENAME into libFILENAME.so.
kono
parents:
diff changeset
51 // * We turn the base of FILENAME into libFILENAME.a.
kono
parents:
diff changeset
52 // * We append ".o".
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 // When using a search path, we apply each of these transformations at
kono
parents:
diff changeset
55 // each entry on the search path before moving on to the next entry.
kono
parents:
diff changeset
56 // If the file exists, but does not contain any Go export data, we
kono
parents:
diff changeset
57 // stop; we do not keep looking for another file with the same name
kono
parents:
diff changeset
58 // later in the search path.
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 Import::Stream*
kono
parents:
diff changeset
61 Import::open_package(const std::string& filename, Location location,
kono
parents:
diff changeset
62 const std::string& relative_import_path)
kono
parents:
diff changeset
63 {
kono
parents:
diff changeset
64 bool is_local;
kono
parents:
diff changeset
65 if (IS_ABSOLUTE_PATH(filename))
kono
parents:
diff changeset
66 is_local = true;
kono
parents:
diff changeset
67 else if (filename[0] == '.'
kono
parents:
diff changeset
68 && (filename[1] == '\0' || IS_DIR_SEPARATOR(filename[1])))
kono
parents:
diff changeset
69 is_local = true;
kono
parents:
diff changeset
70 else if (filename[0] == '.'
kono
parents:
diff changeset
71 && filename[1] == '.'
kono
parents:
diff changeset
72 && (filename[2] == '\0' || IS_DIR_SEPARATOR(filename[2])))
kono
parents:
diff changeset
73 is_local = true;
kono
parents:
diff changeset
74 else
kono
parents:
diff changeset
75 is_local = false;
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 std::string fn = filename;
kono
parents:
diff changeset
78 if (is_local && !IS_ABSOLUTE_PATH(filename) && !relative_import_path.empty())
kono
parents:
diff changeset
79 {
kono
parents:
diff changeset
80 if (fn == ".")
kono
parents:
diff changeset
81 {
kono
parents:
diff changeset
82 // A special case.
kono
parents:
diff changeset
83 fn = relative_import_path;
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85 else if (fn[0] == '.' && fn[1] == '.'
kono
parents:
diff changeset
86 && (fn[2] == '\0' || IS_DIR_SEPARATOR(fn[2])))
kono
parents:
diff changeset
87 {
kono
parents:
diff changeset
88 // We are going to join relative_import_path and fn, and it
kono
parents:
diff changeset
89 // will look like DIR/../PATH. But DIR does not necessarily
kono
parents:
diff changeset
90 // exist in this case, and if it doesn't the use of .. will
kono
parents:
diff changeset
91 // fail although it shouldn't. The gc compiler uses
kono
parents:
diff changeset
92 // path.Join here, which cleans up the .., so we need to do
kono
parents:
diff changeset
93 // the same.
kono
parents:
diff changeset
94 size_t index;
kono
parents:
diff changeset
95 for (index = relative_import_path.length() - 1;
kono
parents:
diff changeset
96 index > 0 && !IS_DIR_SEPARATOR(relative_import_path[index]);
kono
parents:
diff changeset
97 index--)
kono
parents:
diff changeset
98 ;
kono
parents:
diff changeset
99 if (index > 0)
kono
parents:
diff changeset
100 fn = relative_import_path.substr(0, index) + fn.substr(2);
kono
parents:
diff changeset
101 else
kono
parents:
diff changeset
102 fn = relative_import_path + '/' + fn;
kono
parents:
diff changeset
103 }
kono
parents:
diff changeset
104 else
kono
parents:
diff changeset
105 fn = relative_import_path + '/' + fn;
kono
parents:
diff changeset
106 is_local = false;
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 if (!is_local)
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 for (std::vector<std::string>::const_iterator p = search_path.begin();
kono
parents:
diff changeset
112 p != search_path.end();
kono
parents:
diff changeset
113 ++p)
kono
parents:
diff changeset
114 {
kono
parents:
diff changeset
115 std::string indir = *p;
kono
parents:
diff changeset
116 if (!indir.empty() && indir[indir.size() - 1] != '/')
kono
parents:
diff changeset
117 indir += '/';
kono
parents:
diff changeset
118 indir += fn;
kono
parents:
diff changeset
119 Stream* s = Import::try_package_in_directory(indir, location);
kono
parents:
diff changeset
120 if (s != NULL)
kono
parents:
diff changeset
121 return s;
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 Stream* s = Import::try_package_in_directory(fn, location);
kono
parents:
diff changeset
126 if (s != NULL)
kono
parents:
diff changeset
127 return s;
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 return NULL;
kono
parents:
diff changeset
130 }
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 // Try to find the export data for FILENAME.
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 Import::Stream*
kono
parents:
diff changeset
135 Import::try_package_in_directory(const std::string& filename,
kono
parents:
diff changeset
136 Location location)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 std::string found_filename = filename;
kono
parents:
diff changeset
139 int fd = open(found_filename.c_str(), O_RDONLY | O_BINARY);
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 if (fd >= 0)
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 struct stat s;
kono
parents:
diff changeset
144 if (fstat(fd, &s) >= 0 && S_ISDIR(s.st_mode))
kono
parents:
diff changeset
145 {
kono
parents:
diff changeset
146 close(fd);
kono
parents:
diff changeset
147 fd = -1;
kono
parents:
diff changeset
148 errno = EISDIR;
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150 }
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 if (fd < 0)
kono
parents:
diff changeset
153 {
kono
parents:
diff changeset
154 if (errno != ENOENT && errno != EISDIR)
kono
parents:
diff changeset
155 go_warning_at(location, 0, "%s: %m", filename.c_str());
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 fd = Import::try_suffixes(&found_filename);
kono
parents:
diff changeset
158 if (fd < 0)
kono
parents:
diff changeset
159 return NULL;
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 // The export data may not be in this file.
kono
parents:
diff changeset
163 Stream* s = Import::find_export_data(found_filename, fd, location);
kono
parents:
diff changeset
164 if (s != NULL)
kono
parents:
diff changeset
165 return s;
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 close(fd);
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 go_error_at(location, "%s exists but does not contain any Go export data",
kono
parents:
diff changeset
170 found_filename.c_str());
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 return NULL;
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 // Given import "*PFILENAME", where *PFILENAME does not exist, try
kono
parents:
diff changeset
176 // various suffixes. If we find one, set *PFILENAME to the one we
kono
parents:
diff changeset
177 // found. Return the open file descriptor.
kono
parents:
diff changeset
178
kono
parents:
diff changeset
179 int
kono
parents:
diff changeset
180 Import::try_suffixes(std::string* pfilename)
kono
parents:
diff changeset
181 {
kono
parents:
diff changeset
182 std::string filename = *pfilename + ".gox";
kono
parents:
diff changeset
183 int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
kono
parents:
diff changeset
184 if (fd >= 0)
kono
parents:
diff changeset
185 {
kono
parents:
diff changeset
186 *pfilename = filename;
kono
parents:
diff changeset
187 return fd;
kono
parents:
diff changeset
188 }
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 const char* basename = lbasename(pfilename->c_str());
kono
parents:
diff changeset
191 size_t basename_pos = basename - pfilename->c_str();
kono
parents:
diff changeset
192 filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".so";
kono
parents:
diff changeset
193 fd = open(filename.c_str(), O_RDONLY | O_BINARY);
kono
parents:
diff changeset
194 if (fd >= 0)
kono
parents:
diff changeset
195 {
kono
parents:
diff changeset
196 *pfilename = filename;
kono
parents:
diff changeset
197 return fd;
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".a";
kono
parents:
diff changeset
201 fd = open(filename.c_str(), O_RDONLY | O_BINARY);
kono
parents:
diff changeset
202 if (fd >= 0)
kono
parents:
diff changeset
203 {
kono
parents:
diff changeset
204 *pfilename = filename;
kono
parents:
diff changeset
205 return fd;
kono
parents:
diff changeset
206 }
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 filename = *pfilename + ".o";
kono
parents:
diff changeset
209 fd = open(filename.c_str(), O_RDONLY | O_BINARY);
kono
parents:
diff changeset
210 if (fd >= 0)
kono
parents:
diff changeset
211 {
kono
parents:
diff changeset
212 *pfilename = filename;
kono
parents:
diff changeset
213 return fd;
kono
parents:
diff changeset
214 }
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 return -1;
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 // Look for export data in the file descriptor FD.
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 Import::Stream*
kono
parents:
diff changeset
222 Import::find_export_data(const std::string& filename, int fd, Location location)
kono
parents:
diff changeset
223 {
kono
parents:
diff changeset
224 // See if we can read this as an object file.
kono
parents:
diff changeset
225 Import::Stream* stream = Import::find_object_export_data(filename, fd, 0,
kono
parents:
diff changeset
226 location);
kono
parents:
diff changeset
227 if (stream != NULL)
kono
parents:
diff changeset
228 return stream;
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 const int len = MAX(Export::magic_len, Import::archive_magic_len);
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 if (lseek(fd, 0, SEEK_SET) < 0)
kono
parents:
diff changeset
233 {
kono
parents:
diff changeset
234 go_error_at(location, "lseek %s failed: %m", filename.c_str());
kono
parents:
diff changeset
235 return NULL;
kono
parents:
diff changeset
236 }
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 char buf[len];
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
239 ssize_t c = ::read(fd, buf, len);
111
kono
parents:
diff changeset
240 if (c < len)
kono
parents:
diff changeset
241 return NULL;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 // Check for a file containing nothing but Go export data.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
244 if (memcmp(buf, Export::cur_magic, Export::magic_len) == 0
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
245 || memcmp(buf, Export::v1_magic, Export::magic_len) == 0
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
246 || memcmp(buf, Export::v2_magic, Export::magic_len) == 0)
111
kono
parents:
diff changeset
247 return new Stream_from_file(fd);
kono
parents:
diff changeset
248
kono
parents:
diff changeset
249 // See if we can read this as an archive.
kono
parents:
diff changeset
250 if (Import::is_archive_magic(buf))
kono
parents:
diff changeset
251 return Import::find_archive_export_data(filename, fd, location);
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 return NULL;
kono
parents:
diff changeset
254 }
kono
parents:
diff changeset
255
kono
parents:
diff changeset
256 // Look for export data in an object file.
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 Import::Stream*
kono
parents:
diff changeset
259 Import::find_object_export_data(const std::string& filename,
kono
parents:
diff changeset
260 int fd,
kono
parents:
diff changeset
261 off_t offset,
kono
parents:
diff changeset
262 Location location)
kono
parents:
diff changeset
263 {
kono
parents:
diff changeset
264 char *buf;
kono
parents:
diff changeset
265 size_t len;
kono
parents:
diff changeset
266 int err;
kono
parents:
diff changeset
267 const char *errmsg = go_read_export_data(fd, offset, &buf, &len, &err);
kono
parents:
diff changeset
268 if (errmsg != NULL)
kono
parents:
diff changeset
269 {
kono
parents:
diff changeset
270 if (err == 0)
kono
parents:
diff changeset
271 go_error_at(location, "%s: %s", filename.c_str(), errmsg);
kono
parents:
diff changeset
272 else
kono
parents:
diff changeset
273 go_error_at(location, "%s: %s: %s", filename.c_str(), errmsg,
kono
parents:
diff changeset
274 xstrerror(err));
kono
parents:
diff changeset
275 return NULL;
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 if (buf == NULL)
kono
parents:
diff changeset
279 return NULL;
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 return new Stream_from_buffer(buf, len);
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 // Class Import.
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 // Construct an Import object. We make the builtin_types_ vector
kono
parents:
diff changeset
287 // large enough to hold all the builtin types.
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 Import::Import(Stream* stream, Location location)
kono
parents:
diff changeset
290 : gogo_(NULL), stream_(stream), location_(location), package_(NULL),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
291 add_to_globals_(false), packages_(), type_data_(), type_pos_(0),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
292 type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
111
kono
parents:
diff changeset
293 types_(), version_(EXPORT_FORMAT_UNKNOWN)
kono
parents:
diff changeset
294 {
kono
parents:
diff changeset
295 }
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 // Import the data in the associated stream.
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 Package*
kono
parents:
diff changeset
300 Import::import(Gogo* gogo, const std::string& local_name,
kono
parents:
diff changeset
301 bool is_local_name_exported)
kono
parents:
diff changeset
302 {
kono
parents:
diff changeset
303 // Hold on to the Gogo structure. Otherwise we need to pass it
kono
parents:
diff changeset
304 // through all the import functions, because we need it when reading
kono
parents:
diff changeset
305 // a type.
kono
parents:
diff changeset
306 this->gogo_ = gogo;
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 // A stream of export data can include data from more than one input
kono
parents:
diff changeset
309 // file. Here we loop over each input file.
kono
parents:
diff changeset
310 Stream* stream = this->stream_;
kono
parents:
diff changeset
311 while (!stream->at_eof() && !stream->saw_error())
kono
parents:
diff changeset
312 {
kono
parents:
diff changeset
313 // The vector of types is package specific.
kono
parents:
diff changeset
314 this->types_.clear();
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 // Check magic string / version number.
kono
parents:
diff changeset
317 if (stream->match_bytes(Export::cur_magic, Export::magic_len))
kono
parents:
diff changeset
318 {
kono
parents:
diff changeset
319 stream->require_bytes(this->location_, Export::cur_magic,
kono
parents:
diff changeset
320 Export::magic_len);
kono
parents:
diff changeset
321 this->version_ = EXPORT_FORMAT_CURRENT;
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323 else if (stream->match_bytes(Export::v1_magic, Export::magic_len))
kono
parents:
diff changeset
324 {
kono
parents:
diff changeset
325 stream->require_bytes(this->location_, Export::v1_magic,
kono
parents:
diff changeset
326 Export::magic_len);
kono
parents:
diff changeset
327 this->version_ = EXPORT_FORMAT_V1;
kono
parents:
diff changeset
328 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
329 else if (stream->match_bytes(Export::v2_magic, Export::magic_len))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
330 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
331 stream->require_bytes(this->location_, Export::v2_magic,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
332 Export::magic_len);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
333 this->version_ = EXPORT_FORMAT_V2;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
334 }
111
kono
parents:
diff changeset
335 else
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 go_error_at(this->location_,
kono
parents:
diff changeset
338 ("error in import data at %d: invalid magic string"),
kono
parents:
diff changeset
339 stream->pos());
kono
parents:
diff changeset
340 return NULL;
kono
parents:
diff changeset
341 }
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 this->require_c_string("package ");
kono
parents:
diff changeset
344 std::string package_name = this->read_identifier();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
345 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
346 this->require_c_string("\n");
111
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 std::string pkgpath;
kono
parents:
diff changeset
349 std::string pkgpath_symbol;
kono
parents:
diff changeset
350 if (this->match_c_string("prefix "))
kono
parents:
diff changeset
351 {
kono
parents:
diff changeset
352 this->advance(7);
kono
parents:
diff changeset
353 std::string unique_prefix = this->read_identifier();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
354 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
355 this->require_c_string("\n");
111
kono
parents:
diff changeset
356 pkgpath = unique_prefix + '.' + package_name;
kono
parents:
diff changeset
357 pkgpath_symbol = (Gogo::pkgpath_for_symbol(unique_prefix) + '.'
kono
parents:
diff changeset
358 + Gogo::pkgpath_for_symbol(package_name));
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360 else
kono
parents:
diff changeset
361 {
kono
parents:
diff changeset
362 this->require_c_string("pkgpath ");
kono
parents:
diff changeset
363 pkgpath = this->read_identifier();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
364 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
365 this->require_c_string("\n");
111
kono
parents:
diff changeset
366 pkgpath_symbol = Gogo::pkgpath_for_symbol(pkgpath);
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
369 if (stream->saw_error())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
370 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
371
111
kono
parents:
diff changeset
372 this->package_ = gogo->add_imported_package(package_name, local_name,
kono
parents:
diff changeset
373 is_local_name_exported,
kono
parents:
diff changeset
374 pkgpath, pkgpath_symbol,
kono
parents:
diff changeset
375 this->location_,
kono
parents:
diff changeset
376 &this->add_to_globals_);
kono
parents:
diff changeset
377 if (this->package_ == NULL)
kono
parents:
diff changeset
378 {
kono
parents:
diff changeset
379 stream->set_saw_error();
kono
parents:
diff changeset
380 return NULL;
kono
parents:
diff changeset
381 }
kono
parents:
diff changeset
382
kono
parents:
diff changeset
383 // Read and discard priority if older V1 export data format.
kono
parents:
diff changeset
384 if (version() == EXPORT_FORMAT_V1)
kono
parents:
diff changeset
385 {
kono
parents:
diff changeset
386 this->require_c_string("priority ");
kono
parents:
diff changeset
387 std::string priority_string = this->read_identifier();
kono
parents:
diff changeset
388 int prio;
kono
parents:
diff changeset
389 if (!this->string_to_int(priority_string, false, &prio))
kono
parents:
diff changeset
390 return NULL;
kono
parents:
diff changeset
391 this->require_c_string(";\n");
kono
parents:
diff changeset
392 }
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 while (stream->match_c_string("package"))
kono
parents:
diff changeset
395 this->read_one_package();
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 while (stream->match_c_string("import"))
kono
parents:
diff changeset
398 this->read_one_import();
kono
parents:
diff changeset
399
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
400 while (stream->match_c_string("indirectimport"))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
401 this->read_one_indirect_import();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
402
111
kono
parents:
diff changeset
403 if (stream->match_c_string("init"))
kono
parents:
diff changeset
404 this->read_import_init_fns(gogo);
kono
parents:
diff changeset
405
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
406 if (stream->match_c_string("types "))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
407 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
408 if (!this->read_types())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
409 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
410 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
411
111
kono
parents:
diff changeset
412 // Loop over all the input data for this package.
kono
parents:
diff changeset
413 while (!stream->saw_error())
kono
parents:
diff changeset
414 {
kono
parents:
diff changeset
415 if (stream->match_c_string("const "))
kono
parents:
diff changeset
416 this->import_const();
kono
parents:
diff changeset
417 else if (stream->match_c_string("type "))
kono
parents:
diff changeset
418 this->import_type();
kono
parents:
diff changeset
419 else if (stream->match_c_string("var "))
kono
parents:
diff changeset
420 this->import_var();
kono
parents:
diff changeset
421 else if (stream->match_c_string("func "))
kono
parents:
diff changeset
422 this->import_func(this->package_);
kono
parents:
diff changeset
423 else if (stream->match_c_string("checksum "))
kono
parents:
diff changeset
424 break;
kono
parents:
diff changeset
425 else
kono
parents:
diff changeset
426 {
kono
parents:
diff changeset
427 go_error_at(this->location_,
kono
parents:
diff changeset
428 ("error in import data at %d: "
kono
parents:
diff changeset
429 "expected %<const%>, %<type%>, %<var%>, "
kono
parents:
diff changeset
430 "%<func%>, or %<checksum%>"),
kono
parents:
diff changeset
431 stream->pos());
kono
parents:
diff changeset
432 stream->set_saw_error();
kono
parents:
diff changeset
433 return NULL;
kono
parents:
diff changeset
434 }
kono
parents:
diff changeset
435 }
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 // We currently ignore the checksum. In the future we could
kono
parents:
diff changeset
438 // store the checksum somewhere in the generated object and then
kono
parents:
diff changeset
439 // verify that the checksum matches at link time or at dynamic
kono
parents:
diff changeset
440 // load time.
kono
parents:
diff changeset
441 this->require_c_string("checksum ");
kono
parents:
diff changeset
442 stream->advance(Export::checksum_len * 2);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
443 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
444 this->require_c_string("\n");
111
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
447 // Finalize methods for any imported types. This call is made late in the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
448 // import process so as to A) avoid finalization of a type whose methods
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
449 // refer to types that are only partially read in, and B) capture both the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
450 // types imported by read_types() directly, and those imported indirectly
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
451 // because they are referenced by an imported function or variable.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
452 // See issues #33013 and #33219 for more on why this is needed.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
453 this->finalize_methods();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
454
111
kono
parents:
diff changeset
455 return this->package_;
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 // Read a package line. This let us reliably determine the pkgpath
kono
parents:
diff changeset
459 // symbol, even if the package was compiled with a -fgo-prefix option.
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 void
kono
parents:
diff changeset
462 Import::read_one_package()
kono
parents:
diff changeset
463 {
kono
parents:
diff changeset
464 this->require_c_string("package ");
kono
parents:
diff changeset
465 std::string package_name = this->read_identifier();
kono
parents:
diff changeset
466 this->require_c_string(" ");
kono
parents:
diff changeset
467 std::string pkgpath = this->read_identifier();
kono
parents:
diff changeset
468 this->require_c_string(" ");
kono
parents:
diff changeset
469 std::string pkgpath_symbol = this->read_identifier();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
470 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
471 this->require_c_string("\n");
111
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol,
kono
parents:
diff changeset
474 Linemap::unknown_location());
kono
parents:
diff changeset
475 p->set_package_name(package_name, this->location());
kono
parents:
diff changeset
476 }
kono
parents:
diff changeset
477
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
478 // Read an import line.
111
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 void
kono
parents:
diff changeset
481 Import::read_one_import()
kono
parents:
diff changeset
482 {
kono
parents:
diff changeset
483 this->require_c_string("import ");
kono
parents:
diff changeset
484 std::string package_name = this->read_identifier();
kono
parents:
diff changeset
485 this->require_c_string(" ");
kono
parents:
diff changeset
486 std::string pkgpath = this->read_identifier();
kono
parents:
diff changeset
487 this->require_c_string(" \"");
kono
parents:
diff changeset
488 Stream* stream = this->stream_;
kono
parents:
diff changeset
489 while (stream->peek_char() != '"')
kono
parents:
diff changeset
490 stream->advance(1);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
491 this->require_c_string("\"");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
492 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
493 this->require_c_string("\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
494
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
495 Package* p = this->gogo_->register_package(pkgpath, "",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
496 Linemap::unknown_location());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
497 p->set_package_name(package_name, this->location());
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
498
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
499 this->packages_.push_back(p);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
500 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
501
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
502 // Read an indirectimport line.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
503
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
504 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
505 Import::read_one_indirect_import()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
506 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
507 this->require_c_string("indirectimport ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
508 std::string package_name = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
509 this->require_c_string(" ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
510 std::string pkgpath = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
511 this->require_c_string("\n");
111
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 Package* p = this->gogo_->register_package(pkgpath, "",
kono
parents:
diff changeset
514 Linemap::unknown_location());
kono
parents:
diff changeset
515 p->set_package_name(package_name, this->location());
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 this->packages_.push_back(p);
111
kono
parents:
diff changeset
518 }
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 // Read the list of import control functions and/or init graph.
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 void
kono
parents:
diff changeset
523 Import::read_import_init_fns(Gogo* gogo)
kono
parents:
diff changeset
524 {
kono
parents:
diff changeset
525 this->require_c_string("init");
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 // Maps init function to index in the "init" clause; needed
kono
parents:
diff changeset
528 // to read the init_graph section.
kono
parents:
diff changeset
529 std::map<std::string, unsigned> init_idx;
kono
parents:
diff changeset
530
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
531 while (!this->match_c_string("\n") && !this->match_c_string(";"))
111
kono
parents:
diff changeset
532 {
kono
parents:
diff changeset
533 int priority = -1;
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 this->require_c_string(" ");
kono
parents:
diff changeset
536 std::string package_name = this->read_identifier();
kono
parents:
diff changeset
537 this->require_c_string(" ");
kono
parents:
diff changeset
538 std::string init_name = this->read_identifier();
kono
parents:
diff changeset
539 if (this->version_ == EXPORT_FORMAT_V1)
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 // Older version 1 init fcn export data format is:
kono
parents:
diff changeset
542 //
kono
parents:
diff changeset
543 // <packname> <fcn> <priority>
kono
parents:
diff changeset
544 this->require_c_string(" ");
kono
parents:
diff changeset
545 std::string prio_string = this->read_identifier();
kono
parents:
diff changeset
546 if (!this->string_to_int(prio_string, false, &priority))
kono
parents:
diff changeset
547 return;
kono
parents:
diff changeset
548 }
kono
parents:
diff changeset
549 gogo->add_import_init_fn(package_name, init_name, priority);
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 // Record the index of this init fcn so that we can look it
kono
parents:
diff changeset
552 // up by index in the subsequent init_graph section.
kono
parents:
diff changeset
553 unsigned idx = init_idx.size();
kono
parents:
diff changeset
554 init_idx[init_name] = idx;
kono
parents:
diff changeset
555 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
556 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
557 this->require_c_string("\n");
111
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 if (this->match_c_string("init_graph"))
kono
parents:
diff changeset
560 {
kono
parents:
diff changeset
561 this->require_c_string("init_graph");
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 // Build a vector mapping init fcn slot to Import_init pointer.
kono
parents:
diff changeset
564 go_assert(init_idx.size() > 0);
kono
parents:
diff changeset
565 std::vector<Import_init*> import_initvec;
kono
parents:
diff changeset
566 import_initvec.resize(init_idx.size());
kono
parents:
diff changeset
567 for (std::map<std::string, unsigned>::const_iterator it =
kono
parents:
diff changeset
568 init_idx.begin();
kono
parents:
diff changeset
569 it != init_idx.end(); ++it)
kono
parents:
diff changeset
570 {
kono
parents:
diff changeset
571 const std::string& init_name = it->first;
kono
parents:
diff changeset
572 Import_init* ii = gogo->lookup_init(init_name);
kono
parents:
diff changeset
573 import_initvec[it->second] = ii;
kono
parents:
diff changeset
574 }
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 // Init graph format is:
kono
parents:
diff changeset
577 //
kono
parents:
diff changeset
578 // init_graph <src1> <sink1> <src2> <sink2> ... ;
kono
parents:
diff changeset
579 //
kono
parents:
diff changeset
580 // where src + sink are init functions indices.
kono
parents:
diff changeset
581
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
582 while (!this->match_c_string("\n") && !this->match_c_string(";"))
111
kono
parents:
diff changeset
583 {
kono
parents:
diff changeset
584 this->require_c_string(" ");
kono
parents:
diff changeset
585 std::string src_string = this->read_identifier();
kono
parents:
diff changeset
586 unsigned src;
kono
parents:
diff changeset
587 if (!this->string_to_unsigned(src_string, &src)) return;
kono
parents:
diff changeset
588
kono
parents:
diff changeset
589 this->require_c_string(" ");
kono
parents:
diff changeset
590 std::string sink_string = this->read_identifier();
kono
parents:
diff changeset
591 unsigned sink;
kono
parents:
diff changeset
592 if (!this->string_to_unsigned(sink_string, &sink)) return;
kono
parents:
diff changeset
593
kono
parents:
diff changeset
594 go_assert(src < import_initvec.size());
kono
parents:
diff changeset
595 Import_init* ii_src = import_initvec[src];
kono
parents:
diff changeset
596 go_assert(sink < import_initvec.size());
kono
parents:
diff changeset
597 Import_init* ii_sink = import_initvec[sink];
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 ii_src->record_precursor_fcn(ii_sink->init_name());
kono
parents:
diff changeset
600 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
601 this->require_semicolon_if_old_version();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
602 this->require_c_string("\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
603 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
604 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
605
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
606 // Import the types. Starting in export format version 3 all the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
607 // types are listed first.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
608
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
609 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
610 Import::read_types()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
611 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
612 this->require_c_string("types ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
613 std::string str = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
614 int maxp1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
615 if (!this->string_to_int(str, false, &maxp1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
616 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
617
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
618 this->require_c_string(" ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
619 str = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
620 int exportedp1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
621 if (!this->string_to_int(str, false, &exportedp1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
622 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
623
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
624 this->type_offsets_.resize(maxp1, std::make_pair<size_t, size_t>(0, 0));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
625 size_t total_type_size = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
626 // Start at 1 because type index 0 not used.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
627 for (int i = 1; i < maxp1; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
628 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
629 this->require_c_string(" ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
630 str = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
631 int v;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
632 if (!this->string_to_int(str, false, &v))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
633 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
634 size_t vs = static_cast<size_t>(v);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
635 this->type_offsets_[i] = std::make_pair(total_type_size, vs);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
636 total_type_size += vs;
111
kono
parents:
diff changeset
637 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
639 this->require_c_string("\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
640
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
641 // Types can refer to each other in an unpredictable order. Read
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
642 // all the type data into type_data_. The type_offsets_ vector we
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
643 // just initialized provides indexes into type_data_.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
644
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
645 this->type_pos_ = this->stream_->pos();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
646 const char* type_data;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
647 if (!this->stream_->peek(total_type_size, &type_data))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
648 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
649 this->type_data_ = std::string(type_data, total_type_size);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
650 this->advance(total_type_size);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
651
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
652 this->types_.resize(maxp1, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
653
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
654 // Parse all the exported types now, so that the names are properly
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
655 // bound and visible to the parser. Parse unexported types lazily.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
656
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
657 // Start at 1 because there is no type 0.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
658 for (int i = 1; i < exportedp1; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
659 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
660 // We may have already parsed this type when we parsed an
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
661 // earlier type.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
662 Type* type = this->types_[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
663 if (type == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
664 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
665 if (!this->parse_type(i))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
666 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
667 type = this->types_[i];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
668 go_assert(type != NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
669 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
670 Named_type* nt = type->named_type();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
671 if (nt == NULL)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
672 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
673 go_error_at(this->location_,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
674 "error in import data: exported unnamed type %d",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
675 i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
676 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
677 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
678 nt->set_is_visible();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
679 if (this->add_to_globals_)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
680 this->gogo_->add_named_type(nt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
681 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
682
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
683 return true;
111
kono
parents:
diff changeset
684 }
kono
parents:
diff changeset
685
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
686 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
687 Import::finalize_methods()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
688 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
689 Finalize_methods finalizer(this->gogo_);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
690 Unordered_set(Type*) real_for_named;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
691 for (size_t i = 1; i < this->types_.size(); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
692 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
693 Type* type = this->types_[i];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
694 if (type != NULL && type->named_type() != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
695 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
696 finalizer.type(type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
697
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
698 // If the real type is a struct type, we don't want to
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
699 // finalize its methods. For a named type defined as a
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
700 // struct type, we only want to finalize the methods of the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
701 // named type. This is like Finalize_methods::type.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
702 Type* real_type = type->named_type()->real_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
703 if (real_type->struct_type() != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
704 real_for_named.insert(real_type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
705 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
706 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
707 for (size_t i = 1; i < this->types_.size(); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
708 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
709 Type* type = this->types_[i];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
710 if (type != NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
711 && type->named_type() == NULL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
712 && real_for_named.find(type) == real_for_named.end())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
713 finalizer.type(type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
714 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
715 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
716
111
kono
parents:
diff changeset
717 // Import a constant.
kono
parents:
diff changeset
718
kono
parents:
diff changeset
719 void
kono
parents:
diff changeset
720 Import::import_const()
kono
parents:
diff changeset
721 {
kono
parents:
diff changeset
722 std::string name;
kono
parents:
diff changeset
723 Type* type;
kono
parents:
diff changeset
724 Expression* expr;
kono
parents:
diff changeset
725 Named_constant::import_const(this, &name, &type, &expr);
kono
parents:
diff changeset
726 Typed_identifier tid(name, type, this->location_);
kono
parents:
diff changeset
727 Named_object* no = this->package_->add_constant(tid, expr);
kono
parents:
diff changeset
728 if (this->add_to_globals_)
kono
parents:
diff changeset
729 this->gogo_->add_dot_import_object(no);
kono
parents:
diff changeset
730 }
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 // Import a type.
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 void
kono
parents:
diff changeset
735 Import::import_type()
kono
parents:
diff changeset
736 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
737 if (this->version_ >= EXPORT_FORMAT_V3)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
738 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
739 if (!this->stream_->saw_error())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
740 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
741 go_error_at(this->location_,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
742 "error in import data at %d: old type syntax",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
743 this->stream_->pos());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
744 this->stream_->set_saw_error();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
745 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
746 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
747 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
748
111
kono
parents:
diff changeset
749 Named_type* type;
kono
parents:
diff changeset
750 Named_type::import_named_type(this, &type);
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 // The named type has been added to the package by the type import
kono
parents:
diff changeset
753 // process. Here we need to make it visible to the parser, and it
kono
parents:
diff changeset
754 // to the global bindings if necessary.
kono
parents:
diff changeset
755 type->set_is_visible();
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 if (this->add_to_globals_)
kono
parents:
diff changeset
758 this->gogo_->add_named_type(type);
kono
parents:
diff changeset
759 }
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 // Import a variable.
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 void
kono
parents:
diff changeset
764 Import::import_var()
kono
parents:
diff changeset
765 {
kono
parents:
diff changeset
766 std::string name;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
767 Package* vpkg;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
768 bool is_exported;
111
kono
parents:
diff changeset
769 Type* type;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
770 if (!Variable::import_var(this, &name, &vpkg, &is_exported, &type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
771 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
772 if (vpkg == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
773 vpkg = this->package_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
774 if (!is_exported)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
775 name = '.' + vpkg->pkgpath() + '.' + name;
111
kono
parents:
diff changeset
776 Variable* var = new Variable(type, NULL, true, false, false,
kono
parents:
diff changeset
777 this->location_);
kono
parents:
diff changeset
778 Named_object* no;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
779 no = vpkg->add_variable(name, var);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
780 if (this->add_to_globals_ && vpkg == this->package_)
111
kono
parents:
diff changeset
781 this->gogo_->add_dot_import_object(no);
kono
parents:
diff changeset
782 }
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 // Import a function into PACKAGE. PACKAGE is normally
kono
parents:
diff changeset
785 // THIS->PACKAGE_, but it will be different for a method associated
kono
parents:
diff changeset
786 // with a type defined in a different package.
kono
parents:
diff changeset
787
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
788 void
111
kono
parents:
diff changeset
789 Import::import_func(Package* package)
kono
parents:
diff changeset
790 {
kono
parents:
diff changeset
791 std::string name;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
792 Package* fpkg;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
793 bool is_exported;
111
kono
parents:
diff changeset
794 Typed_identifier* receiver;
kono
parents:
diff changeset
795 Typed_identifier_list* parameters;
kono
parents:
diff changeset
796 Typed_identifier_list* results;
kono
parents:
diff changeset
797 bool is_varargs;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
798 bool nointerface;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
799 std::string asm_name;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
800 std::string body;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
801 if (!Function::import_func(this, &name, &fpkg, &is_exported, &receiver,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
802 &parameters, &results, &is_varargs, &nointerface,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
803 &asm_name, &body))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
804 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
805 if (fpkg == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
806 fpkg = package;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
807 if (!is_exported)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
808 name = '.' + fpkg->pkgpath() + '.' + name;
111
kono
parents:
diff changeset
809 Function_type *fntype = Type::make_function_type(receiver, parameters,
kono
parents:
diff changeset
810 results, this->location_);
kono
parents:
diff changeset
811 if (is_varargs)
kono
parents:
diff changeset
812 fntype->set_is_varargs();
kono
parents:
diff changeset
813
kono
parents:
diff changeset
814 Location loc = this->location_;
kono
parents:
diff changeset
815 Named_object* no;
kono
parents:
diff changeset
816 if (fntype->is_method())
kono
parents:
diff changeset
817 {
kono
parents:
diff changeset
818 Type* rtype = receiver->type();
kono
parents:
diff changeset
819
kono
parents:
diff changeset
820 // We may still be reading the definition of RTYPE, so we have
kono
parents:
diff changeset
821 // to be careful to avoid calling base or convert. If RTYPE is
kono
parents:
diff changeset
822 // a named type or a forward declaration, then we know that it
kono
parents:
diff changeset
823 // is not a pointer, because we are reading a method on RTYPE
kono
parents:
diff changeset
824 // and named pointers can't have methods.
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 if (rtype->classification() == Type::TYPE_POINTER)
kono
parents:
diff changeset
827 rtype = rtype->points_to();
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 if (rtype->is_error_type())
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
830 return;
111
kono
parents:
diff changeset
831 else if (rtype->named_type() != NULL)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
832 no = rtype->named_type()->add_method_declaration(name, fpkg, fntype,
111
kono
parents:
diff changeset
833 loc);
kono
parents:
diff changeset
834 else if (rtype->forward_declaration_type() != NULL)
kono
parents:
diff changeset
835 no = rtype->forward_declaration_type()->add_method_declaration(name,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
836 fpkg,
111
kono
parents:
diff changeset
837 fntype,
kono
parents:
diff changeset
838 loc);
kono
parents:
diff changeset
839 else
kono
parents:
diff changeset
840 go_unreachable();
kono
parents:
diff changeset
841 }
kono
parents:
diff changeset
842 else
kono
parents:
diff changeset
843 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
844 no = fpkg->add_function_declaration(name, fntype, loc);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
845 if (this->add_to_globals_ && fpkg == package)
111
kono
parents:
diff changeset
846 this->gogo_->add_dot_import_object(no);
kono
parents:
diff changeset
847 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
848
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
849 if (nointerface)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
850 no->func_declaration_value()->set_nointerface();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
851 if (!asm_name.empty())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
852 no->func_declaration_value()->set_asm_name(asm_name);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
853 if (!body.empty() && !no->func_declaration_value()->has_imported_body())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
854 no->func_declaration_value()->set_imported_body(this, body);
111
kono
parents:
diff changeset
855 }
kono
parents:
diff changeset
856
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
857 // Read a type definition and initialize the entry in this->types_.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
858 // This parses the type definition saved by read_types earlier. This
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
859 // returns true on success, false on failure.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
860
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
861 bool
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
862 Import::parse_type(int i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
863 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
864 go_assert(i >= 0 && static_cast<size_t>(i) < this->types_.size());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
865 go_assert(this->types_[i] == NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
866 size_t offset = this->type_offsets_[i].first;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
867 size_t len = this->type_offsets_[i].second;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
868
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
869 Stream* orig_stream = this->stream_;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
870
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
871 Stream_from_string_ref stream(this->type_data_, offset, len);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
872 stream.set_pos(this->type_pos_ + offset);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
873 this->stream_ = &stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
874
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
875 this->require_c_string("type ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
876 std::string str = this->read_identifier();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
877 int id;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
878 if (!this->string_to_int(str, false, &id))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
879 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
880 this->stream_ = orig_stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
881 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
882 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
883 if (i != id)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
884 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
885 go_error_at(this->location_,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
886 ("error in import data at %d: "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
887 "type ID mismatch: got %d, want %d"),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
888 stream.pos(), id, i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
889 this->stream_ = orig_stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
890 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
891 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
892
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
893 this->require_c_string(" ");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
894 if (stream.peek_char() == '"')
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
895 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
896 stream.advance(1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
897 Type* type = this->read_named_type(i);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
898 if (type->is_error_type())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
899 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
900 this->stream_ = orig_stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
901 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
902 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
903 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
904 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906 Type* type = Type::import_type(this);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
907 if (type->is_error_type())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
908 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 this->stream_ = orig_stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
911 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
912 this->types_[i] = type;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
913
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
914 this->require_c_string("\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
915 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
916
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
917 this->stream_ = orig_stream;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
918 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
919 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920
111
kono
parents:
diff changeset
921 // Read a type in the import stream. This records the type by the
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
922 // type index. If the type is named (which can only happen with older
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
923 // export formats), it registers the name, but marks it as invisible.
111
kono
parents:
diff changeset
924
kono
parents:
diff changeset
925 Type*
kono
parents:
diff changeset
926 Import::read_type()
kono
parents:
diff changeset
927 {
kono
parents:
diff changeset
928 Stream* stream = this->stream_;
kono
parents:
diff changeset
929 this->require_c_string("<type ");
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 std::string number;
kono
parents:
diff changeset
932 int c;
kono
parents:
diff changeset
933 while (true)
kono
parents:
diff changeset
934 {
kono
parents:
diff changeset
935 c = stream->get_char();
kono
parents:
diff changeset
936 if (c != '-' && (c < '0' || c > '9'))
kono
parents:
diff changeset
937 break;
kono
parents:
diff changeset
938 number += c;
kono
parents:
diff changeset
939 }
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 int index;
kono
parents:
diff changeset
942 if (!this->string_to_int(number, true, &index))
kono
parents:
diff changeset
943 return Type::make_error_type();
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 if (c == '>')
kono
parents:
diff changeset
946 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
947 // A reference to a type defined earlier.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
948 bool parsed;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
949 return this->type_for_index(index, "import data", stream->pos(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
950 &parsed);
111
kono
parents:
diff changeset
951 }
kono
parents:
diff changeset
952
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
953 if (this->version_ >= EXPORT_FORMAT_V3)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
954 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
955 if (!stream->saw_error())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
956 go_error_at(this->location_,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
957 "error in import data at %d: expected %<>%>",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
958 stream->pos());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
959 stream->set_saw_error();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
960 return Type::make_error_type();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
961 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
962
111
kono
parents:
diff changeset
963 if (c != ' ')
kono
parents:
diff changeset
964 {
kono
parents:
diff changeset
965 if (!stream->saw_error())
kono
parents:
diff changeset
966 go_error_at(this->location_,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
967 "error in import data at %d: expected %< %> or %<>%>",
111
kono
parents:
diff changeset
968 stream->pos());
kono
parents:
diff changeset
969 stream->set_saw_error();
kono
parents:
diff changeset
970 stream->advance(1);
kono
parents:
diff changeset
971 return Type::make_error_type();
kono
parents:
diff changeset
972 }
kono
parents:
diff changeset
973
kono
parents:
diff changeset
974 if (index <= 0
kono
parents:
diff changeset
975 || (static_cast<size_t>(index) < this->types_.size()
kono
parents:
diff changeset
976 && this->types_[index] != NULL))
kono
parents:
diff changeset
977 {
kono
parents:
diff changeset
978 go_error_at(this->location_,
kono
parents:
diff changeset
979 "error in import data at %d: type index already defined",
kono
parents:
diff changeset
980 stream->pos());
kono
parents:
diff changeset
981 stream->set_saw_error();
kono
parents:
diff changeset
982 return Type::make_error_type();
kono
parents:
diff changeset
983 }
kono
parents:
diff changeset
984
kono
parents:
diff changeset
985 if (static_cast<size_t>(index) >= this->types_.size())
kono
parents:
diff changeset
986 {
kono
parents:
diff changeset
987 int newsize = std::max(static_cast<size_t>(index) + 1,
kono
parents:
diff changeset
988 this->types_.size() * 2);
kono
parents:
diff changeset
989 this->types_.resize(newsize, NULL);
kono
parents:
diff changeset
990 }
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 if (stream->peek_char() != '"')
kono
parents:
diff changeset
993 {
kono
parents:
diff changeset
994 Type* type = Type::import_type(this);
kono
parents:
diff changeset
995 this->require_c_string(">");
kono
parents:
diff changeset
996 this->types_[index] = type;
kono
parents:
diff changeset
997 return type;
kono
parents:
diff changeset
998 }
kono
parents:
diff changeset
999
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1000 stream->advance(1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1001
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1002 Type* type = this->read_named_type(index);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1003
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1004 this->require_c_string(">");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1005
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1006 return type;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1007 }
111
kono
parents:
diff changeset
1008
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1009 // Read a named type from the import stream and store it in
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1010 // this->types_[index]. The stream should be positioned immediately
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1011 // after the '"' that starts the name.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1012
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1013 Type*
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1014 Import::read_named_type(int index)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1015 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1016 Stream* stream = this->stream_;
111
kono
parents:
diff changeset
1017 std::string type_name;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1018 int c;
111
kono
parents:
diff changeset
1019 while ((c = stream->get_char()) != '"')
kono
parents:
diff changeset
1020 type_name += c;
kono
parents:
diff changeset
1021
kono
parents:
diff changeset
1022 // If this type is in the package we are currently importing, the
kono
parents:
diff changeset
1023 // name will be .PKGPATH.NAME or simply NAME with no dots.
kono
parents:
diff changeset
1024 // Otherwise, a non-hidden symbol will be PKGPATH.NAME and a hidden
kono
parents:
diff changeset
1025 // symbol will be .PKGPATH.NAME.
kono
parents:
diff changeset
1026 std::string pkgpath;
kono
parents:
diff changeset
1027 if (type_name.find('.') != std::string::npos)
kono
parents:
diff changeset
1028 {
kono
parents:
diff changeset
1029 size_t start = 0;
kono
parents:
diff changeset
1030 if (type_name[0] == '.')
kono
parents:
diff changeset
1031 start = 1;
kono
parents:
diff changeset
1032 size_t dot = type_name.rfind('.');
kono
parents:
diff changeset
1033 pkgpath = type_name.substr(start, dot - start);
kono
parents:
diff changeset
1034 if (type_name[0] != '.')
kono
parents:
diff changeset
1035 type_name.erase(0, dot + 1);
kono
parents:
diff changeset
1036 }
kono
parents:
diff changeset
1037
kono
parents:
diff changeset
1038 this->require_c_string(" ");
kono
parents:
diff changeset
1039
kono
parents:
diff changeset
1040 // The package name may follow. This is the name of the package in
kono
parents:
diff changeset
1041 // the package clause of that package. The type name will include
kono
parents:
diff changeset
1042 // the pkgpath, which may be different.
kono
parents:
diff changeset
1043 std::string package_name;
kono
parents:
diff changeset
1044 if (stream->peek_char() == '"')
kono
parents:
diff changeset
1045 {
kono
parents:
diff changeset
1046 stream->advance(1);
kono
parents:
diff changeset
1047 while ((c = stream->get_char()) != '"')
kono
parents:
diff changeset
1048 package_name += c;
kono
parents:
diff changeset
1049 this->require_c_string(" ");
kono
parents:
diff changeset
1050 }
kono
parents:
diff changeset
1051
kono
parents:
diff changeset
1052 bool is_alias = false;
kono
parents:
diff changeset
1053 if (this->match_c_string("= "))
kono
parents:
diff changeset
1054 {
kono
parents:
diff changeset
1055 stream->advance(2);
kono
parents:
diff changeset
1056 is_alias = true;
kono
parents:
diff changeset
1057 }
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 // Declare the type in the appropriate package. If we haven't seen
kono
parents:
diff changeset
1060 // it before, mark it as invisible. We declare it before we read
kono
parents:
diff changeset
1061 // the actual definition of the type, since the definition may refer
kono
parents:
diff changeset
1062 // to the type itself.
kono
parents:
diff changeset
1063 Package* package;
kono
parents:
diff changeset
1064 if (pkgpath.empty() || pkgpath == this->gogo_->pkgpath())
kono
parents:
diff changeset
1065 package = this->package_;
kono
parents:
diff changeset
1066 else
kono
parents:
diff changeset
1067 {
kono
parents:
diff changeset
1068 package = this->gogo_->register_package(pkgpath, "",
kono
parents:
diff changeset
1069 Linemap::unknown_location());
kono
parents:
diff changeset
1070 if (!package_name.empty())
kono
parents:
diff changeset
1071 package->set_package_name(package_name, this->location());
kono
parents:
diff changeset
1072 }
kono
parents:
diff changeset
1073
kono
parents:
diff changeset
1074 Named_object* no = package->bindings()->lookup(type_name);
kono
parents:
diff changeset
1075 if (no == NULL)
kono
parents:
diff changeset
1076 no = package->add_type_declaration(type_name, this->location_);
kono
parents:
diff changeset
1077 else if (!no->is_type_declaration() && !no->is_type())
kono
parents:
diff changeset
1078 {
kono
parents:
diff changeset
1079 go_error_at(this->location_, "imported %<%s.%s%> both type and non-type",
kono
parents:
diff changeset
1080 pkgpath.c_str(), Gogo::message_name(type_name).c_str());
kono
parents:
diff changeset
1081 stream->set_saw_error();
kono
parents:
diff changeset
1082 return Type::make_error_type();
kono
parents:
diff changeset
1083 }
kono
parents:
diff changeset
1084 else
kono
parents:
diff changeset
1085 go_assert(no->package() == package);
kono
parents:
diff changeset
1086
kono
parents:
diff changeset
1087 if (this->types_[index] == NULL)
kono
parents:
diff changeset
1088 {
kono
parents:
diff changeset
1089 if (no->is_type_declaration())
kono
parents:
diff changeset
1090 {
kono
parents:
diff changeset
1091 // FIXME: It's silly to make a forward declaration every time.
kono
parents:
diff changeset
1092 this->types_[index] = Type::make_forward_declaration(no);
kono
parents:
diff changeset
1093 }
kono
parents:
diff changeset
1094 else
kono
parents:
diff changeset
1095 {
kono
parents:
diff changeset
1096 go_assert(no->is_type());
kono
parents:
diff changeset
1097 this->types_[index] = no->type_value();
kono
parents:
diff changeset
1098 }
kono
parents:
diff changeset
1099 }
kono
parents:
diff changeset
1100
kono
parents:
diff changeset
1101 // If there is no type definition, then this is just a forward
kono
parents:
diff changeset
1102 // declaration of a type defined in some other file.
kono
parents:
diff changeset
1103 Type* type;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1104 if (this->match_c_string(">") || this->match_c_string("\n"))
111
kono
parents:
diff changeset
1105 type = this->types_[index];
kono
parents:
diff changeset
1106 else
kono
parents:
diff changeset
1107 {
kono
parents:
diff changeset
1108 if (no->is_type_declaration())
kono
parents:
diff changeset
1109 {
kono
parents:
diff changeset
1110 // We can define the type now.
kono
parents:
diff changeset
1111
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1112 type = this->read_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1113
111
kono
parents:
diff changeset
1114 no = package->add_type(type_name, type, this->location_);
kono
parents:
diff changeset
1115 Named_type* ntype = no->type_value();
kono
parents:
diff changeset
1116
kono
parents:
diff changeset
1117 // This type has not yet been imported.
kono
parents:
diff changeset
1118 ntype->clear_is_visible();
kono
parents:
diff changeset
1119
kono
parents:
diff changeset
1120 if (is_alias)
kono
parents:
diff changeset
1121 ntype->set_is_alias();
kono
parents:
diff changeset
1122
kono
parents:
diff changeset
1123 if (!type->is_undefined() && type->interface_type() != NULL)
kono
parents:
diff changeset
1124 this->gogo_->record_interface_type(type->interface_type());
kono
parents:
diff changeset
1125
kono
parents:
diff changeset
1126 type = ntype;
kono
parents:
diff changeset
1127 }
kono
parents:
diff changeset
1128 else if (no->is_type())
kono
parents:
diff changeset
1129 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1130 // We have seen this type before.
111
kono
parents:
diff changeset
1131 type = no->type_value();
kono
parents:
diff changeset
1132
kono
parents:
diff changeset
1133 // Don't change the visibility of the existing type.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1134
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1135 // For older export versions, we need to skip the type
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1136 // definition in the stream.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1137 if (this->version_ < EXPORT_FORMAT_V3)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1138 this->read_type();
111
kono
parents:
diff changeset
1139 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1140 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1141 go_unreachable();
111
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 this->types_[index] = type;
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 // Read the type methods.
kono
parents:
diff changeset
1146 if (this->match_c_string("\n"))
kono
parents:
diff changeset
1147 {
kono
parents:
diff changeset
1148 this->advance(1);
kono
parents:
diff changeset
1149 while (this->match_c_string(" func"))
kono
parents:
diff changeset
1150 {
kono
parents:
diff changeset
1151 this->advance(1);
kono
parents:
diff changeset
1152 this->import_func(package);
kono
parents:
diff changeset
1153 }
kono
parents:
diff changeset
1154 }
kono
parents:
diff changeset
1155 }
kono
parents:
diff changeset
1156
kono
parents:
diff changeset
1157 return type;
kono
parents:
diff changeset
1158 }
kono
parents:
diff changeset
1159
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1160 // Return the type given an index. Set *PARSED if we parsed it here.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1161
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1162 Type*
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1163 Import::type_for_index(int index, const std::string& input_name,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1164 size_t input_offset, bool* parsed)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1165 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1166 *parsed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1167 if (index >= 0 && !this->type_data_.empty())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1168 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1169 if (static_cast<size_t>(index) >= this->type_offsets_.size())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1170 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1171 go_error_at(this->location_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1172 "error in %s at %lu: bad type index %d, max %d",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1173 input_name.c_str(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1174 static_cast<unsigned long>(input_offset),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1175 index, static_cast<int>(this->type_offsets_.size()));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1176 return Type::make_error_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1177 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1178
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1179 if (this->types_[index] == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1180 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1181 if (!this->parse_type(index))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1182 return Type::make_error_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1183 *parsed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1184 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1185 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1186
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1187 if (index < 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1188 ? (static_cast<size_t>(- index) >= this->builtin_types_.size()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1189 || this->builtin_types_[- index] == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1190 : (static_cast<size_t>(index) >= this->types_.size()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1191 || this->types_[index] == NULL))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1192 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1193 go_error_at(this->location_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1194 "error in %s at %lu: bad type index %d",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1195 input_name.c_str(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1196 static_cast<unsigned long>(input_offset), index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1197 return Type::make_error_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1198 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1199
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1200 return index < 0 ? this->builtin_types_[- index] : this->types_[index];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1201 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1202
111
kono
parents:
diff changeset
1203 // Read an escape note.
kono
parents:
diff changeset
1204
kono
parents:
diff changeset
1205 std::string
kono
parents:
diff changeset
1206 Import::read_escape()
kono
parents:
diff changeset
1207 {
kono
parents:
diff changeset
1208 if (this->match_c_string(" <esc:"))
kono
parents:
diff changeset
1209 {
kono
parents:
diff changeset
1210 Stream* stream = this->stream_;
kono
parents:
diff changeset
1211 this->require_c_string(" <esc:");
kono
parents:
diff changeset
1212
kono
parents:
diff changeset
1213 std::string escape = "esc:";
kono
parents:
diff changeset
1214 int c;
kono
parents:
diff changeset
1215 while (true)
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 c = stream->get_char();
kono
parents:
diff changeset
1218 if (c != 'x' && !ISXDIGIT(c))
kono
parents:
diff changeset
1219 break;
kono
parents:
diff changeset
1220 escape += c;
kono
parents:
diff changeset
1221 }
kono
parents:
diff changeset
1222
kono
parents:
diff changeset
1223 if (c != '>')
kono
parents:
diff changeset
1224 {
kono
parents:
diff changeset
1225 go_error_at(this->location(),
kono
parents:
diff changeset
1226 ("error in import data at %d: "
kono
parents:
diff changeset
1227 "expect %< %> or %<>%>, got %c"),
kono
parents:
diff changeset
1228 stream->pos(), c);
kono
parents:
diff changeset
1229 stream->set_saw_error();
kono
parents:
diff changeset
1230 stream->advance(1);
kono
parents:
diff changeset
1231 escape = Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
kono
parents:
diff changeset
1232 }
kono
parents:
diff changeset
1233 return escape;
kono
parents:
diff changeset
1234 }
kono
parents:
diff changeset
1235 else
kono
parents:
diff changeset
1236 return Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
kono
parents:
diff changeset
1237 }
kono
parents:
diff changeset
1238
kono
parents:
diff changeset
1239
kono
parents:
diff changeset
1240 // Register the builtin types.
kono
parents:
diff changeset
1241
kono
parents:
diff changeset
1242 void
kono
parents:
diff changeset
1243 Import::register_builtin_types(Gogo* gogo)
kono
parents:
diff changeset
1244 {
kono
parents:
diff changeset
1245 this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
kono
parents:
diff changeset
1246 this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
kono
parents:
diff changeset
1247 this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
kono
parents:
diff changeset
1248 this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
kono
parents:
diff changeset
1249 this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
kono
parents:
diff changeset
1250 this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
kono
parents:
diff changeset
1251 this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
kono
parents:
diff changeset
1252 this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
kono
parents:
diff changeset
1253 this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
kono
parents:
diff changeset
1254 this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
kono
parents:
diff changeset
1255 this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
kono
parents:
diff changeset
1256 this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
kono
parents:
diff changeset
1257 this->register_builtin_type(gogo, "int", BUILTIN_INT);
kono
parents:
diff changeset
1258 this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
kono
parents:
diff changeset
1259 this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
kono
parents:
diff changeset
1260 this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
kono
parents:
diff changeset
1261 this->register_builtin_type(gogo, "string", BUILTIN_STRING);
kono
parents:
diff changeset
1262 this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
kono
parents:
diff changeset
1263 this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
kono
parents:
diff changeset
1264 this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
kono
parents:
diff changeset
1265 }
kono
parents:
diff changeset
1266
kono
parents:
diff changeset
1267 // Register a single builtin type.
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 void
kono
parents:
diff changeset
1270 Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
kono
parents:
diff changeset
1271 {
kono
parents:
diff changeset
1272 Named_object* named_object = gogo->lookup_global(name);
kono
parents:
diff changeset
1273 go_assert(named_object != NULL && named_object->is_type());
kono
parents:
diff changeset
1274 int index = - static_cast<int>(code);
kono
parents:
diff changeset
1275 go_assert(index > 0
kono
parents:
diff changeset
1276 && static_cast<size_t>(index) < this->builtin_types_.size());
kono
parents:
diff changeset
1277 this->builtin_types_[index] = named_object->type_value();
kono
parents:
diff changeset
1278 }
kono
parents:
diff changeset
1279
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1280 // Characters that stop read_identifier. We base this on the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1281 // characters that stop an identifier, without worrying about
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1282 // characters that are permitted in an identifier. That lets us skip
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1283 // UTF-8 parsing.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1284 static const char * const identifier_stop = " \n;:,()[]";
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1285
111
kono
parents:
diff changeset
1286 // Read an identifier from the stream.
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288 std::string
kono
parents:
diff changeset
1289 Import::read_identifier()
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 std::string ret;
kono
parents:
diff changeset
1292 Stream* stream = this->stream_;
kono
parents:
diff changeset
1293 int c;
kono
parents:
diff changeset
1294 while (true)
kono
parents:
diff changeset
1295 {
kono
parents:
diff changeset
1296 c = stream->peek_char();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1297 if (c == -1 || strchr(identifier_stop, c) != NULL)
111
kono
parents:
diff changeset
1298 break;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1299
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1300 // FIXME: Probably we shouldn't accept '.', but that might break
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1301 // some existing imports.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1302 if (c == '.' && stream->match_c_string("..."))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1303 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1304
111
kono
parents:
diff changeset
1305 ret += c;
kono
parents:
diff changeset
1306 stream->advance(1);
kono
parents:
diff changeset
1307 }
kono
parents:
diff changeset
1308 return ret;
kono
parents:
diff changeset
1309 }
kono
parents:
diff changeset
1310
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1311 // Read a possibly qualified identifier from IMP. The qualification
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1312 // is <pID>, where ID is a package number. If the name has a leading
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1313 // '.', it is not exported; otherwise, it is. Set *NAME, *PKG and
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1314 // *IS_EXPORTED. Reports whether the read succeeded.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1315
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1316 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1317 Import::read_qualified_identifier(Import_expression* imp, std::string* name,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1318 Package** pkg, bool* is_exported)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1319 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1320 *pkg = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1321 if (imp->match_c_string("<p"))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1322 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1323 imp->advance(2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1324 char buf[50];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1325 char *pbuf = &buf[0];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1326 while (true)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1327 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1328 int next = imp->peek_char();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1329 if (next == -1 || static_cast<size_t>(pbuf - buf) >= sizeof buf - 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1330 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1331 if (next == '>')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1332 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1333 imp->advance(1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1334 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1335 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1336 *pbuf = static_cast<char>(next);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1337 ++pbuf;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1338 imp->advance(1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1339 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1340
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1341 *pbuf = '\0';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1342 char *end;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1343 long index = strtol(buf, &end, 10);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1344 if (*end != '\0'
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1345 || index <= 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1346 || static_cast<size_t>(index) > imp->max_package_index())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1347 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1348
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1349 *pkg = imp->package_at_index(index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1350 go_assert(*pkg != NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1351 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1352
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1353 *is_exported = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1354 if (imp->match_c_string("."))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1355 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1356 imp->advance(1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1357 *is_exported = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1358 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1359
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1360 *name = imp->read_identifier();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1361
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1362 return !name->empty();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1363 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1364
111
kono
parents:
diff changeset
1365 // Read a name from the stream.
kono
parents:
diff changeset
1366
kono
parents:
diff changeset
1367 std::string
kono
parents:
diff changeset
1368 Import::read_name()
kono
parents:
diff changeset
1369 {
kono
parents:
diff changeset
1370 std::string ret = this->read_identifier();
kono
parents:
diff changeset
1371 if (ret == "?")
kono
parents:
diff changeset
1372 ret.clear();
kono
parents:
diff changeset
1373 return ret;
kono
parents:
diff changeset
1374 }
kono
parents:
diff changeset
1375
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1376 // Read LENGTH bytes from the stream.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1377
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1378 std::string
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1379 Import::read(size_t length)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1380 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1381 const char* data;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1382 if (!this->stream_->peek(length, &data))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1383 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1384 if (!this->stream_->saw_error())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1385 go_error_at(this->location_, "import error at %d: expected %d bytes",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1386 this->stream_->pos(), static_cast<int>(length));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1387 this->stream_->set_saw_error();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1388 return "";
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1389 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1390 this->advance(length);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1391 return std::string(data, length);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1392 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1393
111
kono
parents:
diff changeset
1394 // Turn a string into a integer with appropriate error handling.
kono
parents:
diff changeset
1395
kono
parents:
diff changeset
1396 bool
kono
parents:
diff changeset
1397 Import::string_to_int(const std::string &s, bool is_neg_ok, int* ret)
kono
parents:
diff changeset
1398 {
kono
parents:
diff changeset
1399 char* end;
kono
parents:
diff changeset
1400 long prio = strtol(s.c_str(), &end, 10);
kono
parents:
diff changeset
1401 if (*end != '\0' || prio > 0x7fffffff || (prio < 0 && !is_neg_ok))
kono
parents:
diff changeset
1402 {
kono
parents:
diff changeset
1403 go_error_at(this->location_, "invalid integer in import data at %d",
kono
parents:
diff changeset
1404 this->stream_->pos());
kono
parents:
diff changeset
1405 this->stream_->set_saw_error();
kono
parents:
diff changeset
1406 return false;
kono
parents:
diff changeset
1407 }
kono
parents:
diff changeset
1408 *ret = prio;
kono
parents:
diff changeset
1409 return true;
kono
parents:
diff changeset
1410 }
kono
parents:
diff changeset
1411
kono
parents:
diff changeset
1412 // Class Import::Stream.
kono
parents:
diff changeset
1413
kono
parents:
diff changeset
1414 Import::Stream::Stream()
kono
parents:
diff changeset
1415 : pos_(0), saw_error_(false)
kono
parents:
diff changeset
1416 {
kono
parents:
diff changeset
1417 }
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 Import::Stream::~Stream()
kono
parents:
diff changeset
1420 {
kono
parents:
diff changeset
1421 }
kono
parents:
diff changeset
1422
kono
parents:
diff changeset
1423 // Return the next character to come from the stream.
kono
parents:
diff changeset
1424
kono
parents:
diff changeset
1425 int
kono
parents:
diff changeset
1426 Import::Stream::peek_char()
kono
parents:
diff changeset
1427 {
kono
parents:
diff changeset
1428 const char* read;
kono
parents:
diff changeset
1429 if (!this->do_peek(1, &read))
kono
parents:
diff changeset
1430 return -1;
kono
parents:
diff changeset
1431 // Make sure we return an unsigned char, so that we don't get
kono
parents:
diff changeset
1432 // confused by \xff.
kono
parents:
diff changeset
1433 unsigned char ret = *read;
kono
parents:
diff changeset
1434 return ret;
kono
parents:
diff changeset
1435 }
kono
parents:
diff changeset
1436
kono
parents:
diff changeset
1437 // Return true if the next LENGTH characters from the stream match
kono
parents:
diff changeset
1438 // BYTES
kono
parents:
diff changeset
1439
kono
parents:
diff changeset
1440 bool
kono
parents:
diff changeset
1441 Import::Stream::match_bytes(const char* bytes, size_t length)
kono
parents:
diff changeset
1442 {
kono
parents:
diff changeset
1443 const char* read;
kono
parents:
diff changeset
1444 if (!this->do_peek(length, &read))
kono
parents:
diff changeset
1445 return false;
kono
parents:
diff changeset
1446 return memcmp(bytes, read, length) == 0;
kono
parents:
diff changeset
1447 }
kono
parents:
diff changeset
1448
kono
parents:
diff changeset
1449 // Require that the next LENGTH bytes from the stream match BYTES.
kono
parents:
diff changeset
1450
kono
parents:
diff changeset
1451 void
kono
parents:
diff changeset
1452 Import::Stream::require_bytes(Location location, const char* bytes,
kono
parents:
diff changeset
1453 size_t length)
kono
parents:
diff changeset
1454 {
kono
parents:
diff changeset
1455 const char* read;
kono
parents:
diff changeset
1456 if (!this->do_peek(length, &read)
kono
parents:
diff changeset
1457 || memcmp(bytes, read, length) != 0)
kono
parents:
diff changeset
1458 {
kono
parents:
diff changeset
1459 if (!this->saw_error_)
kono
parents:
diff changeset
1460 go_error_at(location, "import error at %d: expected %<%.*s%>",
kono
parents:
diff changeset
1461 this->pos(), static_cast<int>(length), bytes);
kono
parents:
diff changeset
1462 this->saw_error_ = true;
kono
parents:
diff changeset
1463 return;
kono
parents:
diff changeset
1464 }
kono
parents:
diff changeset
1465 this->advance(length);
kono
parents:
diff changeset
1466 }
kono
parents:
diff changeset
1467
kono
parents:
diff changeset
1468 // Class Stream_from_file.
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 Stream_from_file::Stream_from_file(int fd)
kono
parents:
diff changeset
1471 : fd_(fd), data_()
kono
parents:
diff changeset
1472 {
kono
parents:
diff changeset
1473 if (lseek(fd, 0, SEEK_SET) != 0)
kono
parents:
diff changeset
1474 {
kono
parents:
diff changeset
1475 go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
kono
parents:
diff changeset
1476 this->set_saw_error();
kono
parents:
diff changeset
1477 }
kono
parents:
diff changeset
1478 }
kono
parents:
diff changeset
1479
kono
parents:
diff changeset
1480 Stream_from_file::~Stream_from_file()
kono
parents:
diff changeset
1481 {
kono
parents:
diff changeset
1482 close(this->fd_);
kono
parents:
diff changeset
1483 }
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 // Read next bytes.
kono
parents:
diff changeset
1486
kono
parents:
diff changeset
1487 bool
kono
parents:
diff changeset
1488 Stream_from_file::do_peek(size_t length, const char** bytes)
kono
parents:
diff changeset
1489 {
kono
parents:
diff changeset
1490 if (this->data_.length() <= length)
kono
parents:
diff changeset
1491 {
kono
parents:
diff changeset
1492 *bytes = this->data_.data();
kono
parents:
diff changeset
1493 return true;
kono
parents:
diff changeset
1494 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1495
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1496 this->data_.resize(length);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1497 ssize_t got = ::read(this->fd_, &this->data_[0], length);
111
kono
parents:
diff changeset
1498
kono
parents:
diff changeset
1499 if (got < 0)
kono
parents:
diff changeset
1500 {
kono
parents:
diff changeset
1501 if (!this->saw_error())
kono
parents:
diff changeset
1502 go_fatal_error(Linemap::unknown_location(), "read failed: %m");
kono
parents:
diff changeset
1503 this->set_saw_error();
kono
parents:
diff changeset
1504 return false;
kono
parents:
diff changeset
1505 }
kono
parents:
diff changeset
1506
kono
parents:
diff changeset
1507 if (lseek(this->fd_, - got, SEEK_CUR) != 0)
kono
parents:
diff changeset
1508 {
kono
parents:
diff changeset
1509 if (!this->saw_error())
kono
parents:
diff changeset
1510 go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
kono
parents:
diff changeset
1511 this->set_saw_error();
kono
parents:
diff changeset
1512 return false;
kono
parents:
diff changeset
1513 }
kono
parents:
diff changeset
1514
kono
parents:
diff changeset
1515 if (static_cast<size_t>(got) < length)
kono
parents:
diff changeset
1516 return false;
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 *bytes = this->data_.data();
kono
parents:
diff changeset
1519 return true;
kono
parents:
diff changeset
1520 }
kono
parents:
diff changeset
1521
kono
parents:
diff changeset
1522 // Advance.
kono
parents:
diff changeset
1523
kono
parents:
diff changeset
1524 void
kono
parents:
diff changeset
1525 Stream_from_file::do_advance(size_t skip)
kono
parents:
diff changeset
1526 {
kono
parents:
diff changeset
1527 if (lseek(this->fd_, skip, SEEK_CUR) != 0)
kono
parents:
diff changeset
1528 {
kono
parents:
diff changeset
1529 if (!this->saw_error())
kono
parents:
diff changeset
1530 go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
kono
parents:
diff changeset
1531 this->set_saw_error();
kono
parents:
diff changeset
1532 }
kono
parents:
diff changeset
1533 if (!this->data_.empty())
kono
parents:
diff changeset
1534 {
kono
parents:
diff changeset
1535 if (this->data_.length() < skip)
kono
parents:
diff changeset
1536 this->data_.erase(0, skip);
kono
parents:
diff changeset
1537 else
kono
parents:
diff changeset
1538 this->data_.clear();
kono
parents:
diff changeset
1539 }
kono
parents:
diff changeset
1540 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1541
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1542 // Class Import_function_body.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1543
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1544 Import_function_body::Import_function_body(Gogo* gogo,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1545 Import* imp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1546 Named_object* named_object,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1547 const std::string& body,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1548 size_t off,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1549 Block* block,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1550 int indent)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1551 : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1552 off_(off), indent_(indent), temporaries_(), labels_(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1553 saw_error_(false)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1554 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1555 this->blocks_.push_back(block);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1556 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1557
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1558 Import_function_body::~Import_function_body()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1559 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1560 // At this point we should be left with the original outer block only.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1561 go_assert(saw_errors() || this->blocks_.size() == 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1562 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1563
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1564 // The name of the function we are parsing.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1565
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1566 const std::string&
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1567 Import_function_body::name() const
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1568 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1569 return this->named_object_->name();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1570 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1571
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1572 // Class Import_function_body.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1573
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1574 // Require that the next bytes match STR, issuing an error if not.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1575 // Advance past the string.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1576
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1577 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1578 Import_function_body::require_c_string(const char* str)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1579 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1580 if (!this->match_c_string(str))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1581 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1582 if (!this->saw_error_)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1583 go_error_at(this->location(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1584 "invalid export data for %qs: expected %qs at %lu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1585 this->name().c_str(), str,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1586 static_cast<unsigned long>(this->off_));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1587 this->saw_error_ = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1588 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1589 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1590 this->advance(strlen(str));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1591 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1592
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1593 // Read an identifier.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1594
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1595 std::string
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1596 Import_function_body::read_identifier()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1597 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1598 size_t start = this->off_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1599 for (size_t i = start; i < this->body_.length(); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1600 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1601 int c = static_cast<unsigned char>(this->body_[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1602 if (strchr(identifier_stop, c) != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1603 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1604 this->off_ = i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1605 return this->body_.substr(start, i - start);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1606 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1607
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1608 // FIXME: Probably we shouldn't accept '.', but that might break
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1609 // some existing imports.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1610 if (c == '.'
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1611 && i + 2 < this->body_.length()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1612 && this->body_[i + 1] == '.'
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1613 && this->body_[i + 2] == '.')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1614 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1615 this->off_ = i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1616 return this->body_.substr(start, i - start);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1617 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1618 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1619 this->off_ = this->body_.length();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1620 return this->body_.substr(start);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1621 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1622
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1623 // Read a type.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1624
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1625 Type*
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1626 Import_function_body::read_type()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1627 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1628 this->require_c_string("<type ");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1629 size_t start = this->off_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1630 size_t i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1631 int c = '\0';
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1632 for (i = start; i < this->body_.length(); ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1633 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1634 c = static_cast<unsigned char>(this->body_[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1635 if (c != '-' && (c < '0' || c > '9'))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1636 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1637 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1638 this->off_ = i + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1639
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1640 char *end;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1641 std::string num = this->body_.substr(start, i - start);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1642 long val = strtol(num.c_str(), &end, 10);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1643 if (*end != '\0' || val > 0x7fffffff)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1644 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1645 if (!this->saw_error_)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1646 go_error_at(this->location(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1647 "invalid export data for %qs: expected integer at %lu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1648 this->name().c_str(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1649 static_cast<unsigned long>(start));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1650 this->saw_error_ = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1651 return Type::make_error_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1652 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1653
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1654 if (c != '>')
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1655 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1656 if (!this->saw_error_)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1657 go_error_at(this->location(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1658 "invalid export data for %qs: expected %<>%> at %lu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1659 this->name().c_str(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1660 static_cast<unsigned long>(i));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1661 this->saw_error_ = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1662 return Type::make_error_type();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1663 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1664
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1665 bool parsed;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1666 Type* type = this->imp_->type_for_index(static_cast<int>(val), this->name(),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1667 static_cast<unsigned long>(start),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1668 &parsed);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1669
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1670 // If we just read this type's information, its methods will not
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1671 // have been finalized. Do that now.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1672 if (parsed)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1673 this->gogo_->finalize_methods_for_type(type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1674
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1675 return type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1676 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1677
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1678 // Return the next size to use for a vector mapping indexes to values.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1679
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1680 size_t
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1681 Import_function_body::next_size(size_t have)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1682 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1683 if (have == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1684 return 8;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1685 else if (have < 256)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1686 return have * 2;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1687 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1688 return have + 64;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1689 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1690
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1691 // Record the index of a temporary statement.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1692
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1693 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1694 Import_function_body::record_temporary(Temporary_statement* temp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1695 unsigned int idx)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1696 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1697 size_t have = this->temporaries_.size();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1698 while (static_cast<size_t>(idx) >= have)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1699 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1700 size_t want = Import_function_body::next_size(have);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1701 this->temporaries_.resize(want, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1702 have = want;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1703 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1704 this->temporaries_[idx] = temp;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1705 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1706
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1707 // Return a temporary statement given an index.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1708
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1709 Temporary_statement*
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1710 Import_function_body::temporary_statement(unsigned int idx)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1711 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1712 if (static_cast<size_t>(idx) >= this->temporaries_.size())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1713 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1714 return this->temporaries_[idx];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1715 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1716
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1717 // Return an unnamed label given an index, defining the label if we
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1718 // haven't seen it already.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1719
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1720 Unnamed_label*
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1721 Import_function_body::unnamed_label(unsigned int idx, Location loc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1722 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1723 size_t have = this->labels_.size();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1724 while (static_cast<size_t>(idx) >= have)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1725 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1726 size_t want = Import_function_body::next_size(have);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1727 this->labels_.resize(want, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1728 have = want;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1729 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1730 Unnamed_label* label = this->labels_[idx];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1731 if (label == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1732 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1733 label = new Unnamed_label(loc);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1734 this->labels_[idx] = label;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1735 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1736 return label;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1737 }