Skip to content

Commit d5d5124

Browse files
compiler: support export/import of unsafe.Add/Slice
For golang/go#19367 For golang/go#40481 Change-Id: Id1aefd0696131842d480d9f9a5330c5ab221245a Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/340549 Trust: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 747f3a2 commit d5d5124

File tree

7 files changed

+129
-28
lines changed

7 files changed

+129
-28
lines changed

go/export.cc

+42-2
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ class Collect_export_references : public Traverse
106106
{
107107
public:
108108
Collect_export_references(Export* exp,
109+
const std::map<std::string, Package*>& packages,
109110
Unordered_set(Named_object*)* exports,
110111
Unordered_set(const Package*)* imports)
111112
: Traverse(traverse_expressions
112113
| traverse_types),
113-
exp_(exp), exports_(exports), imports_(imports),
114+
exp_(exp), packages_(packages), exports_(exports), imports_(imports),
114115
inline_fcn_worklist_(NULL), exports_finalized_(false)
115116
{ }
116117

@@ -150,6 +151,8 @@ class Collect_export_references : public Traverse
150151

151152
// The exporter.
152153
Export* exp_;
154+
// The list of packages known to this compilation.
155+
const std::map<std::string, Package*>& packages_;
153156
// The set of named objects to export.
154157
Unordered_set(Named_object*)* exports_;
155158
// Set containing all directly and indirectly imported packages.
@@ -257,6 +260,24 @@ Collect_export_references::expression(Expression** pexpr)
257260
return TRAVERSE_CONTINUE;
258261
}
259262

263+
const Call_expression* call = expr->call_expression();
264+
if (call != NULL)
265+
{
266+
const Builtin_call_expression* bce = call->builtin_call_expression();
267+
if (bce != NULL
268+
&& (bce->code() == Builtin_call_expression::BUILTIN_ADD
269+
|| bce->code() == Builtin_call_expression::BUILTIN_SLICE))
270+
{
271+
// This is a reference to unsafe.Add or unsafe.Slice. Make
272+
// sure we list the "unsafe" package in the imports and give
273+
// it a package index.
274+
const std::map<std::string, Package*>::const_iterator p =
275+
this->packages_.find("unsafe");
276+
go_assert(p != this->packages_.end());
277+
this->imports_->insert(p->second);
278+
}
279+
}
280+
260281
return TRAVERSE_CONTINUE;
261282
}
262283

@@ -589,7 +610,7 @@ Export::export_globals(const std::string& package_name,
589610
// Track all imported packages mentioned in export data.
590611
Unordered_set(const Package*) all_imports;
591612

592-
Collect_export_references collect(this, &exports, &all_imports);
613+
Collect_export_references collect(this, packages, &exports, &all_imports);
593614

594615
// Walk the set of inlinable routine bodies collected above. This
595616
// can potentially expand the exports set.
@@ -1274,6 +1295,25 @@ Export::package_index(const Package* pkg) const
12741295
return index;
12751296
}
12761297

1298+
// Return the index of the "unsafe" package.
1299+
1300+
int
1301+
Export::unsafe_package_index() const
1302+
{
1303+
for (Unordered_map(const Package*, int)::const_iterator p =
1304+
this->packages_.begin();
1305+
p != this->packages_.end();
1306+
++p)
1307+
{
1308+
if (p->first->pkgpath() == "unsafe")
1309+
{
1310+
go_assert(p->second != 0);
1311+
return p->second;
1312+
}
1313+
}
1314+
go_unreachable();
1315+
}
1316+
12771317
// Return the index of a type.
12781318

12791319
int

go/export.h

+10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ class Export : public String_dump
216216
int
217217
package_index(const Package* p) const;
218218

219+
// Return the index of the "unsafe" package, which must be one of
220+
// the exported packages.
221+
int
222+
unsafe_package_index() const;
223+
219224
private:
220225
Export(const Export&);
221226
Export& operator=(const Export&);
@@ -377,6 +382,11 @@ class Export_function_body : public String_dump
377382
package_index(const Package* p) const
378383
{ return this->exp_->package_index(p); }
379384

385+
// Return the index of the "unsafe" package.
386+
int
387+
unsafe_package_index() const
388+
{ return this->exp_->unsafe_package_index(); }
389+
380390
// Record a temporary statement and return its index.
381391
unsigned int
382392
record_temporary(const Temporary_statement*);

go/expressions.cc

+8
Original file line numberDiff line numberDiff line change
@@ -11039,6 +11039,14 @@ Builtin_call_expression::do_export(Export_function_body* efb) const
1103911039
// A trailing space lets us reliably identify the end of the number.
1104011040
efb->write_c_string(" ");
1104111041
}
11042+
else if (this->code_ == BUILTIN_ADD || this->code_ == BUILTIN_SLICE)
11043+
{
11044+
char buf[50];
11045+
snprintf(buf, sizeof buf, "<p%d>%s", efb->unsafe_package_index(),
11046+
(this->code_ == BUILTIN_ADD ? "Add" : "Slice"));
11047+
efb->write_c_string(buf);
11048+
this->export_arguments(efb);
11049+
}
1104211050
else
1104311051
{
1104411052
const char *s = NULL;

go/expressions.h

+18-3
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,10 @@ class Expression
732732
call_expression()
733733
{ return this->convert<Call_expression, EXPRESSION_CALL>(); }
734734

735+
const Call_expression*
736+
call_expression() const
737+
{ return this->convert<const Call_expression, EXPRESSION_CALL>(); }
738+
735739
// If this is a call_result expression, return the Call_result_expression
736740
// structure. Otherwise, return NULL. This is a controlled dynamic
737741
// cast.
@@ -2460,13 +2464,16 @@ class Call_expression : public Expression
24602464

24612465
// Whether this is a call to builtin function.
24622466
virtual bool
2463-
is_builtin()
2467+
is_builtin() const
24642468
{ return false; }
24652469

24662470
// Convert to a Builtin_call_expression, or return NULL.
24672471
inline Builtin_call_expression*
24682472
builtin_call_expression();
24692473

2474+
inline const Builtin_call_expression*
2475+
builtin_call_expression() const;
2476+
24702477
protected:
24712478
int
24722479
do_traverse(Traverse*);
@@ -2625,12 +2632,12 @@ class Builtin_call_expression : public Call_expression
26252632
};
26262633

26272634
Builtin_function_code
2628-
code()
2635+
code() const
26292636
{ return this->code_; }
26302637

26312638
// This overrides Call_expression::is_builtin.
26322639
bool
2633-
is_builtin()
2640+
is_builtin() const
26342641
{ return true; }
26352642

26362643
// Return whether EXPR, of array type, is a constant if passed to
@@ -2726,6 +2733,14 @@ Call_expression::builtin_call_expression()
27262733
: NULL);
27272734
}
27282735

2736+
inline const Builtin_call_expression*
2737+
Call_expression::builtin_call_expression() const
2738+
{
2739+
return (this->is_builtin()
2740+
? static_cast<const Builtin_call_expression*>(this)
2741+
: NULL);
2742+
}
2743+
27292744
// A single result from a call which returns multiple results.
27302745

27312746
class Call_result_expression : public Expression

go/gogo.h

+4
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,10 @@ class Gogo
533533
register_package(const std::string& pkgpath,
534534
const std::string& pkgpath_symbol, Location);
535535

536+
// Add the unsafe bindings to the unsafe package.
537+
void
538+
add_unsafe_bindings(Package*);
539+
536540
// Look up a package by pkgpath, and return its pkgpath_symbol.
537541
std::string
538542
pkgpath_symbol_for_package(const std::string&);

go/import.cc

+6
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,9 @@ Import::read_one_import()
497497
p->set_package_name(package_name, this->location());
498498

499499
this->packages_.push_back(p);
500+
501+
if (pkgpath == "unsafe")
502+
this->gogo_->add_unsafe_bindings(p);
500503
}
501504

502505
// Read an indirectimport line.
@@ -515,6 +518,9 @@ Import::read_one_indirect_import()
515518
p->set_package_name(package_name, this->location());
516519

517520
this->packages_.push_back(p);
521+
522+
if (pkgpath == "unsafe")
523+
this->gogo_->add_unsafe_bindings(p);
518524
}
519525

520526
// Read the list of import control functions and/or init graph.

go/unsafe.cc

+41-23
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,12 @@
1010
#include "types.h"
1111
#include "gogo.h"
1212

13-
// Set up the builtin unsafe package. This should probably be driven
14-
// by a table.
13+
// Set up the builtin unsafe package.
1514

1615
void
1716
Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
1817
Location location)
1918
{
20-
Location bloc = Linemap::predeclared_location();
21-
2219
bool add_to_globals;
2320
Package* package = this->add_imported_package("unsafe", local_name,
2421
is_local_name_exported,
@@ -34,10 +31,40 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
3431
package->set_location(location);
3532
this->imports_.insert(std::make_pair("unsafe", package));
3633

34+
this->add_unsafe_bindings(package);
35+
36+
Named_object* pointer_no = package->bindings()->lookup_local("Pointer");
37+
pointer_no->type_value()->set_is_visible();
38+
39+
if (add_to_globals)
40+
{
41+
Bindings* bindings = package->bindings();
42+
for (Bindings::const_declarations_iterator p =
43+
bindings->begin_declarations();
44+
p != bindings->end_declarations();
45+
++p)
46+
this->add_dot_import_object(p->second);
47+
}
48+
}
49+
50+
// Add the unsafe bindings to the Package object. This should
51+
// probably be driven by a table.
52+
53+
void
54+
Gogo::add_unsafe_bindings(Package* package)
55+
{
3756
Bindings* bindings = package->bindings();
3857

58+
if (bindings->lookup_local("Sizeof") != NULL)
59+
{
60+
// Already done by an earlier import.
61+
return;
62+
}
63+
64+
Location bloc = Linemap::predeclared_location();
65+
3966
// The type may have already been created by an import.
40-
Named_object* no = package->bindings()->lookup("Pointer");
67+
Named_object* no = bindings->lookup("Pointer");
4168
if (no == NULL)
4269
{
4370
Type* type = Type::make_pointer_type(Type::make_void_type());
@@ -49,11 +76,12 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
4976
go_assert(no->package() == package);
5077
go_assert(no->is_type());
5178
go_assert(no->type_value()->is_unsafe_pointer_type());
52-
no->type_value()->set_is_visible();
5379
}
5480
Named_type* pointer_type = no->type_value();
55-
if (add_to_globals)
56-
this->add_named_type(pointer_type);
81+
82+
// This may be called during an import, so the type may not be
83+
// visible yet.
84+
pointer_type->clear_is_visible();
5785

5886
Type* uintptr_type = Type::lookup_integer_type("uintptr");
5987

@@ -62,45 +90,35 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
6290
results->push_back(Typed_identifier("", uintptr_type, bloc));
6391
Function_type* fntype = Type::make_function_type(NULL, NULL, results, bloc);
6492
fntype->set_is_builtin();
65-
no = bindings->add_function_declaration("Sizeof", package, fntype, bloc);
66-
if (add_to_globals)
67-
this->add_dot_import_object(no);
93+
bindings->add_function_declaration("Sizeof", package, fntype, bloc);
6894

6995
// Offsetof.
7096
results = new Typed_identifier_list;
7197
results->push_back(Typed_identifier("", uintptr_type, bloc));
7298
fntype = Type::make_function_type(NULL, NULL, results, bloc);
7399
fntype->set_is_varargs();
74100
fntype->set_is_builtin();
75-
no = bindings->add_function_declaration("Offsetof", package, fntype, bloc);
76-
if (add_to_globals)
77-
this->add_dot_import_object(no);
101+
bindings->add_function_declaration("Offsetof", package, fntype, bloc);
78102

79103
// Alignof.
80104
results = new Typed_identifier_list;
81105
results->push_back(Typed_identifier("", uintptr_type, bloc));
82106
fntype = Type::make_function_type(NULL, NULL, results, bloc);
83107
fntype->set_is_varargs();
84108
fntype->set_is_builtin();
85-
no = bindings->add_function_declaration("Alignof", package, fntype, bloc);
86-
if (add_to_globals)
87-
this->add_dot_import_object(no);
109+
bindings->add_function_declaration("Alignof", package, fntype, bloc);
88110

89111
// Add.
90112
results = new Typed_identifier_list;
91113
results->push_back(Typed_identifier("", pointer_type, bloc));
92114
fntype = Type::make_function_type(NULL, NULL, results, bloc);
93115
fntype->set_is_builtin();
94-
no = bindings->add_function_declaration("Add", package, fntype, bloc);
95-
if (add_to_globals)
96-
this->add_dot_import_object(no);
116+
bindings->add_function_declaration("Add", package, fntype, bloc);
97117

98118
// Slice.
99119
fntype = Type::make_function_type(NULL, NULL, NULL, bloc);
100120
fntype->set_is_builtin();
101-
no = bindings->add_function_declaration("Slice", package, fntype, bloc);
102-
if (add_to_globals)
103-
this->add_dot_import_object(no);
121+
bindings->add_function_declaration("Slice", package, fntype, bloc);
104122

105123
if (!this->imported_unsafe_)
106124
{

0 commit comments

Comments
 (0)