1 |
714 |
jeremybenn |
// gogo.h -- Go frontend parsed representation. -*- C++ -*-
|
2 |
|
|
|
3 |
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
4 |
|
|
// Use of this source code is governed by a BSD-style
|
5 |
|
|
// license that can be found in the LICENSE file.
|
6 |
|
|
|
7 |
|
|
#ifndef GO_GOGO_H
|
8 |
|
|
#define GO_GOGO_H
|
9 |
|
|
|
10 |
|
|
#include "go-linemap.h"
|
11 |
|
|
|
12 |
|
|
class Traverse;
|
13 |
|
|
class Statement_inserter;
|
14 |
|
|
class Type;
|
15 |
|
|
class Type_hash_identical;
|
16 |
|
|
class Type_equal;
|
17 |
|
|
class Type_identical;
|
18 |
|
|
class Typed_identifier;
|
19 |
|
|
class Typed_identifier_list;
|
20 |
|
|
class Function_type;
|
21 |
|
|
class Expression;
|
22 |
|
|
class Statement;
|
23 |
|
|
class Temporary_statement;
|
24 |
|
|
class Block;
|
25 |
|
|
class Function;
|
26 |
|
|
class Bindings;
|
27 |
|
|
class Bindings_snapshot;
|
28 |
|
|
class Package;
|
29 |
|
|
class Variable;
|
30 |
|
|
class Pointer_type;
|
31 |
|
|
class Struct_type;
|
32 |
|
|
class Struct_field;
|
33 |
|
|
class Struct_field_list;
|
34 |
|
|
class Array_type;
|
35 |
|
|
class Map_type;
|
36 |
|
|
class Channel_type;
|
37 |
|
|
class Interface_type;
|
38 |
|
|
class Named_type;
|
39 |
|
|
class Forward_declaration_type;
|
40 |
|
|
class Method;
|
41 |
|
|
class Methods;
|
42 |
|
|
class Named_object;
|
43 |
|
|
class Label;
|
44 |
|
|
class Translate_context;
|
45 |
|
|
class Backend;
|
46 |
|
|
class Export;
|
47 |
|
|
class Import;
|
48 |
|
|
class Bexpression;
|
49 |
|
|
class Bstatement;
|
50 |
|
|
class Bblock;
|
51 |
|
|
class Bvariable;
|
52 |
|
|
class Blabel;
|
53 |
|
|
|
54 |
|
|
// This file declares the basic classes used to hold the internal
|
55 |
|
|
// representation of Go which is built by the parser.
|
56 |
|
|
|
57 |
|
|
// An initialization function for an imported package. This is a
|
58 |
|
|
// magic function which initializes variables and runs the "init"
|
59 |
|
|
// function.
|
60 |
|
|
|
61 |
|
|
class Import_init
|
62 |
|
|
{
|
63 |
|
|
public:
|
64 |
|
|
Import_init(const std::string& package_name, const std::string& init_name,
|
65 |
|
|
int priority)
|
66 |
|
|
: package_name_(package_name), init_name_(init_name), priority_(priority)
|
67 |
|
|
{ }
|
68 |
|
|
|
69 |
|
|
// The name of the package being imported.
|
70 |
|
|
const std::string&
|
71 |
|
|
package_name() const
|
72 |
|
|
{ return this->package_name_; }
|
73 |
|
|
|
74 |
|
|
// The name of the package's init function.
|
75 |
|
|
const std::string&
|
76 |
|
|
init_name() const
|
77 |
|
|
{ return this->init_name_; }
|
78 |
|
|
|
79 |
|
|
// The priority of the initialization function. Functions with a
|
80 |
|
|
// lower priority number must be run first.
|
81 |
|
|
int
|
82 |
|
|
priority() const
|
83 |
|
|
{ return this->priority_; }
|
84 |
|
|
|
85 |
|
|
private:
|
86 |
|
|
// The name of the package being imported.
|
87 |
|
|
std::string package_name_;
|
88 |
|
|
// The name of the package's init function.
|
89 |
|
|
std::string init_name_;
|
90 |
|
|
// The priority.
|
91 |
|
|
int priority_;
|
92 |
|
|
};
|
93 |
|
|
|
94 |
|
|
// For sorting purposes.
|
95 |
|
|
|
96 |
|
|
inline bool
|
97 |
|
|
operator<(const Import_init& i1, const Import_init& i2)
|
98 |
|
|
{
|
99 |
|
|
if (i1.priority() < i2.priority())
|
100 |
|
|
return true;
|
101 |
|
|
if (i1.priority() > i2.priority())
|
102 |
|
|
return false;
|
103 |
|
|
if (i1.package_name() != i2.package_name())
|
104 |
|
|
return i1.package_name() < i2.package_name();
|
105 |
|
|
return i1.init_name() < i2.init_name();
|
106 |
|
|
}
|
107 |
|
|
|
108 |
|
|
// The holder for the internal representation of the entire
|
109 |
|
|
// compilation unit.
|
110 |
|
|
|
111 |
|
|
class Gogo
|
112 |
|
|
{
|
113 |
|
|
public:
|
114 |
|
|
// Create the IR, passing in the sizes of the types "int" and
|
115 |
|
|
// "uintptr" in bits.
|
116 |
|
|
Gogo(Backend* backend, Linemap *linemap, int int_type_size, int pointer_size);
|
117 |
|
|
|
118 |
|
|
// Get the backend generator.
|
119 |
|
|
Backend*
|
120 |
|
|
backend()
|
121 |
|
|
{ return this->backend_; }
|
122 |
|
|
|
123 |
|
|
// Get the Location generator.
|
124 |
|
|
Linemap*
|
125 |
|
|
linemap()
|
126 |
|
|
{ return this->linemap_; }
|
127 |
|
|
|
128 |
|
|
// Get the package name.
|
129 |
|
|
const std::string&
|
130 |
|
|
package_name() const;
|
131 |
|
|
|
132 |
|
|
// Set the package name.
|
133 |
|
|
void
|
134 |
|
|
set_package_name(const std::string&, Location);
|
135 |
|
|
|
136 |
|
|
// Return whether this is the "main" package.
|
137 |
|
|
bool
|
138 |
|
|
is_main_package() const;
|
139 |
|
|
|
140 |
|
|
// If necessary, adjust the name to use for a hidden symbol. We add
|
141 |
|
|
// a prefix of the package name, so that hidden symbols in different
|
142 |
|
|
// packages do not collide.
|
143 |
|
|
std::string
|
144 |
|
|
pack_hidden_name(const std::string& name, bool is_exported) const
|
145 |
|
|
{
|
146 |
|
|
return (is_exported
|
147 |
|
|
? name
|
148 |
|
|
: ('.' + this->unique_prefix()
|
149 |
|
|
+ '.' + this->package_name()
|
150 |
|
|
+ '.' + name));
|
151 |
|
|
}
|
152 |
|
|
|
153 |
|
|
// Unpack a name which may have been hidden. Returns the
|
154 |
|
|
// user-visible name of the object.
|
155 |
|
|
static std::string
|
156 |
|
|
unpack_hidden_name(const std::string& name)
|
157 |
|
|
{ return name[0] != '.' ? name : name.substr(name.rfind('.') + 1); }
|
158 |
|
|
|
159 |
|
|
// Return whether a possibly packed name is hidden.
|
160 |
|
|
static bool
|
161 |
|
|
is_hidden_name(const std::string& name)
|
162 |
|
|
{ return name[0] == '.'; }
|
163 |
|
|
|
164 |
|
|
// Return the package prefix of a hidden name.
|
165 |
|
|
static std::string
|
166 |
|
|
hidden_name_prefix(const std::string& name)
|
167 |
|
|
{
|
168 |
|
|
go_assert(Gogo::is_hidden_name(name));
|
169 |
|
|
return name.substr(1, name.rfind('.') - 1);
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
// Given a name which may or may not have been hidden, return the
|
173 |
|
|
// name to use in an error message.
|
174 |
|
|
static std::string
|
175 |
|
|
message_name(const std::string& name);
|
176 |
|
|
|
177 |
|
|
// Return whether a name is the blank identifier _.
|
178 |
|
|
static bool
|
179 |
|
|
is_sink_name(const std::string& name)
|
180 |
|
|
{
|
181 |
|
|
return (name[0] == '.'
|
182 |
|
|
&& name[name.length() - 1] == '_'
|
183 |
|
|
&& name[name.length() - 2] == '.');
|
184 |
|
|
}
|
185 |
|
|
|
186 |
|
|
// Return the unique prefix to use for all exported symbols.
|
187 |
|
|
const std::string&
|
188 |
|
|
unique_prefix() const;
|
189 |
|
|
|
190 |
|
|
// Set the unique prefix.
|
191 |
|
|
void
|
192 |
|
|
set_unique_prefix(const std::string&);
|
193 |
|
|
|
194 |
|
|
// Return the priority to use for the package we are compiling.
|
195 |
|
|
// This is two more than the largest priority of any package we
|
196 |
|
|
// import.
|
197 |
|
|
int
|
198 |
|
|
package_priority() const;
|
199 |
|
|
|
200 |
|
|
// Import a package. FILENAME is the file name argument, LOCAL_NAME
|
201 |
|
|
// is the local name to give to the package. If LOCAL_NAME is empty
|
202 |
|
|
// the declarations are added to the global scope.
|
203 |
|
|
void
|
204 |
|
|
import_package(const std::string& filename, const std::string& local_name,
|
205 |
|
|
bool is_local_name_exported, Location);
|
206 |
|
|
|
207 |
|
|
// Whether we are the global binding level.
|
208 |
|
|
bool
|
209 |
|
|
in_global_scope() const;
|
210 |
|
|
|
211 |
|
|
// Look up a name in the current binding contours.
|
212 |
|
|
Named_object*
|
213 |
|
|
lookup(const std::string&, Named_object** pfunction) const;
|
214 |
|
|
|
215 |
|
|
// Look up a name in the current block.
|
216 |
|
|
Named_object*
|
217 |
|
|
lookup_in_block(const std::string&) const;
|
218 |
|
|
|
219 |
|
|
// Look up a name in the global namespace--the universal scope.
|
220 |
|
|
Named_object*
|
221 |
|
|
lookup_global(const char*) const;
|
222 |
|
|
|
223 |
|
|
// Add a new imported package. REAL_NAME is the real name of the
|
224 |
|
|
// package. ALIAS is the alias of the package; this may be the same
|
225 |
|
|
// as REAL_NAME. This sets *PADD_TO_GLOBALS if symbols added to
|
226 |
|
|
// this package should be added to the global namespace; this is
|
227 |
|
|
// true if the alias is ".". LOCATION is the location of the import
|
228 |
|
|
// statement. This returns the new package, or NULL on error.
|
229 |
|
|
Package*
|
230 |
|
|
add_imported_package(const std::string& real_name, const std::string& alias,
|
231 |
|
|
bool is_alias_exported,
|
232 |
|
|
const std::string& unique_prefix,
|
233 |
|
|
Location location,
|
234 |
|
|
bool* padd_to_globals);
|
235 |
|
|
|
236 |
|
|
// Register a package. This package may or may not be imported.
|
237 |
|
|
// This returns the Package structure for the package, creating if
|
238 |
|
|
// it necessary.
|
239 |
|
|
Package*
|
240 |
|
|
register_package(const std::string& name, const std::string& unique_prefix,
|
241 |
|
|
Location);
|
242 |
|
|
|
243 |
|
|
// Start compiling a function. ADD_METHOD_TO_TYPE is true if a
|
244 |
|
|
// method function should be added to the type of its receiver.
|
245 |
|
|
Named_object*
|
246 |
|
|
start_function(const std::string& name, Function_type* type,
|
247 |
|
|
bool add_method_to_type, Location);
|
248 |
|
|
|
249 |
|
|
// Finish compiling a function.
|
250 |
|
|
void
|
251 |
|
|
finish_function(Location);
|
252 |
|
|
|
253 |
|
|
// Return the current function.
|
254 |
|
|
Named_object*
|
255 |
|
|
current_function() const;
|
256 |
|
|
|
257 |
|
|
// Return the current block.
|
258 |
|
|
Block*
|
259 |
|
|
current_block();
|
260 |
|
|
|
261 |
|
|
// Start a new block. This is not initially associated with a
|
262 |
|
|
// function.
|
263 |
|
|
void
|
264 |
|
|
start_block(Location);
|
265 |
|
|
|
266 |
|
|
// Finish the current block and return it.
|
267 |
|
|
Block*
|
268 |
|
|
finish_block(Location);
|
269 |
|
|
|
270 |
|
|
// Declare an erroneous name. This is used to avoid knock-on errors
|
271 |
|
|
// after a parsing error.
|
272 |
|
|
Named_object*
|
273 |
|
|
add_erroneous_name(const std::string& name);
|
274 |
|
|
|
275 |
|
|
// Declare an unknown name. This is used while parsing. The name
|
276 |
|
|
// must be resolved by the end of the parse. Unknown names are
|
277 |
|
|
// always added at the package level.
|
278 |
|
|
Named_object*
|
279 |
|
|
add_unknown_name(const std::string& name, Location);
|
280 |
|
|
|
281 |
|
|
// Declare a function.
|
282 |
|
|
Named_object*
|
283 |
|
|
declare_function(const std::string&, Function_type*, Location);
|
284 |
|
|
|
285 |
|
|
// Declare a function at the package level. This is used for
|
286 |
|
|
// functions generated for a type.
|
287 |
|
|
Named_object*
|
288 |
|
|
declare_package_function(const std::string&, Function_type*, Location);
|
289 |
|
|
|
290 |
|
|
// Add a label.
|
291 |
|
|
Label*
|
292 |
|
|
add_label_definition(const std::string&, Location);
|
293 |
|
|
|
294 |
|
|
// Add a label reference. ISSUE_GOTO_ERRORS is true if we should
|
295 |
|
|
// report errors for a goto from the current location to the label
|
296 |
|
|
// location.
|
297 |
|
|
Label*
|
298 |
|
|
add_label_reference(const std::string&, Location,
|
299 |
|
|
bool issue_goto_errors);
|
300 |
|
|
|
301 |
|
|
// Return a snapshot of the current binding state.
|
302 |
|
|
Bindings_snapshot*
|
303 |
|
|
bindings_snapshot(Location);
|
304 |
|
|
|
305 |
|
|
// Add a statement to the current block.
|
306 |
|
|
void
|
307 |
|
|
add_statement(Statement*);
|
308 |
|
|
|
309 |
|
|
// Add a block to the current block.
|
310 |
|
|
void
|
311 |
|
|
add_block(Block*, Location);
|
312 |
|
|
|
313 |
|
|
// Add a constant.
|
314 |
|
|
Named_object*
|
315 |
|
|
add_constant(const Typed_identifier&, Expression*, int iota_value);
|
316 |
|
|
|
317 |
|
|
// Add a type.
|
318 |
|
|
void
|
319 |
|
|
add_type(const std::string&, Type*, Location);
|
320 |
|
|
|
321 |
|
|
// Add a named type. This is used for builtin types, and to add an
|
322 |
|
|
// imported type to the global scope.
|
323 |
|
|
void
|
324 |
|
|
add_named_type(Named_type*);
|
325 |
|
|
|
326 |
|
|
// Declare a type.
|
327 |
|
|
Named_object*
|
328 |
|
|
declare_type(const std::string&, Location);
|
329 |
|
|
|
330 |
|
|
// Declare a type at the package level. This is used when the
|
331 |
|
|
// parser sees an unknown name where a type name is required.
|
332 |
|
|
Named_object*
|
333 |
|
|
declare_package_type(const std::string&, Location);
|
334 |
|
|
|
335 |
|
|
// Define a type which was already declared.
|
336 |
|
|
void
|
337 |
|
|
define_type(Named_object*, Named_type*);
|
338 |
|
|
|
339 |
|
|
// Add a variable.
|
340 |
|
|
Named_object*
|
341 |
|
|
add_variable(const std::string&, Variable*);
|
342 |
|
|
|
343 |
|
|
// Add a sink--a reference to the blank identifier _.
|
344 |
|
|
Named_object*
|
345 |
|
|
add_sink();
|
346 |
|
|
|
347 |
|
|
// Add a type which needs to be verified. This is used for sink
|
348 |
|
|
// types, just to give appropriate error messages.
|
349 |
|
|
void
|
350 |
|
|
add_type_to_verify(Type* type);
|
351 |
|
|
|
352 |
|
|
// Add a named object to the current namespace. This is used for
|
353 |
|
|
// import . "package".
|
354 |
|
|
void
|
355 |
|
|
add_named_object(Named_object*);
|
356 |
|
|
|
357 |
|
|
// Mark all local variables in current bindings as used. This is
|
358 |
|
|
// used when there is a parse error to avoid useless errors.
|
359 |
|
|
void
|
360 |
|
|
mark_locals_used();
|
361 |
|
|
|
362 |
|
|
// Return a name to use for a thunk function. A thunk function is
|
363 |
|
|
// one we create during the compilation, for a go statement or a
|
364 |
|
|
// defer statement or a method expression.
|
365 |
|
|
static std::string
|
366 |
|
|
thunk_name();
|
367 |
|
|
|
368 |
|
|
// Return whether an object is a thunk.
|
369 |
|
|
static bool
|
370 |
|
|
is_thunk(const Named_object*);
|
371 |
|
|
|
372 |
|
|
// Note that we've seen an interface type. This is used to build
|
373 |
|
|
// all required interface method tables.
|
374 |
|
|
void
|
375 |
|
|
record_interface_type(Interface_type*);
|
376 |
|
|
|
377 |
|
|
// Note that we need an initialization function.
|
378 |
|
|
void
|
379 |
|
|
set_need_init_fn()
|
380 |
|
|
{ this->need_init_fn_ = true; }
|
381 |
|
|
|
382 |
|
|
// Clear out all names in file scope. This is called when we start
|
383 |
|
|
// parsing a new file.
|
384 |
|
|
void
|
385 |
|
|
clear_file_scope();
|
386 |
|
|
|
387 |
|
|
// Queue up a type-specific function to be written out. This is
|
388 |
|
|
// used when a type-specific function is needed when not at the top
|
389 |
|
|
// level.
|
390 |
|
|
void
|
391 |
|
|
queue_specific_type_function(Type* type, Named_type* name,
|
392 |
|
|
const std::string& hash_name,
|
393 |
|
|
Function_type* hash_fntype,
|
394 |
|
|
const std::string& equal_name,
|
395 |
|
|
Function_type* equal_fntype);
|
396 |
|
|
|
397 |
|
|
// Write out queued specific type functions.
|
398 |
|
|
void
|
399 |
|
|
write_specific_type_functions();
|
400 |
|
|
|
401 |
|
|
// Traverse the tree. See the Traverse class.
|
402 |
|
|
void
|
403 |
|
|
traverse(Traverse*);
|
404 |
|
|
|
405 |
|
|
// Define the predeclared global names.
|
406 |
|
|
void
|
407 |
|
|
define_global_names();
|
408 |
|
|
|
409 |
|
|
// Verify and complete all types.
|
410 |
|
|
void
|
411 |
|
|
verify_types();
|
412 |
|
|
|
413 |
|
|
// Lower the parse tree.
|
414 |
|
|
void
|
415 |
|
|
lower_parse_tree();
|
416 |
|
|
|
417 |
|
|
// Lower all the statements in a block.
|
418 |
|
|
void
|
419 |
|
|
lower_block(Named_object* function, Block*);
|
420 |
|
|
|
421 |
|
|
// Lower an expression.
|
422 |
|
|
void
|
423 |
|
|
lower_expression(Named_object* function, Statement_inserter*, Expression**);
|
424 |
|
|
|
425 |
|
|
// Lower a constant.
|
426 |
|
|
void
|
427 |
|
|
lower_constant(Named_object*);
|
428 |
|
|
|
429 |
|
|
// Finalize the method lists and build stub methods for named types.
|
430 |
|
|
void
|
431 |
|
|
finalize_methods();
|
432 |
|
|
|
433 |
|
|
// Work out the types to use for unspecified variables and
|
434 |
|
|
// constants.
|
435 |
|
|
void
|
436 |
|
|
determine_types();
|
437 |
|
|
|
438 |
|
|
// Type check the program.
|
439 |
|
|
void
|
440 |
|
|
check_types();
|
441 |
|
|
|
442 |
|
|
// Check the types in a single block. This is used for complicated
|
443 |
|
|
// go statements.
|
444 |
|
|
void
|
445 |
|
|
check_types_in_block(Block*);
|
446 |
|
|
|
447 |
|
|
// Check for return statements.
|
448 |
|
|
void
|
449 |
|
|
check_return_statements();
|
450 |
|
|
|
451 |
|
|
// Do all exports.
|
452 |
|
|
void
|
453 |
|
|
do_exports();
|
454 |
|
|
|
455 |
|
|
// Add an import control function for an imported package to the
|
456 |
|
|
// list.
|
457 |
|
|
void
|
458 |
|
|
add_import_init_fn(const std::string& package_name,
|
459 |
|
|
const std::string& init_name, int prio);
|
460 |
|
|
|
461 |
|
|
// Turn short-cut operators (&&, ||) into explicit if statements.
|
462 |
|
|
void
|
463 |
|
|
remove_shortcuts();
|
464 |
|
|
|
465 |
|
|
// Use temporary variables to force order of evaluation.
|
466 |
|
|
void
|
467 |
|
|
order_evaluations();
|
468 |
|
|
|
469 |
|
|
// Build thunks for functions which call recover.
|
470 |
|
|
void
|
471 |
|
|
build_recover_thunks();
|
472 |
|
|
|
473 |
|
|
// Simplify statements which might use thunks: go and defer
|
474 |
|
|
// statements.
|
475 |
|
|
void
|
476 |
|
|
simplify_thunk_statements();
|
477 |
|
|
|
478 |
|
|
// Dump AST if -fgo-dump-ast is set
|
479 |
|
|
void
|
480 |
|
|
dump_ast(const char* basename);
|
481 |
|
|
|
482 |
|
|
// Convert named types to the backend representation.
|
483 |
|
|
void
|
484 |
|
|
convert_named_types();
|
485 |
|
|
|
486 |
|
|
// Convert named types in a list of bindings.
|
487 |
|
|
void
|
488 |
|
|
convert_named_types_in_bindings(Bindings*);
|
489 |
|
|
|
490 |
|
|
// True if named types have been converted to the backend
|
491 |
|
|
// representation.
|
492 |
|
|
bool
|
493 |
|
|
named_types_are_converted() const
|
494 |
|
|
{ return this->named_types_are_converted_; }
|
495 |
|
|
|
496 |
|
|
// Write out the global values.
|
497 |
|
|
void
|
498 |
|
|
write_globals();
|
499 |
|
|
|
500 |
|
|
// Create trees for implicit builtin functions.
|
501 |
|
|
void
|
502 |
|
|
define_builtin_function_trees();
|
503 |
|
|
|
504 |
|
|
// Build a call to a builtin function. PDECL should point to a NULL
|
505 |
|
|
// initialized static pointer which will hold the fndecl. NAME is
|
506 |
|
|
// the name of the function. NARGS is the number of arguments.
|
507 |
|
|
// RETTYPE is the return type. It is followed by NARGS pairs of
|
508 |
|
|
// type and argument (both trees).
|
509 |
|
|
static tree
|
510 |
|
|
call_builtin(tree* pdecl, Location, const char* name, int nargs,
|
511 |
|
|
tree rettype, ...);
|
512 |
|
|
|
513 |
|
|
// Build a call to the runtime error function.
|
514 |
|
|
static tree
|
515 |
|
|
runtime_error(int code, Location);
|
516 |
|
|
|
517 |
|
|
// Build a builtin struct with a list of fields.
|
518 |
|
|
static tree
|
519 |
|
|
builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
|
520 |
|
|
int nfields, ...);
|
521 |
|
|
|
522 |
|
|
// Mark a function declaration as a builtin library function.
|
523 |
|
|
static void
|
524 |
|
|
mark_fndecl_as_builtin_library(tree fndecl);
|
525 |
|
|
|
526 |
|
|
// Build a constructor for a slice. SLICE_TYPE_TREE is the type of
|
527 |
|
|
// the slice. VALUES points to the values. COUNT is the size,
|
528 |
|
|
// CAPACITY is the capacity. If CAPACITY is NULL, it is set to
|
529 |
|
|
// COUNT.
|
530 |
|
|
static tree
|
531 |
|
|
slice_constructor(tree slice_type_tree, tree values, tree count,
|
532 |
|
|
tree capacity);
|
533 |
|
|
|
534 |
|
|
// Build required interface method tables.
|
535 |
|
|
void
|
536 |
|
|
build_interface_method_tables();
|
537 |
|
|
|
538 |
|
|
// Build an interface method table for a type: a list of function
|
539 |
|
|
// pointers, one for each interface method. This returns a decl.
|
540 |
|
|
tree
|
541 |
|
|
interface_method_table_for_type(const Interface_type*, Named_type*,
|
542 |
|
|
bool is_pointer);
|
543 |
|
|
|
544 |
|
|
// Return a tree which allocate SIZE bytes to hold values of type
|
545 |
|
|
// TYPE.
|
546 |
|
|
tree
|
547 |
|
|
allocate_memory(Type *type, tree size, Location);
|
548 |
|
|
|
549 |
|
|
// Return a type to use for pointer to const char.
|
550 |
|
|
static tree
|
551 |
|
|
const_char_pointer_type_tree();
|
552 |
|
|
|
553 |
|
|
// Build a string constant with the right type.
|
554 |
|
|
static tree
|
555 |
|
|
string_constant_tree(const std::string&);
|
556 |
|
|
|
557 |
|
|
// Build a Go string constant. This returns a pointer to the
|
558 |
|
|
// constant.
|
559 |
|
|
tree
|
560 |
|
|
go_string_constant_tree(const std::string&);
|
561 |
|
|
|
562 |
|
|
// Receive a value from a channel.
|
563 |
|
|
static tree
|
564 |
|
|
receive_from_channel(tree type_tree, tree type_descriptor_tree, tree channel,
|
565 |
|
|
Location);
|
566 |
|
|
|
567 |
|
|
// Make a trampoline which calls FNADDR passing CLOSURE.
|
568 |
|
|
tree
|
569 |
|
|
make_trampoline(tree fnaddr, tree closure, Location);
|
570 |
|
|
|
571 |
|
|
private:
|
572 |
|
|
// During parsing, we keep a stack of functions. Each function on
|
573 |
|
|
// the stack is one that we are currently parsing. For each
|
574 |
|
|
// function, we keep track of the current stack of blocks.
|
575 |
|
|
struct Open_function
|
576 |
|
|
{
|
577 |
|
|
// The function.
|
578 |
|
|
Named_object* function;
|
579 |
|
|
// The stack of active blocks in the function.
|
580 |
|
|
std::vector<Block*> blocks;
|
581 |
|
|
};
|
582 |
|
|
|
583 |
|
|
// The stack of functions.
|
584 |
|
|
typedef std::vector<Open_function> Open_functions;
|
585 |
|
|
|
586 |
|
|
// Set up the built-in unsafe package.
|
587 |
|
|
void
|
588 |
|
|
import_unsafe(const std::string&, bool is_exported, Location);
|
589 |
|
|
|
590 |
|
|
// Add a new imported package.
|
591 |
|
|
Named_object*
|
592 |
|
|
add_package(const std::string& real_name, const std::string& alias,
|
593 |
|
|
const std::string& unique_prefix, Location location);
|
594 |
|
|
|
595 |
|
|
// Return the current binding contour.
|
596 |
|
|
Bindings*
|
597 |
|
|
current_bindings();
|
598 |
|
|
|
599 |
|
|
const Bindings*
|
600 |
|
|
current_bindings() const;
|
601 |
|
|
|
602 |
|
|
// Get the name of the magic initialization function.
|
603 |
|
|
const std::string&
|
604 |
|
|
get_init_fn_name();
|
605 |
|
|
|
606 |
|
|
// Get the decl for the magic initialization function.
|
607 |
|
|
tree
|
608 |
|
|
initialization_function_decl();
|
609 |
|
|
|
610 |
|
|
// Write the magic initialization function.
|
611 |
|
|
void
|
612 |
|
|
write_initialization_function(tree fndecl, tree init_stmt_list);
|
613 |
|
|
|
614 |
|
|
// Initialize imported packages.
|
615 |
|
|
void
|
616 |
|
|
init_imports(tree*);
|
617 |
|
|
|
618 |
|
|
// Register variables with the garbage collector.
|
619 |
|
|
void
|
620 |
|
|
register_gc_vars(const std::vector<Named_object*>&, tree*);
|
621 |
|
|
|
622 |
|
|
// Build a pointer to a Go string constant. This returns a pointer
|
623 |
|
|
// to the pointer.
|
624 |
|
|
tree
|
625 |
|
|
ptr_go_string_constant_tree(const std::string&);
|
626 |
|
|
|
627 |
|
|
// Return the type of a trampoline.
|
628 |
|
|
static tree
|
629 |
|
|
trampoline_type_tree();
|
630 |
|
|
|
631 |
|
|
// Type used to map import names to packages.
|
632 |
|
|
typedef std::map<std::string, Package*> Imports;
|
633 |
|
|
|
634 |
|
|
// Type used to map package names to packages.
|
635 |
|
|
typedef std::map<std::string, Package*> Packages;
|
636 |
|
|
|
637 |
|
|
// Type used to map special names in the sys package.
|
638 |
|
|
typedef std::map<std::string, std::string> Sys_names;
|
639 |
|
|
|
640 |
|
|
// Type used to queue writing a type specific function.
|
641 |
|
|
struct Specific_type_function
|
642 |
|
|
{
|
643 |
|
|
Type* type;
|
644 |
|
|
Named_type* name;
|
645 |
|
|
std::string hash_name;
|
646 |
|
|
Function_type* hash_fntype;
|
647 |
|
|
std::string equal_name;
|
648 |
|
|
Function_type* equal_fntype;
|
649 |
|
|
|
650 |
|
|
Specific_type_function(Type* atype, Named_type* aname,
|
651 |
|
|
const std::string& ahash_name,
|
652 |
|
|
Function_type* ahash_fntype,
|
653 |
|
|
const std::string& aequal_name,
|
654 |
|
|
Function_type* aequal_fntype)
|
655 |
|
|
: type(atype), name(aname), hash_name(ahash_name),
|
656 |
|
|
hash_fntype(ahash_fntype), equal_name(aequal_name),
|
657 |
|
|
equal_fntype(aequal_fntype)
|
658 |
|
|
{ }
|
659 |
|
|
};
|
660 |
|
|
|
661 |
|
|
// The backend generator.
|
662 |
|
|
Backend* backend_;
|
663 |
|
|
// The object used to keep track of file names and line numbers.
|
664 |
|
|
Linemap* linemap_;
|
665 |
|
|
// The package we are compiling.
|
666 |
|
|
Package* package_;
|
667 |
|
|
// The list of currently open functions during parsing.
|
668 |
|
|
Open_functions functions_;
|
669 |
|
|
// The global binding contour. This includes the builtin functions
|
670 |
|
|
// and the package we are compiling.
|
671 |
|
|
Bindings* globals_;
|
672 |
|
|
// Mapping from import file names to packages.
|
673 |
|
|
Imports imports_;
|
674 |
|
|
// Whether the magic unsafe package was imported.
|
675 |
|
|
bool imported_unsafe_;
|
676 |
|
|
// Mapping from package names we have seen to packages. This does
|
677 |
|
|
// not include the package we are compiling.
|
678 |
|
|
Packages packages_;
|
679 |
|
|
// The functions named "init", if there are any.
|
680 |
|
|
std::vector<Named_object*> init_functions_;
|
681 |
|
|
// Whether we need a magic initialization function.
|
682 |
|
|
bool need_init_fn_;
|
683 |
|
|
// The name of the magic initialization function.
|
684 |
|
|
std::string init_fn_name_;
|
685 |
|
|
// A list of import control variables for packages that we import.
|
686 |
|
|
std::set<Import_init> imported_init_fns_;
|
687 |
|
|
// The unique prefix used for all global symbols.
|
688 |
|
|
std::string unique_prefix_;
|
689 |
|
|
// Whether an explicit unique prefix was set by -fgo-prefix.
|
690 |
|
|
bool unique_prefix_specified_;
|
691 |
|
|
// A list of types to verify.
|
692 |
|
|
std::vector<Type*> verify_types_;
|
693 |
|
|
// A list of interface types defined while parsing.
|
694 |
|
|
std::vector<Interface_type*> interface_types_;
|
695 |
|
|
// Type specific functions to write out.
|
696 |
|
|
std::vector<Specific_type_function*> specific_type_functions_;
|
697 |
|
|
// Whether we are done writing out specific type functions.
|
698 |
|
|
bool specific_type_functions_are_written_;
|
699 |
|
|
// Whether named types have been converted.
|
700 |
|
|
bool named_types_are_converted_;
|
701 |
|
|
};
|
702 |
|
|
|
703 |
|
|
// A block of statements.
|
704 |
|
|
|
705 |
|
|
class Block
|
706 |
|
|
{
|
707 |
|
|
public:
|
708 |
|
|
Block(Block* enclosing, Location);
|
709 |
|
|
|
710 |
|
|
// Return the enclosing block.
|
711 |
|
|
const Block*
|
712 |
|
|
enclosing() const
|
713 |
|
|
{ return this->enclosing_; }
|
714 |
|
|
|
715 |
|
|
// Return the bindings of the block.
|
716 |
|
|
Bindings*
|
717 |
|
|
bindings()
|
718 |
|
|
{ return this->bindings_; }
|
719 |
|
|
|
720 |
|
|
const Bindings*
|
721 |
|
|
bindings() const
|
722 |
|
|
{ return this->bindings_; }
|
723 |
|
|
|
724 |
|
|
// Look at the block's statements.
|
725 |
|
|
const std::vector<Statement*>*
|
726 |
|
|
statements() const
|
727 |
|
|
{ return &this->statements_; }
|
728 |
|
|
|
729 |
|
|
// Return the start location. This is normally the location of the
|
730 |
|
|
// left curly brace which starts the block.
|
731 |
|
|
Location
|
732 |
|
|
start_location() const
|
733 |
|
|
{ return this->start_location_; }
|
734 |
|
|
|
735 |
|
|
// Return the end location. This is normally the location of the
|
736 |
|
|
// right curly brace which ends the block.
|
737 |
|
|
Location
|
738 |
|
|
end_location() const
|
739 |
|
|
{ return this->end_location_; }
|
740 |
|
|
|
741 |
|
|
// Add a statement to the block.
|
742 |
|
|
void
|
743 |
|
|
add_statement(Statement*);
|
744 |
|
|
|
745 |
|
|
// Add a statement to the front of the block.
|
746 |
|
|
void
|
747 |
|
|
add_statement_at_front(Statement*);
|
748 |
|
|
|
749 |
|
|
// Replace a statement in a block.
|
750 |
|
|
void
|
751 |
|
|
replace_statement(size_t index, Statement*);
|
752 |
|
|
|
753 |
|
|
// Add a Statement before statement number INDEX.
|
754 |
|
|
void
|
755 |
|
|
insert_statement_before(size_t index, Statement*);
|
756 |
|
|
|
757 |
|
|
// Add a Statement after statement number INDEX.
|
758 |
|
|
void
|
759 |
|
|
insert_statement_after(size_t index, Statement*);
|
760 |
|
|
|
761 |
|
|
// Set the end location of the block.
|
762 |
|
|
void
|
763 |
|
|
set_end_location(Location location)
|
764 |
|
|
{ this->end_location_ = location; }
|
765 |
|
|
|
766 |
|
|
// Traverse the tree.
|
767 |
|
|
int
|
768 |
|
|
traverse(Traverse*);
|
769 |
|
|
|
770 |
|
|
// Set final types for unspecified variables and constants.
|
771 |
|
|
void
|
772 |
|
|
determine_types();
|
773 |
|
|
|
774 |
|
|
// Return true if execution of this block may fall through to the
|
775 |
|
|
// next block.
|
776 |
|
|
bool
|
777 |
|
|
may_fall_through() const;
|
778 |
|
|
|
779 |
|
|
// Convert the block to the backend representation.
|
780 |
|
|
Bblock*
|
781 |
|
|
get_backend(Translate_context*);
|
782 |
|
|
|
783 |
|
|
// Iterate over statements.
|
784 |
|
|
|
785 |
|
|
typedef std::vector<Statement*>::iterator iterator;
|
786 |
|
|
|
787 |
|
|
iterator
|
788 |
|
|
begin()
|
789 |
|
|
{ return this->statements_.begin(); }
|
790 |
|
|
|
791 |
|
|
iterator
|
792 |
|
|
end()
|
793 |
|
|
{ return this->statements_.end(); }
|
794 |
|
|
|
795 |
|
|
private:
|
796 |
|
|
// Enclosing block.
|
797 |
|
|
Block* enclosing_;
|
798 |
|
|
// Statements in the block.
|
799 |
|
|
std::vector<Statement*> statements_;
|
800 |
|
|
// Binding contour.
|
801 |
|
|
Bindings* bindings_;
|
802 |
|
|
// Location of start of block.
|
803 |
|
|
Location start_location_;
|
804 |
|
|
// Location of end of block.
|
805 |
|
|
Location end_location_;
|
806 |
|
|
};
|
807 |
|
|
|
808 |
|
|
// A function.
|
809 |
|
|
|
810 |
|
|
class Function
|
811 |
|
|
{
|
812 |
|
|
public:
|
813 |
|
|
Function(Function_type* type, Function*, Block*, Location);
|
814 |
|
|
|
815 |
|
|
// Return the function's type.
|
816 |
|
|
Function_type*
|
817 |
|
|
type() const
|
818 |
|
|
{ return this->type_; }
|
819 |
|
|
|
820 |
|
|
// Return the enclosing function if there is one.
|
821 |
|
|
Function*
|
822 |
|
|
enclosing()
|
823 |
|
|
{ return this->enclosing_; }
|
824 |
|
|
|
825 |
|
|
// Set the enclosing function. This is used when building thunks
|
826 |
|
|
// for functions which call recover.
|
827 |
|
|
void
|
828 |
|
|
set_enclosing(Function* enclosing)
|
829 |
|
|
{
|
830 |
|
|
go_assert(this->enclosing_ == NULL);
|
831 |
|
|
this->enclosing_ = enclosing;
|
832 |
|
|
}
|
833 |
|
|
|
834 |
|
|
// The result variables.
|
835 |
|
|
typedef std::vector<Named_object*> Results;
|
836 |
|
|
|
837 |
|
|
// Create the result variables in the outer block.
|
838 |
|
|
void
|
839 |
|
|
create_result_variables(Gogo*);
|
840 |
|
|
|
841 |
|
|
// Update the named result variables when cloning a function which
|
842 |
|
|
// calls recover.
|
843 |
|
|
void
|
844 |
|
|
update_result_variables();
|
845 |
|
|
|
846 |
|
|
// Return the result variables.
|
847 |
|
|
Results*
|
848 |
|
|
result_variables()
|
849 |
|
|
{ return this->results_; }
|
850 |
|
|
|
851 |
|
|
// Whether the result variables have names.
|
852 |
|
|
bool
|
853 |
|
|
results_are_named() const
|
854 |
|
|
{ return this->results_are_named_; }
|
855 |
|
|
|
856 |
|
|
// Add a new field to the closure variable.
|
857 |
|
|
void
|
858 |
|
|
add_closure_field(Named_object* var, Location loc)
|
859 |
|
|
{ this->closure_fields_.push_back(std::make_pair(var, loc)); }
|
860 |
|
|
|
861 |
|
|
// Whether this function needs a closure.
|
862 |
|
|
bool
|
863 |
|
|
needs_closure() const
|
864 |
|
|
{ return !this->closure_fields_.empty(); }
|
865 |
|
|
|
866 |
|
|
// Return the closure variable, creating it if necessary. This is
|
867 |
|
|
// passed to the function as a static chain parameter.
|
868 |
|
|
Named_object*
|
869 |
|
|
closure_var();
|
870 |
|
|
|
871 |
|
|
// Set the closure variable. This is used when building thunks for
|
872 |
|
|
// functions which call recover.
|
873 |
|
|
void
|
874 |
|
|
set_closure_var(Named_object* v)
|
875 |
|
|
{
|
876 |
|
|
go_assert(this->closure_var_ == NULL);
|
877 |
|
|
this->closure_var_ = v;
|
878 |
|
|
}
|
879 |
|
|
|
880 |
|
|
// Return the variable for a reference to field INDEX in the closure
|
881 |
|
|
// variable.
|
882 |
|
|
Named_object*
|
883 |
|
|
enclosing_var(unsigned int index)
|
884 |
|
|
{
|
885 |
|
|
go_assert(index < this->closure_fields_.size());
|
886 |
|
|
return closure_fields_[index].first;
|
887 |
|
|
}
|
888 |
|
|
|
889 |
|
|
// Set the type of the closure variable if there is one.
|
890 |
|
|
void
|
891 |
|
|
set_closure_type();
|
892 |
|
|
|
893 |
|
|
// Get the block of statements associated with the function.
|
894 |
|
|
Block*
|
895 |
|
|
block() const
|
896 |
|
|
{ return this->block_; }
|
897 |
|
|
|
898 |
|
|
// Get the location of the start of the function.
|
899 |
|
|
Location
|
900 |
|
|
location() const
|
901 |
|
|
{ return this->location_; }
|
902 |
|
|
|
903 |
|
|
// Return whether this function is actually a method.
|
904 |
|
|
bool
|
905 |
|
|
is_method() const;
|
906 |
|
|
|
907 |
|
|
// Add a label definition to the function.
|
908 |
|
|
Label*
|
909 |
|
|
add_label_definition(Gogo*, const std::string& label_name, Location);
|
910 |
|
|
|
911 |
|
|
// Add a label reference to a function. ISSUE_GOTO_ERRORS is true
|
912 |
|
|
// if we should report errors for a goto from the current location
|
913 |
|
|
// to the label location.
|
914 |
|
|
Label*
|
915 |
|
|
add_label_reference(Gogo*, const std::string& label_name,
|
916 |
|
|
Location, bool issue_goto_errors);
|
917 |
|
|
|
918 |
|
|
// Warn about labels that are defined but not used.
|
919 |
|
|
void
|
920 |
|
|
check_labels() const;
|
921 |
|
|
|
922 |
|
|
// Whether this function calls the predeclared recover function.
|
923 |
|
|
bool
|
924 |
|
|
calls_recover() const
|
925 |
|
|
{ return this->calls_recover_; }
|
926 |
|
|
|
927 |
|
|
// Record that this function calls the predeclared recover function.
|
928 |
|
|
// This is set during the lowering pass.
|
929 |
|
|
void
|
930 |
|
|
set_calls_recover()
|
931 |
|
|
{ this->calls_recover_ = true; }
|
932 |
|
|
|
933 |
|
|
// Whether this is a recover thunk function.
|
934 |
|
|
bool
|
935 |
|
|
is_recover_thunk() const
|
936 |
|
|
{ return this->is_recover_thunk_; }
|
937 |
|
|
|
938 |
|
|
// Record that this is a thunk built for a function which calls
|
939 |
|
|
// recover.
|
940 |
|
|
void
|
941 |
|
|
set_is_recover_thunk()
|
942 |
|
|
{ this->is_recover_thunk_ = true; }
|
943 |
|
|
|
944 |
|
|
// Whether this function already has a recover thunk.
|
945 |
|
|
bool
|
946 |
|
|
has_recover_thunk() const
|
947 |
|
|
{ return this->has_recover_thunk_; }
|
948 |
|
|
|
949 |
|
|
// Record that this function already has a recover thunk.
|
950 |
|
|
void
|
951 |
|
|
set_has_recover_thunk()
|
952 |
|
|
{ this->has_recover_thunk_ = true; }
|
953 |
|
|
|
954 |
|
|
// Swap with another function. Used only for the thunk which calls
|
955 |
|
|
// recover.
|
956 |
|
|
void
|
957 |
|
|
swap_for_recover(Function *);
|
958 |
|
|
|
959 |
|
|
// Traverse the tree.
|
960 |
|
|
int
|
961 |
|
|
traverse(Traverse*);
|
962 |
|
|
|
963 |
|
|
// Determine types in the function.
|
964 |
|
|
void
|
965 |
|
|
determine_types();
|
966 |
|
|
|
967 |
|
|
// Return the function's decl given an identifier.
|
968 |
|
|
tree
|
969 |
|
|
get_or_make_decl(Gogo*, Named_object*, tree id);
|
970 |
|
|
|
971 |
|
|
// Return the function's decl after it has been built.
|
972 |
|
|
tree
|
973 |
|
|
get_decl() const
|
974 |
|
|
{
|
975 |
|
|
go_assert(this->fndecl_ != NULL);
|
976 |
|
|
return this->fndecl_;
|
977 |
|
|
}
|
978 |
|
|
|
979 |
|
|
// Set the function decl to hold a tree of the function code.
|
980 |
|
|
void
|
981 |
|
|
build_tree(Gogo*, Named_object*);
|
982 |
|
|
|
983 |
|
|
// Get the value to return when not explicitly specified. May also
|
984 |
|
|
// add statements to execute first to STMT_LIST.
|
985 |
|
|
tree
|
986 |
|
|
return_value(Gogo*, Named_object*, Location, tree* stmt_list) const;
|
987 |
|
|
|
988 |
|
|
// Get a tree for the variable holding the defer stack.
|
989 |
|
|
Expression*
|
990 |
|
|
defer_stack(Location);
|
991 |
|
|
|
992 |
|
|
// Export the function.
|
993 |
|
|
void
|
994 |
|
|
export_func(Export*, const std::string& name) const;
|
995 |
|
|
|
996 |
|
|
// Export a function with a type.
|
997 |
|
|
static void
|
998 |
|
|
export_func_with_type(Export*, const std::string& name,
|
999 |
|
|
const Function_type*);
|
1000 |
|
|
|
1001 |
|
|
// Import a function.
|
1002 |
|
|
static void
|
1003 |
|
|
import_func(Import*, std::string* pname, Typed_identifier** receiver,
|
1004 |
|
|
Typed_identifier_list** pparameters,
|
1005 |
|
|
Typed_identifier_list** presults, bool* is_varargs);
|
1006 |
|
|
|
1007 |
|
|
private:
|
1008 |
|
|
// Type for mapping from label names to Label objects.
|
1009 |
|
|
typedef Unordered_map(std::string, Label*) Labels;
|
1010 |
|
|
|
1011 |
|
|
tree
|
1012 |
|
|
make_receiver_parm_decl(Gogo*, Named_object*, tree);
|
1013 |
|
|
|
1014 |
|
|
tree
|
1015 |
|
|
copy_parm_to_heap(Gogo*, Named_object*, tree);
|
1016 |
|
|
|
1017 |
|
|
void
|
1018 |
|
|
build_defer_wrapper(Gogo*, Named_object*, tree*, tree*);
|
1019 |
|
|
|
1020 |
|
|
typedef std::vector<std::pair<Named_object*,
|
1021 |
|
|
Location> > Closure_fields;
|
1022 |
|
|
|
1023 |
|
|
// The function's type.
|
1024 |
|
|
Function_type* type_;
|
1025 |
|
|
// The enclosing function. This is NULL when there isn't one, which
|
1026 |
|
|
// is the normal case.
|
1027 |
|
|
Function* enclosing_;
|
1028 |
|
|
// The result variables, if any.
|
1029 |
|
|
Results* results_;
|
1030 |
|
|
// If there is a closure, this is the list of variables which appear
|
1031 |
|
|
// in the closure. This is created by the parser, and then resolved
|
1032 |
|
|
// to a real type when we lower parse trees.
|
1033 |
|
|
Closure_fields closure_fields_;
|
1034 |
|
|
// The closure variable, passed as a parameter using the static
|
1035 |
|
|
// chain parameter. Normally NULL.
|
1036 |
|
|
Named_object* closure_var_;
|
1037 |
|
|
// The outer block of statements in the function.
|
1038 |
|
|
Block* block_;
|
1039 |
|
|
// The source location of the start of the function.
|
1040 |
|
|
Location location_;
|
1041 |
|
|
// Labels defined or referenced in the function.
|
1042 |
|
|
Labels labels_;
|
1043 |
|
|
// The function decl.
|
1044 |
|
|
tree fndecl_;
|
1045 |
|
|
// The defer stack variable. A pointer to this variable is used to
|
1046 |
|
|
// distinguish the defer stack for one function from another. This
|
1047 |
|
|
// is NULL unless we actually need a defer stack.
|
1048 |
|
|
Temporary_statement* defer_stack_;
|
1049 |
|
|
// True if the result variables are named.
|
1050 |
|
|
bool results_are_named_;
|
1051 |
|
|
// True if this function calls the predeclared recover function.
|
1052 |
|
|
bool calls_recover_;
|
1053 |
|
|
// True if this a thunk built for a function which calls recover.
|
1054 |
|
|
bool is_recover_thunk_;
|
1055 |
|
|
// True if this function already has a recover thunk.
|
1056 |
|
|
bool has_recover_thunk_;
|
1057 |
|
|
};
|
1058 |
|
|
|
1059 |
|
|
// A snapshot of the current binding state.
|
1060 |
|
|
|
1061 |
|
|
class Bindings_snapshot
|
1062 |
|
|
{
|
1063 |
|
|
public:
|
1064 |
|
|
Bindings_snapshot(const Block*, Location);
|
1065 |
|
|
|
1066 |
|
|
// Report any errors appropriate for a goto from the current binding
|
1067 |
|
|
// state of B to this one.
|
1068 |
|
|
void
|
1069 |
|
|
check_goto_from(const Block* b, Location);
|
1070 |
|
|
|
1071 |
|
|
// Report any errors appropriate for a goto from this binding state
|
1072 |
|
|
// to the current state of B.
|
1073 |
|
|
void
|
1074 |
|
|
check_goto_to(const Block* b);
|
1075 |
|
|
|
1076 |
|
|
private:
|
1077 |
|
|
bool
|
1078 |
|
|
check_goto_block(Location, const Block*, const Block*, size_t*);
|
1079 |
|
|
|
1080 |
|
|
void
|
1081 |
|
|
check_goto_defs(Location, const Block*, size_t, size_t);
|
1082 |
|
|
|
1083 |
|
|
// The current block.
|
1084 |
|
|
const Block* block_;
|
1085 |
|
|
// The number of names currently defined in each open block.
|
1086 |
|
|
// Element 0 is this->block_, element 1 is
|
1087 |
|
|
// this->block_->enclosing(), etc.
|
1088 |
|
|
std::vector<size_t> counts_;
|
1089 |
|
|
// The location where this snapshot was taken.
|
1090 |
|
|
Location location_;
|
1091 |
|
|
};
|
1092 |
|
|
|
1093 |
|
|
// A function declaration.
|
1094 |
|
|
|
1095 |
|
|
class Function_declaration
|
1096 |
|
|
{
|
1097 |
|
|
public:
|
1098 |
|
|
Function_declaration(Function_type* fntype, Location location)
|
1099 |
|
|
: fntype_(fntype), location_(location), asm_name_(), fndecl_(NULL)
|
1100 |
|
|
{ }
|
1101 |
|
|
|
1102 |
|
|
Function_type*
|
1103 |
|
|
type() const
|
1104 |
|
|
{ return this->fntype_; }
|
1105 |
|
|
|
1106 |
|
|
Location
|
1107 |
|
|
location() const
|
1108 |
|
|
{ return this->location_; }
|
1109 |
|
|
|
1110 |
|
|
const std::string&
|
1111 |
|
|
asm_name() const
|
1112 |
|
|
{ return this->asm_name_; }
|
1113 |
|
|
|
1114 |
|
|
// Set the assembler name.
|
1115 |
|
|
void
|
1116 |
|
|
set_asm_name(const std::string& asm_name)
|
1117 |
|
|
{ this->asm_name_ = asm_name; }
|
1118 |
|
|
|
1119 |
|
|
// Return a decl for the function given an identifier.
|
1120 |
|
|
tree
|
1121 |
|
|
get_or_make_decl(Gogo*, Named_object*, tree id);
|
1122 |
|
|
|
1123 |
|
|
// Export a function declaration.
|
1124 |
|
|
void
|
1125 |
|
|
export_func(Export* exp, const std::string& name) const
|
1126 |
|
|
{ Function::export_func_with_type(exp, name, this->fntype_); }
|
1127 |
|
|
|
1128 |
|
|
private:
|
1129 |
|
|
// The type of the function.
|
1130 |
|
|
Function_type* fntype_;
|
1131 |
|
|
// The location of the declaration.
|
1132 |
|
|
Location location_;
|
1133 |
|
|
// The assembler name: this is the name to use in references to the
|
1134 |
|
|
// function. This is normally empty.
|
1135 |
|
|
std::string asm_name_;
|
1136 |
|
|
// The function decl if needed.
|
1137 |
|
|
tree fndecl_;
|
1138 |
|
|
};
|
1139 |
|
|
|
1140 |
|
|
// A variable.
|
1141 |
|
|
|
1142 |
|
|
class Variable
|
1143 |
|
|
{
|
1144 |
|
|
public:
|
1145 |
|
|
Variable(Type*, Expression*, bool is_global, bool is_parameter,
|
1146 |
|
|
bool is_receiver, Location);
|
1147 |
|
|
|
1148 |
|
|
// Get the type of the variable.
|
1149 |
|
|
Type*
|
1150 |
|
|
type();
|
1151 |
|
|
|
1152 |
|
|
Type*
|
1153 |
|
|
type() const;
|
1154 |
|
|
|
1155 |
|
|
// Return whether the type is defined yet.
|
1156 |
|
|
bool
|
1157 |
|
|
has_type() const;
|
1158 |
|
|
|
1159 |
|
|
// Get the initial value.
|
1160 |
|
|
Expression*
|
1161 |
|
|
init() const
|
1162 |
|
|
{ return this->init_; }
|
1163 |
|
|
|
1164 |
|
|
// Return whether there are any preinit statements.
|
1165 |
|
|
bool
|
1166 |
|
|
has_pre_init() const
|
1167 |
|
|
{ return this->preinit_ != NULL; }
|
1168 |
|
|
|
1169 |
|
|
// Return the preinit statements if any.
|
1170 |
|
|
Block*
|
1171 |
|
|
preinit() const
|
1172 |
|
|
{ return this->preinit_; }
|
1173 |
|
|
|
1174 |
|
|
// Return whether this is a global variable.
|
1175 |
|
|
bool
|
1176 |
|
|
is_global() const
|
1177 |
|
|
{ return this->is_global_; }
|
1178 |
|
|
|
1179 |
|
|
// Return whether this is a function parameter.
|
1180 |
|
|
bool
|
1181 |
|
|
is_parameter() const
|
1182 |
|
|
{ return this->is_parameter_; }
|
1183 |
|
|
|
1184 |
|
|
// Return whether this is the receiver parameter of a method.
|
1185 |
|
|
bool
|
1186 |
|
|
is_receiver() const
|
1187 |
|
|
{ return this->is_receiver_; }
|
1188 |
|
|
|
1189 |
|
|
// Change this parameter to be a receiver. This is used when
|
1190 |
|
|
// creating the thunks created for functions which call recover.
|
1191 |
|
|
void
|
1192 |
|
|
set_is_receiver()
|
1193 |
|
|
{
|
1194 |
|
|
go_assert(this->is_parameter_);
|
1195 |
|
|
this->is_receiver_ = true;
|
1196 |
|
|
}
|
1197 |
|
|
|
1198 |
|
|
// Change this parameter to not be a receiver. This is used when
|
1199 |
|
|
// creating the thunks created for functions which call recover.
|
1200 |
|
|
void
|
1201 |
|
|
set_is_not_receiver()
|
1202 |
|
|
{
|
1203 |
|
|
go_assert(this->is_parameter_);
|
1204 |
|
|
this->is_receiver_ = false;
|
1205 |
|
|
}
|
1206 |
|
|
|
1207 |
|
|
// Return whether this is the varargs parameter of a function.
|
1208 |
|
|
bool
|
1209 |
|
|
is_varargs_parameter() const
|
1210 |
|
|
{ return this->is_varargs_parameter_; }
|
1211 |
|
|
|
1212 |
|
|
// Whether this variable's address is taken.
|
1213 |
|
|
bool
|
1214 |
|
|
is_address_taken() const
|
1215 |
|
|
{ return this->is_address_taken_; }
|
1216 |
|
|
|
1217 |
|
|
// Whether this variable should live in the heap.
|
1218 |
|
|
bool
|
1219 |
|
|
is_in_heap() const
|
1220 |
|
|
{ return this->is_address_taken_ && !this->is_global_; }
|
1221 |
|
|
|
1222 |
|
|
// Note that something takes the address of this variable.
|
1223 |
|
|
void
|
1224 |
|
|
set_address_taken()
|
1225 |
|
|
{ this->is_address_taken_ = true; }
|
1226 |
|
|
|
1227 |
|
|
// Return whether the address is taken but does not escape.
|
1228 |
|
|
bool
|
1229 |
|
|
is_non_escaping_address_taken() const
|
1230 |
|
|
{ return this->is_non_escaping_address_taken_; }
|
1231 |
|
|
|
1232 |
|
|
// Note that something takes the address of this variable such that
|
1233 |
|
|
// the address does not escape the function.
|
1234 |
|
|
void
|
1235 |
|
|
set_non_escaping_address_taken()
|
1236 |
|
|
{ this->is_non_escaping_address_taken_ = true; }
|
1237 |
|
|
|
1238 |
|
|
// Get the source location of the variable's declaration.
|
1239 |
|
|
Location
|
1240 |
|
|
location() const
|
1241 |
|
|
{ return this->location_; }
|
1242 |
|
|
|
1243 |
|
|
// Record that this is the varargs parameter of a function.
|
1244 |
|
|
void
|
1245 |
|
|
set_is_varargs_parameter()
|
1246 |
|
|
{
|
1247 |
|
|
go_assert(this->is_parameter_);
|
1248 |
|
|
this->is_varargs_parameter_ = true;
|
1249 |
|
|
}
|
1250 |
|
|
|
1251 |
|
|
// Return whether the variable has been used.
|
1252 |
|
|
bool
|
1253 |
|
|
is_used() const
|
1254 |
|
|
{ return this->is_used_; }
|
1255 |
|
|
|
1256 |
|
|
// Mark that the variable has been used.
|
1257 |
|
|
void
|
1258 |
|
|
set_is_used()
|
1259 |
|
|
{ this->is_used_ = true; }
|
1260 |
|
|
|
1261 |
|
|
// Clear the initial value; used for error handling.
|
1262 |
|
|
void
|
1263 |
|
|
clear_init()
|
1264 |
|
|
{ this->init_ = NULL; }
|
1265 |
|
|
|
1266 |
|
|
// Set the initial value; used for converting shortcuts.
|
1267 |
|
|
void
|
1268 |
|
|
set_init(Expression* init)
|
1269 |
|
|
{ this->init_ = init; }
|
1270 |
|
|
|
1271 |
|
|
// Get the preinit block, a block of statements to be run before the
|
1272 |
|
|
// initialization expression.
|
1273 |
|
|
Block*
|
1274 |
|
|
preinit_block(Gogo*);
|
1275 |
|
|
|
1276 |
|
|
// Add a statement to be run before the initialization expression.
|
1277 |
|
|
// This is only used for global variables.
|
1278 |
|
|
void
|
1279 |
|
|
add_preinit_statement(Gogo*, Statement*);
|
1280 |
|
|
|
1281 |
|
|
// Lower the initialization expression after parsing is complete.
|
1282 |
|
|
void
|
1283 |
|
|
lower_init_expression(Gogo*, Named_object*, Statement_inserter*);
|
1284 |
|
|
|
1285 |
|
|
// A special case: the init value is used only to determine the
|
1286 |
|
|
// type. This is used if the variable is defined using := with the
|
1287 |
|
|
// comma-ok form of a map index or a receive expression. The init
|
1288 |
|
|
// value is actually the map index expression or receive expression.
|
1289 |
|
|
// We use this because we may not know the right type at parse time.
|
1290 |
|
|
void
|
1291 |
|
|
set_type_from_init_tuple()
|
1292 |
|
|
{ this->type_from_init_tuple_ = true; }
|
1293 |
|
|
|
1294 |
|
|
// Another special case: the init value is used only to determine
|
1295 |
|
|
// the type. This is used if the variable is defined using := with
|
1296 |
|
|
// a range clause. The init value is the range expression. The
|
1297 |
|
|
// type of the variable is the index type of the range expression
|
1298 |
|
|
// (i.e., the first value returned by a range).
|
1299 |
|
|
void
|
1300 |
|
|
set_type_from_range_index()
|
1301 |
|
|
{ this->type_from_range_index_ = true; }
|
1302 |
|
|
|
1303 |
|
|
// Another special case: like set_type_from_range_index, but the
|
1304 |
|
|
// type is the value type of the range expression (i.e., the second
|
1305 |
|
|
// value returned by a range).
|
1306 |
|
|
void
|
1307 |
|
|
set_type_from_range_value()
|
1308 |
|
|
{ this->type_from_range_value_ = true; }
|
1309 |
|
|
|
1310 |
|
|
// Another special case: the init value is used only to determine
|
1311 |
|
|
// the type. This is used if the variable is defined using := with
|
1312 |
|
|
// a case in a select statement. The init value is the channel.
|
1313 |
|
|
// The type of the variable is the channel's element type.
|
1314 |
|
|
void
|
1315 |
|
|
set_type_from_chan_element()
|
1316 |
|
|
{ this->type_from_chan_element_ = true; }
|
1317 |
|
|
|
1318 |
|
|
// After we lower the select statement, we once again set the type
|
1319 |
|
|
// from the initialization expression.
|
1320 |
|
|
void
|
1321 |
|
|
clear_type_from_chan_element()
|
1322 |
|
|
{
|
1323 |
|
|
go_assert(this->type_from_chan_element_);
|
1324 |
|
|
this->type_from_chan_element_ = false;
|
1325 |
|
|
}
|
1326 |
|
|
|
1327 |
|
|
// Note that this variable was created for a type switch clause.
|
1328 |
|
|
void
|
1329 |
|
|
set_is_type_switch_var()
|
1330 |
|
|
{ this->is_type_switch_var_ = true; }
|
1331 |
|
|
|
1332 |
|
|
// Traverse the initializer expression.
|
1333 |
|
|
int
|
1334 |
|
|
traverse_expression(Traverse*, unsigned int traverse_mask);
|
1335 |
|
|
|
1336 |
|
|
// Determine the type of the variable if necessary.
|
1337 |
|
|
void
|
1338 |
|
|
determine_type();
|
1339 |
|
|
|
1340 |
|
|
// Get the backend representation of the variable.
|
1341 |
|
|
Bvariable*
|
1342 |
|
|
get_backend_variable(Gogo*, Named_object*, const Package*,
|
1343 |
|
|
const std::string&);
|
1344 |
|
|
|
1345 |
|
|
// Get the initial value of the variable as a tree. This may only
|
1346 |
|
|
// be called if has_pre_init() returns false.
|
1347 |
|
|
tree
|
1348 |
|
|
get_init_tree(Gogo*, Named_object* function);
|
1349 |
|
|
|
1350 |
|
|
// Return a series of statements which sets the value of the
|
1351 |
|
|
// variable in DECL. This should only be called is has_pre_init()
|
1352 |
|
|
// returns true. DECL may be NULL for a sink variable.
|
1353 |
|
|
tree
|
1354 |
|
|
get_init_block(Gogo*, Named_object* function, tree decl);
|
1355 |
|
|
|
1356 |
|
|
// Export the variable.
|
1357 |
|
|
void
|
1358 |
|
|
export_var(Export*, const std::string& name) const;
|
1359 |
|
|
|
1360 |
|
|
// Import a variable.
|
1361 |
|
|
static void
|
1362 |
|
|
import_var(Import*, std::string* pname, Type** ptype);
|
1363 |
|
|
|
1364 |
|
|
private:
|
1365 |
|
|
// The type of a tuple.
|
1366 |
|
|
Type*
|
1367 |
|
|
type_from_tuple(Expression*, bool) const;
|
1368 |
|
|
|
1369 |
|
|
// The type of a range.
|
1370 |
|
|
Type*
|
1371 |
|
|
type_from_range(Expression*, bool, bool) const;
|
1372 |
|
|
|
1373 |
|
|
// The element type of a channel.
|
1374 |
|
|
Type*
|
1375 |
|
|
type_from_chan_element(Expression*, bool) const;
|
1376 |
|
|
|
1377 |
|
|
// The variable's type. This may be NULL if the type is set from
|
1378 |
|
|
// the expression.
|
1379 |
|
|
Type* type_;
|
1380 |
|
|
// The initial value. This may be NULL if the variable should be
|
1381 |
|
|
// initialized to the default value for the type.
|
1382 |
|
|
Expression* init_;
|
1383 |
|
|
// Statements to run before the init statement.
|
1384 |
|
|
Block* preinit_;
|
1385 |
|
|
// Location of variable definition.
|
1386 |
|
|
Location location_;
|
1387 |
|
|
// Backend representation.
|
1388 |
|
|
Bvariable* backend_;
|
1389 |
|
|
// Whether this is a global variable.
|
1390 |
|
|
bool is_global_ : 1;
|
1391 |
|
|
// Whether this is a function parameter.
|
1392 |
|
|
bool is_parameter_ : 1;
|
1393 |
|
|
// Whether this is the receiver parameter of a method.
|
1394 |
|
|
bool is_receiver_ : 1;
|
1395 |
|
|
// Whether this is the varargs parameter of a function.
|
1396 |
|
|
bool is_varargs_parameter_ : 1;
|
1397 |
|
|
// Whether this variable is ever referenced.
|
1398 |
|
|
bool is_used_ : 1;
|
1399 |
|
|
// Whether something takes the address of this variable. For a
|
1400 |
|
|
// local variable this implies that the variable has to be on the
|
1401 |
|
|
// heap.
|
1402 |
|
|
bool is_address_taken_ : 1;
|
1403 |
|
|
// Whether something takes the address of this variable such that
|
1404 |
|
|
// the address does not escape the function.
|
1405 |
|
|
bool is_non_escaping_address_taken_ : 1;
|
1406 |
|
|
// True if we have seen this variable in a traversal.
|
1407 |
|
|
bool seen_ : 1;
|
1408 |
|
|
// True if we have lowered the initialization expression.
|
1409 |
|
|
bool init_is_lowered_ : 1;
|
1410 |
|
|
// True if init is a tuple used to set the type.
|
1411 |
|
|
bool type_from_init_tuple_ : 1;
|
1412 |
|
|
// True if init is a range clause and the type is the index type.
|
1413 |
|
|
bool type_from_range_index_ : 1;
|
1414 |
|
|
// True if init is a range clause and the type is the value type.
|
1415 |
|
|
bool type_from_range_value_ : 1;
|
1416 |
|
|
// True if init is a channel and the type is the channel's element type.
|
1417 |
|
|
bool type_from_chan_element_ : 1;
|
1418 |
|
|
// True if this is a variable created for a type switch case.
|
1419 |
|
|
bool is_type_switch_var_ : 1;
|
1420 |
|
|
// True if we have determined types.
|
1421 |
|
|
bool determined_type_ : 1;
|
1422 |
|
|
};
|
1423 |
|
|
|
1424 |
|
|
// A variable which is really the name for a function return value, or
|
1425 |
|
|
// part of one.
|
1426 |
|
|
|
1427 |
|
|
class Result_variable
|
1428 |
|
|
{
|
1429 |
|
|
public:
|
1430 |
|
|
Result_variable(Type* type, Function* function, int index,
|
1431 |
|
|
Location location)
|
1432 |
|
|
: type_(type), function_(function), index_(index), location_(location),
|
1433 |
|
|
backend_(NULL), is_address_taken_(false),
|
1434 |
|
|
is_non_escaping_address_taken_(false)
|
1435 |
|
|
{ }
|
1436 |
|
|
|
1437 |
|
|
// Get the type of the result variable.
|
1438 |
|
|
Type*
|
1439 |
|
|
type() const
|
1440 |
|
|
{ return this->type_; }
|
1441 |
|
|
|
1442 |
|
|
// Get the function that this is associated with.
|
1443 |
|
|
Function*
|
1444 |
|
|
function() const
|
1445 |
|
|
{ return this->function_; }
|
1446 |
|
|
|
1447 |
|
|
// Index in the list of function results.
|
1448 |
|
|
int
|
1449 |
|
|
index() const
|
1450 |
|
|
{ return this->index_; }
|
1451 |
|
|
|
1452 |
|
|
// The location of the variable definition.
|
1453 |
|
|
Location
|
1454 |
|
|
location() const
|
1455 |
|
|
{ return this->location_; }
|
1456 |
|
|
|
1457 |
|
|
// Whether this variable's address is taken.
|
1458 |
|
|
bool
|
1459 |
|
|
is_address_taken() const
|
1460 |
|
|
{ return this->is_address_taken_; }
|
1461 |
|
|
|
1462 |
|
|
// Note that something takes the address of this variable.
|
1463 |
|
|
void
|
1464 |
|
|
set_address_taken()
|
1465 |
|
|
{ this->is_address_taken_ = true; }
|
1466 |
|
|
|
1467 |
|
|
// Return whether the address is taken but does not escape.
|
1468 |
|
|
bool
|
1469 |
|
|
is_non_escaping_address_taken() const
|
1470 |
|
|
{ return this->is_non_escaping_address_taken_; }
|
1471 |
|
|
|
1472 |
|
|
// Note that something takes the address of this variable such that
|
1473 |
|
|
// the address does not escape the function.
|
1474 |
|
|
void
|
1475 |
|
|
set_non_escaping_address_taken()
|
1476 |
|
|
{ this->is_non_escaping_address_taken_ = true; }
|
1477 |
|
|
|
1478 |
|
|
// Whether this variable should live in the heap.
|
1479 |
|
|
bool
|
1480 |
|
|
is_in_heap() const
|
1481 |
|
|
{ return this->is_address_taken_; }
|
1482 |
|
|
|
1483 |
|
|
// Set the function. This is used when cloning functions which call
|
1484 |
|
|
// recover.
|
1485 |
|
|
void
|
1486 |
|
|
set_function(Function* function)
|
1487 |
|
|
{ this->function_ = function; }
|
1488 |
|
|
|
1489 |
|
|
// Get the backend representation of the variable.
|
1490 |
|
|
Bvariable*
|
1491 |
|
|
get_backend_variable(Gogo*, Named_object*, const std::string&);
|
1492 |
|
|
|
1493 |
|
|
private:
|
1494 |
|
|
// Type of result variable.
|
1495 |
|
|
Type* type_;
|
1496 |
|
|
// Function with which this is associated.
|
1497 |
|
|
Function* function_;
|
1498 |
|
|
// Index in list of results.
|
1499 |
|
|
int index_;
|
1500 |
|
|
// Where the result variable is defined.
|
1501 |
|
|
Location location_;
|
1502 |
|
|
// Backend representation.
|
1503 |
|
|
Bvariable* backend_;
|
1504 |
|
|
// Whether something takes the address of this variable.
|
1505 |
|
|
bool is_address_taken_;
|
1506 |
|
|
// Whether something takes the address of this variable such that
|
1507 |
|
|
// the address does not escape the function.
|
1508 |
|
|
bool is_non_escaping_address_taken_;
|
1509 |
|
|
};
|
1510 |
|
|
|
1511 |
|
|
// The value we keep for a named constant. This lets us hold a type
|
1512 |
|
|
// and an expression.
|
1513 |
|
|
|
1514 |
|
|
class Named_constant
|
1515 |
|
|
{
|
1516 |
|
|
public:
|
1517 |
|
|
Named_constant(Type* type, Expression* expr, int iota_value,
|
1518 |
|
|
Location location)
|
1519 |
|
|
: type_(type), expr_(expr), iota_value_(iota_value), location_(location),
|
1520 |
|
|
lowering_(false)
|
1521 |
|
|
{ }
|
1522 |
|
|
|
1523 |
|
|
Type*
|
1524 |
|
|
type() const
|
1525 |
|
|
{ return this->type_; }
|
1526 |
|
|
|
1527 |
|
|
Expression*
|
1528 |
|
|
expr() const
|
1529 |
|
|
{ return this->expr_; }
|
1530 |
|
|
|
1531 |
|
|
int
|
1532 |
|
|
iota_value() const
|
1533 |
|
|
{ return this->iota_value_; }
|
1534 |
|
|
|
1535 |
|
|
Location
|
1536 |
|
|
location() const
|
1537 |
|
|
{ return this->location_; }
|
1538 |
|
|
|
1539 |
|
|
// Whether we are lowering.
|
1540 |
|
|
bool
|
1541 |
|
|
lowering() const
|
1542 |
|
|
{ return this->lowering_; }
|
1543 |
|
|
|
1544 |
|
|
// Set that we are lowering.
|
1545 |
|
|
void
|
1546 |
|
|
set_lowering()
|
1547 |
|
|
{ this->lowering_ = true; }
|
1548 |
|
|
|
1549 |
|
|
// We are no longer lowering.
|
1550 |
|
|
void
|
1551 |
|
|
clear_lowering()
|
1552 |
|
|
{ this->lowering_ = false; }
|
1553 |
|
|
|
1554 |
|
|
// Traverse the expression.
|
1555 |
|
|
int
|
1556 |
|
|
traverse_expression(Traverse*);
|
1557 |
|
|
|
1558 |
|
|
// Determine the type of the constant if necessary.
|
1559 |
|
|
void
|
1560 |
|
|
determine_type();
|
1561 |
|
|
|
1562 |
|
|
// Indicate that we found and reported an error for this constant.
|
1563 |
|
|
void
|
1564 |
|
|
set_error();
|
1565 |
|
|
|
1566 |
|
|
// Export the constant.
|
1567 |
|
|
void
|
1568 |
|
|
export_const(Export*, const std::string& name) const;
|
1569 |
|
|
|
1570 |
|
|
// Import a constant.
|
1571 |
|
|
static void
|
1572 |
|
|
import_const(Import*, std::string*, Type**, Expression**);
|
1573 |
|
|
|
1574 |
|
|
private:
|
1575 |
|
|
// The type of the constant.
|
1576 |
|
|
Type* type_;
|
1577 |
|
|
// The expression for the constant.
|
1578 |
|
|
Expression* expr_;
|
1579 |
|
|
// If the predeclared constant iota is used in EXPR_, this is the
|
1580 |
|
|
// value it will have. We do this because at parse time we don't
|
1581 |
|
|
// know whether the name "iota" will refer to the predeclared
|
1582 |
|
|
// constant or to something else. We put in the right value in when
|
1583 |
|
|
// we lower.
|
1584 |
|
|
int iota_value_;
|
1585 |
|
|
// The location of the definition.
|
1586 |
|
|
Location location_;
|
1587 |
|
|
// Whether we are currently lowering this constant.
|
1588 |
|
|
bool lowering_;
|
1589 |
|
|
};
|
1590 |
|
|
|
1591 |
|
|
// A type declaration.
|
1592 |
|
|
|
1593 |
|
|
class Type_declaration
|
1594 |
|
|
{
|
1595 |
|
|
public:
|
1596 |
|
|
Type_declaration(Location location)
|
1597 |
|
|
: location_(location), in_function_(NULL), methods_(),
|
1598 |
|
|
issued_warning_(false)
|
1599 |
|
|
{ }
|
1600 |
|
|
|
1601 |
|
|
// Return the location.
|
1602 |
|
|
Location
|
1603 |
|
|
location() const
|
1604 |
|
|
{ return this->location_; }
|
1605 |
|
|
|
1606 |
|
|
// Return the function in which this type is declared. This will
|
1607 |
|
|
// return NULL for a type declared in global scope.
|
1608 |
|
|
Named_object*
|
1609 |
|
|
in_function()
|
1610 |
|
|
{ return this->in_function_; }
|
1611 |
|
|
|
1612 |
|
|
// Set the function in which this type is declared.
|
1613 |
|
|
void
|
1614 |
|
|
set_in_function(Named_object* f)
|
1615 |
|
|
{ this->in_function_ = f; }
|
1616 |
|
|
|
1617 |
|
|
// Add a method to this type. This is used when methods are defined
|
1618 |
|
|
// before the type.
|
1619 |
|
|
Named_object*
|
1620 |
|
|
add_method(const std::string& name, Function* function);
|
1621 |
|
|
|
1622 |
|
|
// Add a method declaration to this type.
|
1623 |
|
|
Named_object*
|
1624 |
|
|
add_method_declaration(const std::string& name, Package*,
|
1625 |
|
|
Function_type* type, Location location);
|
1626 |
|
|
|
1627 |
|
|
// Return whether any methods were defined.
|
1628 |
|
|
bool
|
1629 |
|
|
has_methods() const;
|
1630 |
|
|
|
1631 |
|
|
// Define methods when the real type is known.
|
1632 |
|
|
void
|
1633 |
|
|
define_methods(Named_type*);
|
1634 |
|
|
|
1635 |
|
|
// This is called if we are trying to use this type. It returns
|
1636 |
|
|
// true if we should issue a warning.
|
1637 |
|
|
bool
|
1638 |
|
|
using_type();
|
1639 |
|
|
|
1640 |
|
|
private:
|
1641 |
|
|
typedef std::vector<Named_object*> Methods;
|
1642 |
|
|
|
1643 |
|
|
// The location of the type declaration.
|
1644 |
|
|
Location location_;
|
1645 |
|
|
// If this type is declared in a function, a pointer back to the
|
1646 |
|
|
// function in which it is defined.
|
1647 |
|
|
Named_object* in_function_;
|
1648 |
|
|
// Methods defined before the type is defined.
|
1649 |
|
|
Methods methods_;
|
1650 |
|
|
// True if we have issued a warning about a use of this type
|
1651 |
|
|
// declaration when it is undefined.
|
1652 |
|
|
bool issued_warning_;
|
1653 |
|
|
};
|
1654 |
|
|
|
1655 |
|
|
// An unknown object. These are created by the parser for forward
|
1656 |
|
|
// references to names which have not been seen before. In a correct
|
1657 |
|
|
// program, these will always point to a real definition by the end of
|
1658 |
|
|
// the parse. Because they point to another Named_object, these may
|
1659 |
|
|
// only be referenced by Unknown_expression objects.
|
1660 |
|
|
|
1661 |
|
|
class Unknown_name
|
1662 |
|
|
{
|
1663 |
|
|
public:
|
1664 |
|
|
Unknown_name(Location location)
|
1665 |
|
|
: location_(location), real_named_object_(NULL)
|
1666 |
|
|
{ }
|
1667 |
|
|
|
1668 |
|
|
// Return the location where this name was first seen.
|
1669 |
|
|
Location
|
1670 |
|
|
location() const
|
1671 |
|
|
{ return this->location_; }
|
1672 |
|
|
|
1673 |
|
|
// Return the real named object that this points to, or NULL if it
|
1674 |
|
|
// was never resolved.
|
1675 |
|
|
Named_object*
|
1676 |
|
|
real_named_object() const
|
1677 |
|
|
{ return this->real_named_object_; }
|
1678 |
|
|
|
1679 |
|
|
// Set the real named object that this points to.
|
1680 |
|
|
void
|
1681 |
|
|
set_real_named_object(Named_object* no);
|
1682 |
|
|
|
1683 |
|
|
private:
|
1684 |
|
|
// The location where this name was first seen.
|
1685 |
|
|
Location location_;
|
1686 |
|
|
// The real named object when it is known.
|
1687 |
|
|
Named_object*
|
1688 |
|
|
real_named_object_;
|
1689 |
|
|
};
|
1690 |
|
|
|
1691 |
|
|
// A named object named. This is the result of a declaration. We
|
1692 |
|
|
// don't use a superclass because they all have to be handled
|
1693 |
|
|
// differently.
|
1694 |
|
|
|
1695 |
|
|
class Named_object
|
1696 |
|
|
{
|
1697 |
|
|
public:
|
1698 |
|
|
enum Classification
|
1699 |
|
|
{
|
1700 |
|
|
// An uninitialized Named_object. We should never see this.
|
1701 |
|
|
NAMED_OBJECT_UNINITIALIZED,
|
1702 |
|
|
// An erroneous name. This indicates a parse error, to avoid
|
1703 |
|
|
// later errors about undefined references.
|
1704 |
|
|
NAMED_OBJECT_ERRONEOUS,
|
1705 |
|
|
// An unknown name. This is used for forward references. In a
|
1706 |
|
|
// correct program, these will all be resolved by the end of the
|
1707 |
|
|
// parse.
|
1708 |
|
|
NAMED_OBJECT_UNKNOWN,
|
1709 |
|
|
// A const.
|
1710 |
|
|
NAMED_OBJECT_CONST,
|
1711 |
|
|
// A type.
|
1712 |
|
|
NAMED_OBJECT_TYPE,
|
1713 |
|
|
// A forward type declaration.
|
1714 |
|
|
NAMED_OBJECT_TYPE_DECLARATION,
|
1715 |
|
|
// A var.
|
1716 |
|
|
NAMED_OBJECT_VAR,
|
1717 |
|
|
// A result variable in a function.
|
1718 |
|
|
NAMED_OBJECT_RESULT_VAR,
|
1719 |
|
|
// The blank identifier--the special variable named _.
|
1720 |
|
|
NAMED_OBJECT_SINK,
|
1721 |
|
|
// A func.
|
1722 |
|
|
NAMED_OBJECT_FUNC,
|
1723 |
|
|
// A forward func declaration.
|
1724 |
|
|
NAMED_OBJECT_FUNC_DECLARATION,
|
1725 |
|
|
// A package.
|
1726 |
|
|
NAMED_OBJECT_PACKAGE
|
1727 |
|
|
};
|
1728 |
|
|
|
1729 |
|
|
// Return the classification.
|
1730 |
|
|
Classification
|
1731 |
|
|
classification() const
|
1732 |
|
|
{ return this->classification_; }
|
1733 |
|
|
|
1734 |
|
|
// Classifiers.
|
1735 |
|
|
|
1736 |
|
|
bool
|
1737 |
|
|
is_erroneous() const
|
1738 |
|
|
{ return this->classification_ == NAMED_OBJECT_ERRONEOUS; }
|
1739 |
|
|
|
1740 |
|
|
bool
|
1741 |
|
|
is_unknown() const
|
1742 |
|
|
{ return this->classification_ == NAMED_OBJECT_UNKNOWN; }
|
1743 |
|
|
|
1744 |
|
|
bool
|
1745 |
|
|
is_const() const
|
1746 |
|
|
{ return this->classification_ == NAMED_OBJECT_CONST; }
|
1747 |
|
|
|
1748 |
|
|
bool
|
1749 |
|
|
is_type() const
|
1750 |
|
|
{ return this->classification_ == NAMED_OBJECT_TYPE; }
|
1751 |
|
|
|
1752 |
|
|
bool
|
1753 |
|
|
is_type_declaration() const
|
1754 |
|
|
{ return this->classification_ == NAMED_OBJECT_TYPE_DECLARATION; }
|
1755 |
|
|
|
1756 |
|
|
bool
|
1757 |
|
|
is_variable() const
|
1758 |
|
|
{ return this->classification_ == NAMED_OBJECT_VAR; }
|
1759 |
|
|
|
1760 |
|
|
bool
|
1761 |
|
|
is_result_variable() const
|
1762 |
|
|
{ return this->classification_ == NAMED_OBJECT_RESULT_VAR; }
|
1763 |
|
|
|
1764 |
|
|
bool
|
1765 |
|
|
is_sink() const
|
1766 |
|
|
{ return this->classification_ == NAMED_OBJECT_SINK; }
|
1767 |
|
|
|
1768 |
|
|
bool
|
1769 |
|
|
is_function() const
|
1770 |
|
|
{ return this->classification_ == NAMED_OBJECT_FUNC; }
|
1771 |
|
|
|
1772 |
|
|
bool
|
1773 |
|
|
is_function_declaration() const
|
1774 |
|
|
{ return this->classification_ == NAMED_OBJECT_FUNC_DECLARATION; }
|
1775 |
|
|
|
1776 |
|
|
bool
|
1777 |
|
|
is_package() const
|
1778 |
|
|
{ return this->classification_ == NAMED_OBJECT_PACKAGE; }
|
1779 |
|
|
|
1780 |
|
|
// Creators.
|
1781 |
|
|
|
1782 |
|
|
static Named_object*
|
1783 |
|
|
make_erroneous_name(const std::string& name)
|
1784 |
|
|
{ return new Named_object(name, NULL, NAMED_OBJECT_ERRONEOUS); }
|
1785 |
|
|
|
1786 |
|
|
static Named_object*
|
1787 |
|
|
make_unknown_name(const std::string& name, Location);
|
1788 |
|
|
|
1789 |
|
|
static Named_object*
|
1790 |
|
|
make_constant(const Typed_identifier&, const Package*, Expression*,
|
1791 |
|
|
int iota_value);
|
1792 |
|
|
|
1793 |
|
|
static Named_object*
|
1794 |
|
|
make_type(const std::string&, const Package*, Type*, Location);
|
1795 |
|
|
|
1796 |
|
|
static Named_object*
|
1797 |
|
|
make_type_declaration(const std::string&, const Package*, Location);
|
1798 |
|
|
|
1799 |
|
|
static Named_object*
|
1800 |
|
|
make_variable(const std::string&, const Package*, Variable*);
|
1801 |
|
|
|
1802 |
|
|
static Named_object*
|
1803 |
|
|
make_result_variable(const std::string&, Result_variable*);
|
1804 |
|
|
|
1805 |
|
|
static Named_object*
|
1806 |
|
|
make_sink();
|
1807 |
|
|
|
1808 |
|
|
static Named_object*
|
1809 |
|
|
make_function(const std::string&, const Package*, Function*);
|
1810 |
|
|
|
1811 |
|
|
static Named_object*
|
1812 |
|
|
make_function_declaration(const std::string&, const Package*, Function_type*,
|
1813 |
|
|
Location);
|
1814 |
|
|
|
1815 |
|
|
static Named_object*
|
1816 |
|
|
make_package(const std::string& alias, Package* package);
|
1817 |
|
|
|
1818 |
|
|
// Getters.
|
1819 |
|
|
|
1820 |
|
|
Unknown_name*
|
1821 |
|
|
unknown_value()
|
1822 |
|
|
{
|
1823 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
|
1824 |
|
|
return this->u_.unknown_value;
|
1825 |
|
|
}
|
1826 |
|
|
|
1827 |
|
|
const Unknown_name*
|
1828 |
|
|
unknown_value() const
|
1829 |
|
|
{
|
1830 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_UNKNOWN);
|
1831 |
|
|
return this->u_.unknown_value;
|
1832 |
|
|
}
|
1833 |
|
|
|
1834 |
|
|
Named_constant*
|
1835 |
|
|
const_value()
|
1836 |
|
|
{
|
1837 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_CONST);
|
1838 |
|
|
return this->u_.const_value;
|
1839 |
|
|
}
|
1840 |
|
|
|
1841 |
|
|
const Named_constant*
|
1842 |
|
|
const_value() const
|
1843 |
|
|
{
|
1844 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_CONST);
|
1845 |
|
|
return this->u_.const_value;
|
1846 |
|
|
}
|
1847 |
|
|
|
1848 |
|
|
Named_type*
|
1849 |
|
|
type_value()
|
1850 |
|
|
{
|
1851 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_TYPE);
|
1852 |
|
|
return this->u_.type_value;
|
1853 |
|
|
}
|
1854 |
|
|
|
1855 |
|
|
const Named_type*
|
1856 |
|
|
type_value() const
|
1857 |
|
|
{
|
1858 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_TYPE);
|
1859 |
|
|
return this->u_.type_value;
|
1860 |
|
|
}
|
1861 |
|
|
|
1862 |
|
|
Type_declaration*
|
1863 |
|
|
type_declaration_value()
|
1864 |
|
|
{
|
1865 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
|
1866 |
|
|
return this->u_.type_declaration;
|
1867 |
|
|
}
|
1868 |
|
|
|
1869 |
|
|
const Type_declaration*
|
1870 |
|
|
type_declaration_value() const
|
1871 |
|
|
{
|
1872 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_TYPE_DECLARATION);
|
1873 |
|
|
return this->u_.type_declaration;
|
1874 |
|
|
}
|
1875 |
|
|
|
1876 |
|
|
Variable*
|
1877 |
|
|
var_value()
|
1878 |
|
|
{
|
1879 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_VAR);
|
1880 |
|
|
return this->u_.var_value;
|
1881 |
|
|
}
|
1882 |
|
|
|
1883 |
|
|
const Variable*
|
1884 |
|
|
var_value() const
|
1885 |
|
|
{
|
1886 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_VAR);
|
1887 |
|
|
return this->u_.var_value;
|
1888 |
|
|
}
|
1889 |
|
|
|
1890 |
|
|
Result_variable*
|
1891 |
|
|
result_var_value()
|
1892 |
|
|
{
|
1893 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
|
1894 |
|
|
return this->u_.result_var_value;
|
1895 |
|
|
}
|
1896 |
|
|
|
1897 |
|
|
const Result_variable*
|
1898 |
|
|
result_var_value() const
|
1899 |
|
|
{
|
1900 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_RESULT_VAR);
|
1901 |
|
|
return this->u_.result_var_value;
|
1902 |
|
|
}
|
1903 |
|
|
|
1904 |
|
|
Function*
|
1905 |
|
|
func_value()
|
1906 |
|
|
{
|
1907 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_FUNC);
|
1908 |
|
|
return this->u_.func_value;
|
1909 |
|
|
}
|
1910 |
|
|
|
1911 |
|
|
const Function*
|
1912 |
|
|
func_value() const
|
1913 |
|
|
{
|
1914 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_FUNC);
|
1915 |
|
|
return this->u_.func_value;
|
1916 |
|
|
}
|
1917 |
|
|
|
1918 |
|
|
Function_declaration*
|
1919 |
|
|
func_declaration_value()
|
1920 |
|
|
{
|
1921 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
|
1922 |
|
|
return this->u_.func_declaration_value;
|
1923 |
|
|
}
|
1924 |
|
|
|
1925 |
|
|
const Function_declaration*
|
1926 |
|
|
func_declaration_value() const
|
1927 |
|
|
{
|
1928 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_FUNC_DECLARATION);
|
1929 |
|
|
return this->u_.func_declaration_value;
|
1930 |
|
|
}
|
1931 |
|
|
|
1932 |
|
|
Package*
|
1933 |
|
|
package_value()
|
1934 |
|
|
{
|
1935 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
|
1936 |
|
|
return this->u_.package_value;
|
1937 |
|
|
}
|
1938 |
|
|
|
1939 |
|
|
const Package*
|
1940 |
|
|
package_value() const
|
1941 |
|
|
{
|
1942 |
|
|
go_assert(this->classification_ == NAMED_OBJECT_PACKAGE);
|
1943 |
|
|
return this->u_.package_value;
|
1944 |
|
|
}
|
1945 |
|
|
|
1946 |
|
|
const std::string&
|
1947 |
|
|
name() const
|
1948 |
|
|
{ return this->name_; }
|
1949 |
|
|
|
1950 |
|
|
// Return the name to use in an error message. The difference is
|
1951 |
|
|
// that if this Named_object is defined in a different package, this
|
1952 |
|
|
// will return PACKAGE.NAME.
|
1953 |
|
|
std::string
|
1954 |
|
|
message_name() const;
|
1955 |
|
|
|
1956 |
|
|
const Package*
|
1957 |
|
|
package() const
|
1958 |
|
|
{ return this->package_; }
|
1959 |
|
|
|
1960 |
|
|
// Resolve an unknown value if possible. This returns the same
|
1961 |
|
|
// Named_object or a new one.
|
1962 |
|
|
Named_object*
|
1963 |
|
|
resolve()
|
1964 |
|
|
{
|
1965 |
|
|
Named_object* ret = this;
|
1966 |
|
|
if (this->is_unknown())
|
1967 |
|
|
{
|
1968 |
|
|
Named_object* r = this->unknown_value()->real_named_object();
|
1969 |
|
|
if (r != NULL)
|
1970 |
|
|
ret = r;
|
1971 |
|
|
}
|
1972 |
|
|
return ret;
|
1973 |
|
|
}
|
1974 |
|
|
|
1975 |
|
|
const Named_object*
|
1976 |
|
|
resolve() const
|
1977 |
|
|
{
|
1978 |
|
|
const Named_object* ret = this;
|
1979 |
|
|
if (this->is_unknown())
|
1980 |
|
|
{
|
1981 |
|
|
const Named_object* r = this->unknown_value()->real_named_object();
|
1982 |
|
|
if (r != NULL)
|
1983 |
|
|
ret = r;
|
1984 |
|
|
}
|
1985 |
|
|
return ret;
|
1986 |
|
|
}
|
1987 |
|
|
|
1988 |
|
|
// The location where this object was defined or referenced.
|
1989 |
|
|
Location
|
1990 |
|
|
location() const;
|
1991 |
|
|
|
1992 |
|
|
// Convert a variable to the backend representation.
|
1993 |
|
|
Bvariable*
|
1994 |
|
|
get_backend_variable(Gogo*, Named_object* function);
|
1995 |
|
|
|
1996 |
|
|
// Return a tree for the external identifier for this object.
|
1997 |
|
|
tree
|
1998 |
|
|
get_id(Gogo*);
|
1999 |
|
|
|
2000 |
|
|
// Return a tree representing this object.
|
2001 |
|
|
tree
|
2002 |
|
|
get_tree(Gogo*, Named_object* function);
|
2003 |
|
|
|
2004 |
|
|
// Define a type declaration.
|
2005 |
|
|
void
|
2006 |
|
|
set_type_value(Named_type*);
|
2007 |
|
|
|
2008 |
|
|
// Define a function declaration.
|
2009 |
|
|
void
|
2010 |
|
|
set_function_value(Function*);
|
2011 |
|
|
|
2012 |
|
|
// Declare an unknown name as a type declaration.
|
2013 |
|
|
void
|
2014 |
|
|
declare_as_type();
|
2015 |
|
|
|
2016 |
|
|
// Export this object.
|
2017 |
|
|
void
|
2018 |
|
|
export_named_object(Export*) const;
|
2019 |
|
|
|
2020 |
|
|
private:
|
2021 |
|
|
Named_object(const std::string&, const Package*, Classification);
|
2022 |
|
|
|
2023 |
|
|
// The name of the object.
|
2024 |
|
|
std::string name_;
|
2025 |
|
|
// The package that this object is in. This is NULL if it is in the
|
2026 |
|
|
// file we are compiling.
|
2027 |
|
|
const Package* package_;
|
2028 |
|
|
// The type of object this is.
|
2029 |
|
|
Classification classification_;
|
2030 |
|
|
// The real data.
|
2031 |
|
|
union
|
2032 |
|
|
{
|
2033 |
|
|
Unknown_name* unknown_value;
|
2034 |
|
|
Named_constant* const_value;
|
2035 |
|
|
Named_type* type_value;
|
2036 |
|
|
Type_declaration* type_declaration;
|
2037 |
|
|
Variable* var_value;
|
2038 |
|
|
Result_variable* result_var_value;
|
2039 |
|
|
Function* func_value;
|
2040 |
|
|
Function_declaration* func_declaration_value;
|
2041 |
|
|
Package* package_value;
|
2042 |
|
|
} u_;
|
2043 |
|
|
// The DECL tree for this object if we have already converted it.
|
2044 |
|
|
tree tree_;
|
2045 |
|
|
};
|
2046 |
|
|
|
2047 |
|
|
// A binding contour. This binds names to objects.
|
2048 |
|
|
|
2049 |
|
|
class Bindings
|
2050 |
|
|
{
|
2051 |
|
|
public:
|
2052 |
|
|
// Type for mapping from names to objects.
|
2053 |
|
|
typedef Unordered_map(std::string, Named_object*) Contour;
|
2054 |
|
|
|
2055 |
|
|
Bindings(Bindings* enclosing);
|
2056 |
|
|
|
2057 |
|
|
// Add an erroneous name.
|
2058 |
|
|
Named_object*
|
2059 |
|
|
add_erroneous_name(const std::string& name)
|
2060 |
|
|
{ return this->add_named_object(Named_object::make_erroneous_name(name)); }
|
2061 |
|
|
|
2062 |
|
|
// Add an unknown name.
|
2063 |
|
|
Named_object*
|
2064 |
|
|
add_unknown_name(const std::string& name, Location location)
|
2065 |
|
|
{
|
2066 |
|
|
return this->add_named_object(Named_object::make_unknown_name(name,
|
2067 |
|
|
location));
|
2068 |
|
|
}
|
2069 |
|
|
|
2070 |
|
|
// Add a constant.
|
2071 |
|
|
Named_object*
|
2072 |
|
|
add_constant(const Typed_identifier& tid, const Package* package,
|
2073 |
|
|
Expression* expr, int iota_value)
|
2074 |
|
|
{
|
2075 |
|
|
return this->add_named_object(Named_object::make_constant(tid, package,
|
2076 |
|
|
expr,
|
2077 |
|
|
iota_value));
|
2078 |
|
|
}
|
2079 |
|
|
|
2080 |
|
|
// Add a type.
|
2081 |
|
|
Named_object*
|
2082 |
|
|
add_type(const std::string& name, const Package* package, Type* type,
|
2083 |
|
|
Location location)
|
2084 |
|
|
{
|
2085 |
|
|
return this->add_named_object(Named_object::make_type(name, package, type,
|
2086 |
|
|
location));
|
2087 |
|
|
}
|
2088 |
|
|
|
2089 |
|
|
// Add a named type. This is used for builtin types, and to add an
|
2090 |
|
|
// imported type to the global scope.
|
2091 |
|
|
Named_object*
|
2092 |
|
|
add_named_type(Named_type* named_type);
|
2093 |
|
|
|
2094 |
|
|
// Add a type declaration.
|
2095 |
|
|
Named_object*
|
2096 |
|
|
add_type_declaration(const std::string& name, const Package* package,
|
2097 |
|
|
Location location)
|
2098 |
|
|
{
|
2099 |
|
|
Named_object* no = Named_object::make_type_declaration(name, package,
|
2100 |
|
|
location);
|
2101 |
|
|
return this->add_named_object(no);
|
2102 |
|
|
}
|
2103 |
|
|
|
2104 |
|
|
// Add a variable.
|
2105 |
|
|
Named_object*
|
2106 |
|
|
add_variable(const std::string& name, const Package* package,
|
2107 |
|
|
Variable* variable)
|
2108 |
|
|
{
|
2109 |
|
|
return this->add_named_object(Named_object::make_variable(name, package,
|
2110 |
|
|
variable));
|
2111 |
|
|
}
|
2112 |
|
|
|
2113 |
|
|
// Add a result variable.
|
2114 |
|
|
Named_object*
|
2115 |
|
|
add_result_variable(const std::string& name, Result_variable* result)
|
2116 |
|
|
{
|
2117 |
|
|
return this->add_named_object(Named_object::make_result_variable(name,
|
2118 |
|
|
result));
|
2119 |
|
|
}
|
2120 |
|
|
|
2121 |
|
|
// Add a function.
|
2122 |
|
|
Named_object*
|
2123 |
|
|
add_function(const std::string& name, const Package*, Function* function);
|
2124 |
|
|
|
2125 |
|
|
// Add a function declaration.
|
2126 |
|
|
Named_object*
|
2127 |
|
|
add_function_declaration(const std::string& name, const Package* package,
|
2128 |
|
|
Function_type* type, Location location);
|
2129 |
|
|
|
2130 |
|
|
// Add a package. The location is the location of the import
|
2131 |
|
|
// statement.
|
2132 |
|
|
Named_object*
|
2133 |
|
|
add_package(const std::string& alias, Package* package)
|
2134 |
|
|
{
|
2135 |
|
|
Named_object* no = Named_object::make_package(alias, package);
|
2136 |
|
|
return this->add_named_object(no);
|
2137 |
|
|
}
|
2138 |
|
|
|
2139 |
|
|
// Define a type which was already declared.
|
2140 |
|
|
void
|
2141 |
|
|
define_type(Named_object*, Named_type*);
|
2142 |
|
|
|
2143 |
|
|
// Add a method to the list of objects. This is not added to the
|
2144 |
|
|
// lookup table.
|
2145 |
|
|
void
|
2146 |
|
|
add_method(Named_object*);
|
2147 |
|
|
|
2148 |
|
|
// Add a named object to this binding.
|
2149 |
|
|
Named_object*
|
2150 |
|
|
add_named_object(Named_object* no)
|
2151 |
|
|
{ return this->add_named_object_to_contour(&this->bindings_, no); }
|
2152 |
|
|
|
2153 |
|
|
// Clear all names in file scope from the bindings.
|
2154 |
|
|
void
|
2155 |
|
|
clear_file_scope();
|
2156 |
|
|
|
2157 |
|
|
// Look up a name in this binding contour and in any enclosing
|
2158 |
|
|
// binding contours. This returns NULL if the name is not found.
|
2159 |
|
|
Named_object*
|
2160 |
|
|
lookup(const std::string&) const;
|
2161 |
|
|
|
2162 |
|
|
// Look up a name in this binding contour without looking in any
|
2163 |
|
|
// enclosing binding contours. Returns NULL if the name is not found.
|
2164 |
|
|
Named_object*
|
2165 |
|
|
lookup_local(const std::string&) const;
|
2166 |
|
|
|
2167 |
|
|
// Remove a name.
|
2168 |
|
|
void
|
2169 |
|
|
remove_binding(Named_object*);
|
2170 |
|
|
|
2171 |
|
|
// Mark all variables as used. This is used for some types of parse
|
2172 |
|
|
// error.
|
2173 |
|
|
void
|
2174 |
|
|
mark_locals_used();
|
2175 |
|
|
|
2176 |
|
|
// Traverse the tree. See the Traverse class.
|
2177 |
|
|
int
|
2178 |
|
|
traverse(Traverse*, bool is_global);
|
2179 |
|
|
|
2180 |
|
|
// Iterate over definitions. This does not include things which
|
2181 |
|
|
// were only declared.
|
2182 |
|
|
|
2183 |
|
|
typedef std::vector<Named_object*>::const_iterator
|
2184 |
|
|
const_definitions_iterator;
|
2185 |
|
|
|
2186 |
|
|
const_definitions_iterator
|
2187 |
|
|
begin_definitions() const
|
2188 |
|
|
{ return this->named_objects_.begin(); }
|
2189 |
|
|
|
2190 |
|
|
const_definitions_iterator
|
2191 |
|
|
end_definitions() const
|
2192 |
|
|
{ return this->named_objects_.end(); }
|
2193 |
|
|
|
2194 |
|
|
// Return the number of definitions.
|
2195 |
|
|
size_t
|
2196 |
|
|
size_definitions() const
|
2197 |
|
|
{ return this->named_objects_.size(); }
|
2198 |
|
|
|
2199 |
|
|
// Return whether there are no definitions.
|
2200 |
|
|
bool
|
2201 |
|
|
empty_definitions() const
|
2202 |
|
|
{ return this->named_objects_.empty(); }
|
2203 |
|
|
|
2204 |
|
|
// Iterate over declarations. This is everything that has been
|
2205 |
|
|
// declared, which includes everything which has been defined.
|
2206 |
|
|
|
2207 |
|
|
typedef Contour::const_iterator const_declarations_iterator;
|
2208 |
|
|
|
2209 |
|
|
const_declarations_iterator
|
2210 |
|
|
begin_declarations() const
|
2211 |
|
|
{ return this->bindings_.begin(); }
|
2212 |
|
|
|
2213 |
|
|
const_declarations_iterator
|
2214 |
|
|
end_declarations() const
|
2215 |
|
|
{ return this->bindings_.end(); }
|
2216 |
|
|
|
2217 |
|
|
// Return the number of declarations.
|
2218 |
|
|
size_t
|
2219 |
|
|
size_declarations() const
|
2220 |
|
|
{ return this->bindings_.size(); }
|
2221 |
|
|
|
2222 |
|
|
// Return whether there are no declarations.
|
2223 |
|
|
bool
|
2224 |
|
|
empty_declarations() const
|
2225 |
|
|
{ return this->bindings_.empty(); }
|
2226 |
|
|
|
2227 |
|
|
// Return the first declaration.
|
2228 |
|
|
Named_object*
|
2229 |
|
|
first_declaration()
|
2230 |
|
|
{ return this->bindings_.empty() ? NULL : this->bindings_.begin()->second; }
|
2231 |
|
|
|
2232 |
|
|
private:
|
2233 |
|
|
Named_object*
|
2234 |
|
|
add_named_object_to_contour(Contour*, Named_object*);
|
2235 |
|
|
|
2236 |
|
|
Named_object*
|
2237 |
|
|
new_definition(Named_object*, Named_object*);
|
2238 |
|
|
|
2239 |
|
|
// Enclosing bindings.
|
2240 |
|
|
Bindings* enclosing_;
|
2241 |
|
|
// The list of objects.
|
2242 |
|
|
std::vector<Named_object*> named_objects_;
|
2243 |
|
|
// The mapping from names to objects.
|
2244 |
|
|
Contour bindings_;
|
2245 |
|
|
};
|
2246 |
|
|
|
2247 |
|
|
// A label.
|
2248 |
|
|
|
2249 |
|
|
class Label
|
2250 |
|
|
{
|
2251 |
|
|
public:
|
2252 |
|
|
Label(const std::string& name)
|
2253 |
|
|
: name_(name), location_(Linemap::unknown_location()), snapshot_(NULL),
|
2254 |
|
|
refs_(), is_used_(false), blabel_(NULL)
|
2255 |
|
|
{ }
|
2256 |
|
|
|
2257 |
|
|
// Return the label's name.
|
2258 |
|
|
const std::string&
|
2259 |
|
|
name() const
|
2260 |
|
|
{ return this->name_; }
|
2261 |
|
|
|
2262 |
|
|
// Return whether the label has been defined.
|
2263 |
|
|
bool
|
2264 |
|
|
is_defined() const
|
2265 |
|
|
{ return !Linemap::is_unknown_location(this->location_); }
|
2266 |
|
|
|
2267 |
|
|
// Return whether the label has been used.
|
2268 |
|
|
bool
|
2269 |
|
|
is_used() const
|
2270 |
|
|
{ return this->is_used_; }
|
2271 |
|
|
|
2272 |
|
|
// Record that the label is used.
|
2273 |
|
|
void
|
2274 |
|
|
set_is_used()
|
2275 |
|
|
{ this->is_used_ = true; }
|
2276 |
|
|
|
2277 |
|
|
// Return the location of the definition.
|
2278 |
|
|
Location
|
2279 |
|
|
location() const
|
2280 |
|
|
{ return this->location_; }
|
2281 |
|
|
|
2282 |
|
|
// Return the bindings snapshot.
|
2283 |
|
|
Bindings_snapshot*
|
2284 |
|
|
snapshot() const
|
2285 |
|
|
{ return this->snapshot_; }
|
2286 |
|
|
|
2287 |
|
|
// Add a snapshot of a goto which refers to this label.
|
2288 |
|
|
void
|
2289 |
|
|
add_snapshot_ref(Bindings_snapshot* snapshot)
|
2290 |
|
|
{
|
2291 |
|
|
go_assert(Linemap::is_unknown_location(this->location_));
|
2292 |
|
|
this->refs_.push_back(snapshot);
|
2293 |
|
|
}
|
2294 |
|
|
|
2295 |
|
|
// Return the list of snapshots of goto statements which refer to
|
2296 |
|
|
// this label.
|
2297 |
|
|
const std::vector<Bindings_snapshot*>&
|
2298 |
|
|
refs() const
|
2299 |
|
|
{ return this->refs_; }
|
2300 |
|
|
|
2301 |
|
|
// Clear the references.
|
2302 |
|
|
void
|
2303 |
|
|
clear_refs();
|
2304 |
|
|
|
2305 |
|
|
// Define the label at LOCATION with the given bindings snapshot.
|
2306 |
|
|
void
|
2307 |
|
|
define(Location location, Bindings_snapshot* snapshot)
|
2308 |
|
|
{
|
2309 |
|
|
go_assert(Linemap::is_unknown_location(this->location_)
|
2310 |
|
|
&& this->snapshot_ == NULL);
|
2311 |
|
|
this->location_ = location;
|
2312 |
|
|
this->snapshot_ = snapshot;
|
2313 |
|
|
}
|
2314 |
|
|
|
2315 |
|
|
// Return the backend representation for this label.
|
2316 |
|
|
Blabel*
|
2317 |
|
|
get_backend_label(Translate_context*);
|
2318 |
|
|
|
2319 |
|
|
// Return an expression for the address of this label. This is used
|
2320 |
|
|
// to get the return address of a deferred function to see whether
|
2321 |
|
|
// the function may call recover.
|
2322 |
|
|
Bexpression*
|
2323 |
|
|
get_addr(Translate_context*, Location location);
|
2324 |
|
|
|
2325 |
|
|
private:
|
2326 |
|
|
// The name of the label.
|
2327 |
|
|
std::string name_;
|
2328 |
|
|
// The location of the definition. This is 0 if the label has not
|
2329 |
|
|
// yet been defined.
|
2330 |
|
|
Location location_;
|
2331 |
|
|
// A snapshot of the set of bindings defined at this label, used to
|
2332 |
|
|
// issue errors about invalid goto statements.
|
2333 |
|
|
Bindings_snapshot* snapshot_;
|
2334 |
|
|
// A list of snapshots of goto statements which refer to this label.
|
2335 |
|
|
std::vector<Bindings_snapshot*> refs_;
|
2336 |
|
|
// Whether the label has been used.
|
2337 |
|
|
bool is_used_;
|
2338 |
|
|
// The backend representation.
|
2339 |
|
|
Blabel* blabel_;
|
2340 |
|
|
};
|
2341 |
|
|
|
2342 |
|
|
// An unnamed label. These are used when lowering loops.
|
2343 |
|
|
|
2344 |
|
|
class Unnamed_label
|
2345 |
|
|
{
|
2346 |
|
|
public:
|
2347 |
|
|
Unnamed_label(Location location)
|
2348 |
|
|
: location_(location), blabel_(NULL)
|
2349 |
|
|
{ }
|
2350 |
|
|
|
2351 |
|
|
// Get the location where the label is defined.
|
2352 |
|
|
Location
|
2353 |
|
|
location() const
|
2354 |
|
|
{ return this->location_; }
|
2355 |
|
|
|
2356 |
|
|
// Set the location where the label is defined.
|
2357 |
|
|
void
|
2358 |
|
|
set_location(Location location)
|
2359 |
|
|
{ this->location_ = location; }
|
2360 |
|
|
|
2361 |
|
|
// Return a statement which defines this label.
|
2362 |
|
|
Bstatement*
|
2363 |
|
|
get_definition(Translate_context*);
|
2364 |
|
|
|
2365 |
|
|
// Return a goto to this label from LOCATION.
|
2366 |
|
|
Bstatement*
|
2367 |
|
|
get_goto(Translate_context*, Location location);
|
2368 |
|
|
|
2369 |
|
|
private:
|
2370 |
|
|
// Return the backend representation.
|
2371 |
|
|
Blabel*
|
2372 |
|
|
get_blabel(Translate_context*);
|
2373 |
|
|
|
2374 |
|
|
// The location where the label is defined.
|
2375 |
|
|
Location location_;
|
2376 |
|
|
// The backend representation of this label.
|
2377 |
|
|
Blabel* blabel_;
|
2378 |
|
|
};
|
2379 |
|
|
|
2380 |
|
|
// An imported package.
|
2381 |
|
|
|
2382 |
|
|
class Package
|
2383 |
|
|
{
|
2384 |
|
|
public:
|
2385 |
|
|
Package(const std::string& name, const std::string& unique_prefix,
|
2386 |
|
|
Location location);
|
2387 |
|
|
|
2388 |
|
|
// The real name of this package. This may be different from the
|
2389 |
|
|
// name in the associated Named_object if the import statement used
|
2390 |
|
|
// an alias.
|
2391 |
|
|
const std::string&
|
2392 |
|
|
name() const
|
2393 |
|
|
{ return this->name_; }
|
2394 |
|
|
|
2395 |
|
|
// Return the location of the import statement.
|
2396 |
|
|
Location
|
2397 |
|
|
location() const
|
2398 |
|
|
{ return this->location_; }
|
2399 |
|
|
|
2400 |
|
|
// Get the unique prefix used for all symbols exported from this
|
2401 |
|
|
// package.
|
2402 |
|
|
const std::string&
|
2403 |
|
|
unique_prefix() const
|
2404 |
|
|
{
|
2405 |
|
|
go_assert(!this->unique_prefix_.empty());
|
2406 |
|
|
return this->unique_prefix_;
|
2407 |
|
|
}
|
2408 |
|
|
|
2409 |
|
|
// The priority of this package. The init function of packages with
|
2410 |
|
|
// lower priority must be run before the init function of packages
|
2411 |
|
|
// with higher priority.
|
2412 |
|
|
int
|
2413 |
|
|
priority() const
|
2414 |
|
|
{ return this->priority_; }
|
2415 |
|
|
|
2416 |
|
|
// Set the priority.
|
2417 |
|
|
void
|
2418 |
|
|
set_priority(int priority);
|
2419 |
|
|
|
2420 |
|
|
// Return the bindings.
|
2421 |
|
|
Bindings*
|
2422 |
|
|
bindings()
|
2423 |
|
|
{ return this->bindings_; }
|
2424 |
|
|
|
2425 |
|
|
// Whether some symbol from the package was used.
|
2426 |
|
|
bool
|
2427 |
|
|
used() const
|
2428 |
|
|
{ return this->used_; }
|
2429 |
|
|
|
2430 |
|
|
// Note that some symbol from this package was used.
|
2431 |
|
|
void
|
2432 |
|
|
set_used() const
|
2433 |
|
|
{ this->used_ = true; }
|
2434 |
|
|
|
2435 |
|
|
// Clear the used field for the next file.
|
2436 |
|
|
void
|
2437 |
|
|
clear_used()
|
2438 |
|
|
{ this->used_ = false; }
|
2439 |
|
|
|
2440 |
|
|
// Whether this package was imported in the current file.
|
2441 |
|
|
bool
|
2442 |
|
|
is_imported() const
|
2443 |
|
|
{ return this->is_imported_; }
|
2444 |
|
|
|
2445 |
|
|
// Note that this package was imported in the current file.
|
2446 |
|
|
void
|
2447 |
|
|
set_is_imported()
|
2448 |
|
|
{ this->is_imported_ = true; }
|
2449 |
|
|
|
2450 |
|
|
// Clear the imported field for the next file.
|
2451 |
|
|
void
|
2452 |
|
|
clear_is_imported()
|
2453 |
|
|
{ this->is_imported_ = false; }
|
2454 |
|
|
|
2455 |
|
|
// Whether this package was imported with a name of "_".
|
2456 |
|
|
bool
|
2457 |
|
|
uses_sink_alias() const
|
2458 |
|
|
{ return this->uses_sink_alias_; }
|
2459 |
|
|
|
2460 |
|
|
// Note that this package was imported with a name of "_".
|
2461 |
|
|
void
|
2462 |
|
|
set_uses_sink_alias()
|
2463 |
|
|
{ this->uses_sink_alias_ = true; }
|
2464 |
|
|
|
2465 |
|
|
// Clear the sink alias field for the next file.
|
2466 |
|
|
void
|
2467 |
|
|
clear_uses_sink_alias()
|
2468 |
|
|
{ this->uses_sink_alias_ = false; }
|
2469 |
|
|
|
2470 |
|
|
// Look up a name in the package. Returns NULL if the name is not
|
2471 |
|
|
// found.
|
2472 |
|
|
Named_object*
|
2473 |
|
|
lookup(const std::string& name) const
|
2474 |
|
|
{ return this->bindings_->lookup(name); }
|
2475 |
|
|
|
2476 |
|
|
// Set the location of the package. This is used if it is seen in a
|
2477 |
|
|
// different import before it is really imported.
|
2478 |
|
|
void
|
2479 |
|
|
set_location(Location location)
|
2480 |
|
|
{ this->location_ = location; }
|
2481 |
|
|
|
2482 |
|
|
// Add a constant to the package.
|
2483 |
|
|
Named_object*
|
2484 |
|
|
add_constant(const Typed_identifier& tid, Expression* expr)
|
2485 |
|
|
{ return this->bindings_->add_constant(tid, this, expr, 0); }
|
2486 |
|
|
|
2487 |
|
|
// Add a type to the package.
|
2488 |
|
|
Named_object*
|
2489 |
|
|
add_type(const std::string& name, Type* type, Location location)
|
2490 |
|
|
{ return this->bindings_->add_type(name, this, type, location); }
|
2491 |
|
|
|
2492 |
|
|
// Add a type declaration to the package.
|
2493 |
|
|
Named_object*
|
2494 |
|
|
add_type_declaration(const std::string& name, Location location)
|
2495 |
|
|
{ return this->bindings_->add_type_declaration(name, this, location); }
|
2496 |
|
|
|
2497 |
|
|
// Add a variable to the package.
|
2498 |
|
|
Named_object*
|
2499 |
|
|
add_variable(const std::string& name, Variable* variable)
|
2500 |
|
|
{ return this->bindings_->add_variable(name, this, variable); }
|
2501 |
|
|
|
2502 |
|
|
// Add a function declaration to the package.
|
2503 |
|
|
Named_object*
|
2504 |
|
|
add_function_declaration(const std::string& name, Function_type* type,
|
2505 |
|
|
Location loc)
|
2506 |
|
|
{ return this->bindings_->add_function_declaration(name, this, type, loc); }
|
2507 |
|
|
|
2508 |
|
|
// Determine types of constants.
|
2509 |
|
|
void
|
2510 |
|
|
determine_types();
|
2511 |
|
|
|
2512 |
|
|
private:
|
2513 |
|
|
// The real name of this package.
|
2514 |
|
|
std::string name_;
|
2515 |
|
|
// The unique prefix for all exported global symbols.
|
2516 |
|
|
std::string unique_prefix_;
|
2517 |
|
|
// The names in this package.
|
2518 |
|
|
Bindings* bindings_;
|
2519 |
|
|
// The priority of this package. A package has a priority higher
|
2520 |
|
|
// than the priority of all of the packages that it imports. This
|
2521 |
|
|
// is used to run init functions in the right order.
|
2522 |
|
|
int priority_;
|
2523 |
|
|
// The location of the import statement.
|
2524 |
|
|
Location location_;
|
2525 |
|
|
// True if some name from this package was used. This is mutable
|
2526 |
|
|
// because we can use a package even if we have a const pointer to
|
2527 |
|
|
// it.
|
2528 |
|
|
mutable bool used_;
|
2529 |
|
|
// True if this package was imported in the current file.
|
2530 |
|
|
bool is_imported_;
|
2531 |
|
|
// True if this package was imported with a name of "_".
|
2532 |
|
|
bool uses_sink_alias_;
|
2533 |
|
|
};
|
2534 |
|
|
|
2535 |
|
|
// Return codes for the traversal functions. This is not an enum
|
2536 |
|
|
// because we want to be able to declare traversal functions in other
|
2537 |
|
|
// header files without including this one.
|
2538 |
|
|
|
2539 |
|
|
// Continue traversal as usual.
|
2540 |
|
|
const int TRAVERSE_CONTINUE = -1;
|
2541 |
|
|
|
2542 |
|
|
// Exit traversal.
|
2543 |
|
|
const int TRAVERSE_EXIT = 0;
|
2544 |
|
|
|
2545 |
|
|
// Continue traversal, but skip components of the current object.
|
2546 |
|
|
// E.g., if this is returned by Traverse::statement, we do not
|
2547 |
|
|
// traverse the expressions in the statement even if
|
2548 |
|
|
// traverse_expressions is set in the traverse_mask.
|
2549 |
|
|
const int TRAVERSE_SKIP_COMPONENTS = 1;
|
2550 |
|
|
|
2551 |
|
|
// This class is used when traversing the parse tree. The caller uses
|
2552 |
|
|
// a subclass which overrides functions as desired.
|
2553 |
|
|
|
2554 |
|
|
class Traverse
|
2555 |
|
|
{
|
2556 |
|
|
public:
|
2557 |
|
|
// These bitmasks say what to traverse.
|
2558 |
|
|
static const unsigned int traverse_variables = 0x1;
|
2559 |
|
|
static const unsigned int traverse_constants = 0x2;
|
2560 |
|
|
static const unsigned int traverse_functions = 0x4;
|
2561 |
|
|
static const unsigned int traverse_blocks = 0x8;
|
2562 |
|
|
static const unsigned int traverse_statements = 0x10;
|
2563 |
|
|
static const unsigned int traverse_expressions = 0x20;
|
2564 |
|
|
static const unsigned int traverse_types = 0x40;
|
2565 |
|
|
|
2566 |
|
|
Traverse(unsigned int traverse_mask)
|
2567 |
|
|
: traverse_mask_(traverse_mask), types_seen_(NULL), expressions_seen_(NULL)
|
2568 |
|
|
{ }
|
2569 |
|
|
|
2570 |
|
|
virtual ~Traverse();
|
2571 |
|
|
|
2572 |
|
|
// The bitmask of what to traverse.
|
2573 |
|
|
unsigned int
|
2574 |
|
|
traverse_mask() const
|
2575 |
|
|
{ return this->traverse_mask_; }
|
2576 |
|
|
|
2577 |
|
|
// Record that we are going to traverse a type. This returns true
|
2578 |
|
|
// if the type has already been seen in this traversal. This is
|
2579 |
|
|
// required because types, unlike expressions, can form a circular
|
2580 |
|
|
// graph.
|
2581 |
|
|
bool
|
2582 |
|
|
remember_type(const Type*);
|
2583 |
|
|
|
2584 |
|
|
// Record that we are going to see an expression. This returns true
|
2585 |
|
|
// if the expression has already been seen in this traversal. This
|
2586 |
|
|
// is only needed for cases where multiple expressions can point to
|
2587 |
|
|
// a single one.
|
2588 |
|
|
bool
|
2589 |
|
|
remember_expression(const Expression*);
|
2590 |
|
|
|
2591 |
|
|
// These functions return one of the TRAVERSE codes defined above.
|
2592 |
|
|
|
2593 |
|
|
// If traverse_variables is set in the mask, this is called for
|
2594 |
|
|
// every variable in the tree.
|
2595 |
|
|
virtual int
|
2596 |
|
|
variable(Named_object*);
|
2597 |
|
|
|
2598 |
|
|
// If traverse_constants is set in the mask, this is called for
|
2599 |
|
|
// every named constant in the tree. The bool parameter is true for
|
2600 |
|
|
// a global constant.
|
2601 |
|
|
virtual int
|
2602 |
|
|
constant(Named_object*, bool);
|
2603 |
|
|
|
2604 |
|
|
// If traverse_functions is set in the mask, this is called for
|
2605 |
|
|
// every function in the tree.
|
2606 |
|
|
virtual int
|
2607 |
|
|
function(Named_object*);
|
2608 |
|
|
|
2609 |
|
|
// If traverse_blocks is set in the mask, this is called for every
|
2610 |
|
|
// block in the tree.
|
2611 |
|
|
virtual int
|
2612 |
|
|
block(Block*);
|
2613 |
|
|
|
2614 |
|
|
// If traverse_statements is set in the mask, this is called for
|
2615 |
|
|
// every statement in the tree.
|
2616 |
|
|
virtual int
|
2617 |
|
|
statement(Block*, size_t* index, Statement*);
|
2618 |
|
|
|
2619 |
|
|
// If traverse_expressions is set in the mask, this is called for
|
2620 |
|
|
// every expression in the tree.
|
2621 |
|
|
virtual int
|
2622 |
|
|
expression(Expression**);
|
2623 |
|
|
|
2624 |
|
|
// If traverse_types is set in the mask, this is called for every
|
2625 |
|
|
// type in the tree.
|
2626 |
|
|
virtual int
|
2627 |
|
|
type(Type*);
|
2628 |
|
|
|
2629 |
|
|
private:
|
2630 |
|
|
// A hash table for types we have seen during this traversal. Note
|
2631 |
|
|
// that this uses the default hash functions for pointers rather
|
2632 |
|
|
// than Type_hash_identical and Type_identical. This is because for
|
2633 |
|
|
// traversal we care about seeing a specific type structure. If
|
2634 |
|
|
// there are two separate instances of identical types, we want to
|
2635 |
|
|
// traverse both.
|
2636 |
|
|
typedef Unordered_set(const Type*) Types_seen;
|
2637 |
|
|
|
2638 |
|
|
typedef Unordered_set(const Expression*) Expressions_seen;
|
2639 |
|
|
|
2640 |
|
|
// Bitmask of what sort of objects to traverse.
|
2641 |
|
|
unsigned int traverse_mask_;
|
2642 |
|
|
// Types which have been seen in this traversal.
|
2643 |
|
|
Types_seen* types_seen_;
|
2644 |
|
|
// Expressions which have been seen in this traversal.
|
2645 |
|
|
Expressions_seen* expressions_seen_;
|
2646 |
|
|
};
|
2647 |
|
|
|
2648 |
|
|
// A class which makes it easier to insert new statements before the
|
2649 |
|
|
// current statement during a traversal.
|
2650 |
|
|
|
2651 |
|
|
class Statement_inserter
|
2652 |
|
|
{
|
2653 |
|
|
public:
|
2654 |
|
|
// Empty constructor.
|
2655 |
|
|
Statement_inserter()
|
2656 |
|
|
: block_(NULL), pindex_(NULL), gogo_(NULL), var_(NULL)
|
2657 |
|
|
{ }
|
2658 |
|
|
|
2659 |
|
|
// Constructor for a statement in a block.
|
2660 |
|
|
Statement_inserter(Block* block, size_t *pindex)
|
2661 |
|
|
: block_(block), pindex_(pindex), gogo_(NULL), var_(NULL)
|
2662 |
|
|
{ }
|
2663 |
|
|
|
2664 |
|
|
// Constructor for a global variable.
|
2665 |
|
|
Statement_inserter(Gogo* gogo, Variable* var)
|
2666 |
|
|
: block_(NULL), pindex_(NULL), gogo_(gogo), var_(var)
|
2667 |
|
|
{ go_assert(var->is_global()); }
|
2668 |
|
|
|
2669 |
|
|
// We use the default copy constructor and assignment operator.
|
2670 |
|
|
|
2671 |
|
|
// Insert S before the statement we are traversing, or before the
|
2672 |
|
|
// initialization expression of a global variable.
|
2673 |
|
|
void
|
2674 |
|
|
insert(Statement* s);
|
2675 |
|
|
|
2676 |
|
|
private:
|
2677 |
|
|
// The block that the statement is in.
|
2678 |
|
|
Block* block_;
|
2679 |
|
|
// The index of the statement that we are traversing.
|
2680 |
|
|
size_t* pindex_;
|
2681 |
|
|
// The IR, needed when looking at an initializer expression for a
|
2682 |
|
|
// global variable.
|
2683 |
|
|
Gogo* gogo_;
|
2684 |
|
|
// The global variable, when looking at an initializer expression.
|
2685 |
|
|
Variable* var_;
|
2686 |
|
|
};
|
2687 |
|
|
|
2688 |
|
|
// When translating the gogo IR into the backend data structure, this
|
2689 |
|
|
// is the context we pass down the blocks and statements.
|
2690 |
|
|
|
2691 |
|
|
class Translate_context
|
2692 |
|
|
{
|
2693 |
|
|
public:
|
2694 |
|
|
Translate_context(Gogo* gogo, Named_object* function, Block* block,
|
2695 |
|
|
Bblock* bblock)
|
2696 |
|
|
: gogo_(gogo), backend_(gogo->backend()), function_(function),
|
2697 |
|
|
block_(block), bblock_(bblock), is_const_(false)
|
2698 |
|
|
{ }
|
2699 |
|
|
|
2700 |
|
|
// Accessors.
|
2701 |
|
|
|
2702 |
|
|
Gogo*
|
2703 |
|
|
gogo()
|
2704 |
|
|
{ return this->gogo_; }
|
2705 |
|
|
|
2706 |
|
|
Backend*
|
2707 |
|
|
backend()
|
2708 |
|
|
{ return this->backend_; }
|
2709 |
|
|
|
2710 |
|
|
Named_object*
|
2711 |
|
|
function()
|
2712 |
|
|
{ return this->function_; }
|
2713 |
|
|
|
2714 |
|
|
Block*
|
2715 |
|
|
block()
|
2716 |
|
|
{ return this->block_; }
|
2717 |
|
|
|
2718 |
|
|
Bblock*
|
2719 |
|
|
bblock()
|
2720 |
|
|
{ return this->bblock_; }
|
2721 |
|
|
|
2722 |
|
|
bool
|
2723 |
|
|
is_const()
|
2724 |
|
|
{ return this->is_const_; }
|
2725 |
|
|
|
2726 |
|
|
// Make a constant context.
|
2727 |
|
|
void
|
2728 |
|
|
set_is_const()
|
2729 |
|
|
{ this->is_const_ = true; }
|
2730 |
|
|
|
2731 |
|
|
private:
|
2732 |
|
|
// The IR for the entire compilation unit.
|
2733 |
|
|
Gogo* gogo_;
|
2734 |
|
|
// The generator for the backend data structures.
|
2735 |
|
|
Backend* backend_;
|
2736 |
|
|
// The function we are currently translating. NULL if not in a
|
2737 |
|
|
// function, e.g., the initializer of a global variable.
|
2738 |
|
|
Named_object* function_;
|
2739 |
|
|
// The block we are currently translating. NULL if not in a
|
2740 |
|
|
// function.
|
2741 |
|
|
Block *block_;
|
2742 |
|
|
// The backend representation of the current block. NULL if block_
|
2743 |
|
|
// is NULL.
|
2744 |
|
|
Bblock* bblock_;
|
2745 |
|
|
// Whether this is being evaluated in a constant context. This is
|
2746 |
|
|
// used for type descriptor initializers.
|
2747 |
|
|
bool is_const_;
|
2748 |
|
|
};
|
2749 |
|
|
|
2750 |
|
|
// Runtime error codes. These must match the values in
|
2751 |
|
|
// libgo/runtime/go-runtime-error.c.
|
2752 |
|
|
|
2753 |
|
|
// Slice index out of bounds: negative or larger than the length of
|
2754 |
|
|
// the slice.
|
2755 |
|
|
static const int RUNTIME_ERROR_SLICE_INDEX_OUT_OF_BOUNDS = 0;
|
2756 |
|
|
|
2757 |
|
|
// Array index out of bounds.
|
2758 |
|
|
static const int RUNTIME_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS = 1;
|
2759 |
|
|
|
2760 |
|
|
// String index out of bounds.
|
2761 |
|
|
static const int RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS = 2;
|
2762 |
|
|
|
2763 |
|
|
// Slice slice out of bounds: negative or larger than the length of
|
2764 |
|
|
// the slice or high bound less than low bound.
|
2765 |
|
|
static const int RUNTIME_ERROR_SLICE_SLICE_OUT_OF_BOUNDS = 3;
|
2766 |
|
|
|
2767 |
|
|
// Array slice out of bounds.
|
2768 |
|
|
static const int RUNTIME_ERROR_ARRAY_SLICE_OUT_OF_BOUNDS = 4;
|
2769 |
|
|
|
2770 |
|
|
// String slice out of bounds.
|
2771 |
|
|
static const int RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS = 5;
|
2772 |
|
|
|
2773 |
|
|
// Dereference of nil pointer. This is used when there is a
|
2774 |
|
|
// dereference of a pointer to a very large struct or array, to ensure
|
2775 |
|
|
// that a gigantic array is not used a proxy to access random memory
|
2776 |
|
|
// locations.
|
2777 |
|
|
static const int RUNTIME_ERROR_NIL_DEREFERENCE = 6;
|
2778 |
|
|
|
2779 |
|
|
// Slice length or capacity out of bounds in make: negative or
|
2780 |
|
|
// overflow or length greater than capacity.
|
2781 |
|
|
static const int RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS = 7;
|
2782 |
|
|
|
2783 |
|
|
// Map capacity out of bounds in make: negative or overflow.
|
2784 |
|
|
static const int RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS = 8;
|
2785 |
|
|
|
2786 |
|
|
// Channel capacity out of bounds in make: negative or overflow.
|
2787 |
|
|
static const int RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS = 9;
|
2788 |
|
|
|
2789 |
|
|
// This is used by some of the langhooks.
|
2790 |
|
|
extern Gogo* go_get_gogo();
|
2791 |
|
|
|
2792 |
|
|
// Whether we have seen any errors. FIXME: Replace with a backend
|
2793 |
|
|
// interface.
|
2794 |
|
|
extern bool saw_errors();
|
2795 |
|
|
|
2796 |
|
|
#endif // !defined(GO_GOGO_H)
|