Commit f3878205 by Than McIntosh Committed by Ian Lance Taylor

compiler: relocate ID encoding utilities to gofrontend

    
    Relocate the code that encodes/sanitizes identifiers to make them
    assembler-friendly, moving it from the back end to the front end; the
    decisions about when to encode an identifier and the calls to the
    encoding helpers now take place entirely in gofrontend.
    
    Reviewed-on: https://go-review.googlesource.com/33424

	* go-gcc.cc (char_needs_encoding): Remove.
	(needs_encoding, fetch_utf8_char, encode_id): Remove.
	(Gcc_backend::global_variable): Add asm_name parameter.  Don't
	compute asm_name here.
	(Gcc_backend::implicit_variable): Likewise.
	(Gcc_backend::implicit_variable_reference): Likewise.
	(Gcc_backend::immutable_struct): Likewise.
	(Gcc_backend::immutable_struct_reference): Likewise.
	* Make-lang.in (GO_OBJS): Add go/go-encode-id.o.

From-SVN: r242726
parent 7e98cccb
2016-11-22 Than McIntosh <thanm@google.com>
* go-gcc.cc (char_needs_encoding): Remove.
(needs_encoding, fetch_utf8_char, encode_id): Remove.
(Gcc_backend::global_variable): Add asm_name parameter. Don't
compute asm_name here.
(Gcc_backend::implicit_variable): Likewise.
(Gcc_backend::implicit_variable_reference): Likewise.
(Gcc_backend::immutable_struct): Likewise.
(Gcc_backend::immutable_struct_reference): Likewise.
* Make-lang.in (GO_OBJS): Add go/go-encode-id.o.
2016-11-22 Ian Lance Taylor <iant@google.com> 2016-11-22 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::Gcc_backend): Add builtin function * go-gcc.cc (Gcc_backend::Gcc_backend): Add builtin function
......
...@@ -55,6 +55,7 @@ GO_OBJS = \ ...@@ -55,6 +55,7 @@ GO_OBJS = \
go/expressions.o \ go/expressions.o \
go/go-backend.o \ go/go-backend.o \
go/go-diagnostics.o \ go/go-diagnostics.o \
go/go-encode-id.o \
go/go-dump.o \ go/go-dump.o \
go/go-gcc.o \ go/go-gcc.o \
go/go-gcc-diagnostics.o \ go/go-gcc-diagnostics.o \
...@@ -230,6 +231,7 @@ CFLAGS-go/go-gcc.o += $(GOINCLUDES) ...@@ -230,6 +231,7 @@ CFLAGS-go/go-gcc.o += $(GOINCLUDES)
CFLAGS-go/go-linemap.o += $(GOINCLUDES) CFLAGS-go/go-linemap.o += $(GOINCLUDES)
CFLAGS-go/go-sha1.o += $(GOINCLUDES) CFLAGS-go/go-sha1.o += $(GOINCLUDES)
CFLAGS-go/go-gcc-diagnostics.o += $(GOINCLUDES) CFLAGS-go/go-gcc-diagnostics.o += $(GOINCLUDES)
CFLAGS-go/go-encode-id.o += $(GOINCLUDES)
go/%.o: go/gofrontend/%.cc go/%.o: go/gofrontend/%.cc
$(COMPILE) $(GOINCLUDES) $< $(COMPILE) $(GOINCLUDES) $<
......
...@@ -412,9 +412,8 @@ class Gcc_backend : public Backend ...@@ -412,9 +412,8 @@ class Gcc_backend : public Backend
{ return new Bvariable(error_mark_node); } { return new Bvariable(error_mark_node); }
Bvariable* Bvariable*
global_variable(const std::string& package_name, global_variable(const std::string& var_name,
const std::string& pkgpath, const std::string& asm_name,
const std::string& name,
Btype* btype, Btype* btype,
bool is_external, bool is_external,
bool is_hidden, bool is_hidden,
...@@ -440,25 +439,27 @@ class Gcc_backend : public Backend ...@@ -440,25 +439,27 @@ class Gcc_backend : public Backend
Location, Bstatement**); Location, Bstatement**);
Bvariable* Bvariable*
implicit_variable(const std::string&, Btype*, bool, bool, bool, implicit_variable(const std::string&, const std::string&, Btype*,
int64_t); bool, bool, bool, int64_t);
void void
implicit_variable_set_init(Bvariable*, const std::string&, Btype*, implicit_variable_set_init(Bvariable*, const std::string&, Btype*,
bool, bool, bool, Bexpression*); bool, bool, bool, Bexpression*);
Bvariable* Bvariable*
implicit_variable_reference(const std::string&, Btype*); implicit_variable_reference(const std::string&, const std::string&, Btype*);
Bvariable* Bvariable*
immutable_struct(const std::string&, bool, bool, Btype*, Location); immutable_struct(const std::string&, const std::string&,
bool, bool, Btype*, Location);
void void
immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*, immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*,
Location, Bexpression*); Location, Bexpression*);
Bvariable* Bvariable*
immutable_struct_reference(const std::string&, Btype*, Location); immutable_struct_reference(const std::string&, const std::string&,
Btype*, Location);
// Labels. // Labels.
...@@ -550,102 +551,6 @@ get_identifier_from_string(const std::string& str) ...@@ -550,102 +551,6 @@ get_identifier_from_string(const std::string& str)
return get_identifier_with_length(str.data(), str.length()); return get_identifier_with_length(str.data(), str.length());
} }
// Return whether the character c is OK to use in the assembler.
static bool
char_needs_encoding(char c)
{
switch (c)
{
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '_': case '.': case '$': case '/':
return false;
default:
return true;
}
}
// Return whether the identifier needs to be translated because it
// contains non-ASCII characters.
static bool
needs_encoding(const std::string& str)
{
for (std::string::const_iterator p = str.begin();
p != str.end();
++p)
if (char_needs_encoding(*p))
return true;
return false;
}
// Pull the next UTF-8 character out of P and store it in *PC. Return
// the number of bytes read.
static size_t
fetch_utf8_char(const char* p, unsigned int* pc)
{
unsigned char c = *p;
if ((c & 0x80) == 0)
{
*pc = c;
return 1;
}
size_t len = 0;
while ((c & 0x80) != 0)
{
++len;
c <<= 1;
}
unsigned int rc = *p & ((1 << (7 - len)) - 1);
for (size_t i = 1; i < len; i++)
{
unsigned int u = p[i];
rc <<= 6;
rc |= u & 0x3f;
}
*pc = rc;
return len;
}
// Encode an identifier using ASCII characters.
static std::string
encode_id(const std::string id)
{
std::string ret;
const char* p = id.c_str();
const char* pend = p + id.length();
while (p < pend)
{
unsigned int c;
size_t len = fetch_utf8_char(p, &c);
if (len == 1 && !char_needs_encoding(c))
ret += c;
else
{
ret += "$U";
char buf[30];
snprintf(buf, sizeof buf, "%x", c);
ret += buf;
ret += "$";
}
p += len;
}
return ret;
}
// Define the built-in functions that are exposed to GCCGo. // Define the built-in functions that are exposed to GCCGo.
Gcc_backend::Gcc_backend() Gcc_backend::Gcc_backend()
...@@ -2580,9 +2485,8 @@ Gcc_backend::non_zero_size_type(tree type) ...@@ -2580,9 +2485,8 @@ Gcc_backend::non_zero_size_type(tree type)
// Make a global variable. // Make a global variable.
Bvariable* Bvariable*
Gcc_backend::global_variable(const std::string& package_name, Gcc_backend::global_variable(const std::string& var_name,
const std::string& pkgpath, const std::string& asm_name,
const std::string& name,
Btype* btype, Btype* btype,
bool is_external, bool is_external,
bool is_hidden, bool is_hidden,
...@@ -2598,9 +2502,6 @@ Gcc_backend::global_variable(const std::string& package_name, ...@@ -2598,9 +2502,6 @@ Gcc_backend::global_variable(const std::string& package_name,
if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0) if ((is_external || !is_hidden) && int_size_in_bytes(type_tree) == 0)
type_tree = this->non_zero_size_type(type_tree); type_tree = this->non_zero_size_type(type_tree);
std::string var_name(package_name);
var_name.push_back('.');
var_name.append(name);
tree decl = build_decl(location.gcc_location(), VAR_DECL, tree decl = build_decl(location.gcc_location(), VAR_DECL,
get_identifier_from_string(var_name), get_identifier_from_string(var_name),
type_tree); type_tree);
...@@ -2611,17 +2512,12 @@ Gcc_backend::global_variable(const std::string& package_name, ...@@ -2611,17 +2512,12 @@ Gcc_backend::global_variable(const std::string& package_name,
if (!is_hidden) if (!is_hidden)
{ {
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
std::string asm_name(pkgpath);
asm_name.push_back('.');
asm_name.append(name);
if (needs_encoding(asm_name))
asm_name = encode_id(asm_name);
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
} }
else if (needs_encoding(var_name)) else
SET_DECL_ASSEMBLER_NAME(decl, {
get_identifier_from_string(encode_id(var_name))); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
}
TREE_USED(decl) = 1; TREE_USED(decl) = 1;
...@@ -2814,8 +2710,9 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, ...@@ -2814,8 +2710,9 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
// generating GC root variables and storing the values of a slice initializer. // generating GC root variables and storing the values of a slice initializer.
Bvariable* Bvariable*
Gcc_backend::implicit_variable(const std::string& name, Btype* type, Gcc_backend::implicit_variable(const std::string& name,
bool is_hidden, bool is_constant, const std::string& asm_name,
Btype* type, bool is_hidden, bool is_constant,
bool is_common, int64_t alignment) bool is_common, int64_t alignment)
{ {
tree type_tree = type->get_tree(); tree type_tree = type->get_tree();
...@@ -2857,8 +2754,8 @@ Gcc_backend::implicit_variable(const std::string& name, Btype* type, ...@@ -2857,8 +2754,8 @@ Gcc_backend::implicit_variable(const std::string& name, Btype* type,
SET_DECL_ALIGN(decl, alignment * BITS_PER_UNIT); SET_DECL_ALIGN(decl, alignment * BITS_PER_UNIT);
DECL_USER_ALIGN(decl) = 1; DECL_USER_ALIGN(decl) = 1;
} }
if (needs_encoding(name)) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name))); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
go_preserve_from_gc(decl); go_preserve_from_gc(decl);
return new Bvariable(decl); return new Bvariable(decl);
...@@ -2899,7 +2796,9 @@ Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&, ...@@ -2899,7 +2796,9 @@ Gcc_backend::implicit_variable_set_init(Bvariable* var, const std::string&,
// Return a reference to an implicit variable defined in another package. // Return a reference to an implicit variable defined in another package.
Bvariable* Bvariable*
Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype) Gcc_backend::implicit_variable_reference(const std::string& name,
const std::string& asm_name,
Btype* btype)
{ {
tree type_tree = btype->get_tree(); tree type_tree = btype->get_tree();
if (type_tree == error_mark_node) if (type_tree == error_mark_node)
...@@ -2911,8 +2810,8 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype) ...@@ -2911,8 +2810,8 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype)
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
TREE_STATIC(decl) = 1; TREE_STATIC(decl) = 1;
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
if (needs_encoding(name)) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name))); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
go_preserve_from_gc(decl); go_preserve_from_gc(decl);
return new Bvariable(decl); return new Bvariable(decl);
} }
...@@ -2920,7 +2819,9 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype) ...@@ -2920,7 +2819,9 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype)
// Create a named immutable initialized data structure. // Create a named immutable initialized data structure.
Bvariable* Bvariable*
Gcc_backend::immutable_struct(const std::string& name, bool is_hidden, Gcc_backend::immutable_struct(const std::string& name,
const std::string& asm_name,
bool is_hidden,
bool is_common, Btype* btype, Location location) bool is_common, Btype* btype, Location location)
{ {
tree type_tree = btype->get_tree(); tree type_tree = btype->get_tree();
...@@ -2937,8 +2838,8 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden, ...@@ -2937,8 +2838,8 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
if (!is_hidden) if (!is_hidden)
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
if (needs_encoding(name)) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name))); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
// When the initializer for one immutable_struct refers to another, // When the initializer for one immutable_struct refers to another,
// it needs to know the visibility of the referenced struct so that // it needs to know the visibility of the referenced struct so that
...@@ -2998,7 +2899,9 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&, ...@@ -2998,7 +2899,9 @@ Gcc_backend::immutable_struct_set_init(Bvariable* var, const std::string&,
// defined in another package. // defined in another package.
Bvariable* Bvariable*
Gcc_backend::immutable_struct_reference(const std::string& name, Btype* btype, Gcc_backend::immutable_struct_reference(const std::string& name,
const std::string& asm_name,
Btype* btype,
Location location) Location location)
{ {
tree type_tree = btype->get_tree(); tree type_tree = btype->get_tree();
...@@ -3013,8 +2916,8 @@ Gcc_backend::immutable_struct_reference(const std::string& name, Btype* btype, ...@@ -3013,8 +2916,8 @@ Gcc_backend::immutable_struct_reference(const std::string& name, Btype* btype,
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
DECL_EXTERNAL(decl) = 1; DECL_EXTERNAL(decl) = 1;
if (needs_encoding(name)) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name))); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
go_preserve_from_gc(decl); go_preserve_from_gc(decl);
return new Bvariable(decl); return new Bvariable(decl);
} }
...@@ -3104,10 +3007,8 @@ Gcc_backend::function(Btype* fntype, const std::string& name, ...@@ -3104,10 +3007,8 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
return this->error_function(); return this->error_function();
tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype); tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype);
if (!asm_name.empty()) if (! asm_name.empty())
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name)); SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
else if (needs_encoding(name))
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
if (is_visible) if (is_visible)
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
if (is_declaration) if (is_declaration)
......
e66f30e862cb5d02b9d55bf44ac439bb8fc4ea19 4d8e00e730897cc7e73b1582522ecab031cfcaf2
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -482,21 +482,19 @@ class Backend ...@@ -482,21 +482,19 @@ class Backend
virtual Bvariable* virtual Bvariable*
error_variable() = 0; error_variable() = 0;
// Create a global variable. PACKAGE_NAME is the name of the // Create a global variable. NAME is the package-qualified name of
// package where the variable is defined. PKGPATH is the package // the variable. ASM_NAME is the encoded identifier for the
// path for that package, from the -fgo-pkgpath or -fgo-prefix // variable, incorporating the package, and made safe for the
// option. NAME is the name of the variable. BTYPE is the type of // assembler. BTYPE is the type of the variable. IS_EXTERNAL is
// the variable. IS_EXTERNAL is true if the variable is defined in // true if the variable is defined in some other package. IS_HIDDEN
// some other package. IS_HIDDEN is true if the variable is not // is true if the variable is not exported (name begins with a lower
// exported (name begins with a lower case letter). // case letter). IN_UNIQUE_SECTION is true if the variable should
// IN_UNIQUE_SECTION is true if the variable should be put into a // be put into a unique section if possible; this is intended to
// unique section if possible; this is intended to permit the linker // permit the linker to garbage collect the variable if it is not
// to garbage collect the variable if it is not referenced. // referenced. LOCATION is where the variable was defined.
// LOCATION is where the variable was defined.
virtual Bvariable* virtual Bvariable*
global_variable(const std::string& package_name, global_variable(const std::string& name,
const std::string& pkgpath, const std::string& asm_name,
const std::string& name,
Btype* btype, Btype* btype,
bool is_external, bool is_external,
bool is_hidden, bool is_hidden,
...@@ -561,6 +559,9 @@ class Backend ...@@ -561,6 +559,9 @@ class Backend
// //
// NAME is the name to use for the initialized variable this will create. // NAME is the name to use for the initialized variable this will create.
// //
// ASM_NAME is encoded assembler-friendly version of the name, or the
// empty string if no encoding is needed.
//
// TYPE is the type of the implicit variable. // TYPE is the type of the implicit variable.
// //
// IS_HIDDEN will be true if the descriptor should only be visible // IS_HIDDEN will be true if the descriptor should only be visible
...@@ -578,8 +579,9 @@ class Backend ...@@ -578,8 +579,9 @@ class Backend
// //
// If ALIGNMENT is not zero, it is the desired alignment of the variable. // If ALIGNMENT is not zero, it is the desired alignment of the variable.
virtual Bvariable* virtual Bvariable*
implicit_variable(const std::string& name, Btype* type, bool is_hidden, implicit_variable(const std::string& name, const std::string& asm_name,
bool is_constant, bool is_common, int64_t alignment) = 0; Btype* type, bool is_hidden, bool is_constant,
bool is_common, int64_t alignment) = 0;
// Set the initial value of a variable created by implicit_variable. // Set the initial value of a variable created by implicit_variable.
...@@ -597,12 +599,15 @@ class Backend ...@@ -597,12 +599,15 @@ class Backend
bool is_hidden, bool is_constant, bool is_common, bool is_hidden, bool is_constant, bool is_common,
Bexpression* init) = 0; Bexpression* init) = 0;
// Create a reference to a named implicit variable defined in some other // Create a reference to a named implicit variable defined in some
// package. This will be a variable created by a call to implicit_variable // other package. This will be a variable created by a call to
// with the same NAME and TYPE and with IS_COMMON passed as false. This // implicit_variable with the same NAME, ASM_NAME and TYPE and with
// corresponds to an extern global variable in C. // IS_COMMON passed as false. This corresponds to an extern global
// variable in C.
virtual Bvariable* virtual Bvariable*
implicit_variable_reference(const std::string& name, Btype* type) = 0; implicit_variable_reference(const std::string& name,
const std::string& asm_name,
Btype* type) = 0;
// Create a named immutable initialized data structure. This is // Create a named immutable initialized data structure. This is
// used for type descriptors, map descriptors, and function // used for type descriptors, map descriptors, and function
...@@ -612,6 +617,9 @@ class Backend ...@@ -612,6 +617,9 @@ class Backend
// NAME is the name to use for the initialized global variable which // NAME is the name to use for the initialized global variable which
// this call will create. // this call will create.
// //
// ASM_NAME is the encoded, assembler-friendly version of NAME, or
// the empty string if no encoding is needed.
//
// IS_HIDDEN will be true if the descriptor should only be visible // IS_HIDDEN will be true if the descriptor should only be visible
// within the current object. // within the current object.
// //
...@@ -630,7 +638,9 @@ class Backend ...@@ -630,7 +638,9 @@ class Backend
// address. After calling this the frontend will call // address. After calling this the frontend will call
// immutable_struct_set_init. // immutable_struct_set_init.
virtual Bvariable* virtual Bvariable*
immutable_struct(const std::string& name, bool is_hidden, bool is_common, immutable_struct(const std::string& name,
const std::string& asm_name,
bool is_hidden, bool is_common,
Btype* type, Location) = 0; Btype* type, Location) = 0;
// Set the initial value of a variable created by immutable_struct. // Set the initial value of a variable created by immutable_struct.
...@@ -648,11 +658,12 @@ class Backend ...@@ -648,11 +658,12 @@ class Backend
// Create a reference to a named immutable initialized data // Create a reference to a named immutable initialized data
// structure defined in some other package. This will be a // structure defined in some other package. This will be a
// structure created by a call to immutable_struct with the same // structure created by a call to immutable_struct with the same
// NAME and TYPE and with IS_COMMON passed as false. This // NAME, ASM_NAME and TYPE and with IS_COMMON passed as false. This
// corresponds to an extern const global variable in C. // corresponds to an extern const global variable in C.
virtual Bvariable* virtual Bvariable*
immutable_struct_reference(const std::string& name, Btype* type, immutable_struct_reference(const std::string& name,
Location) = 0; const std::string& asm_name,
Btype* type, Location) = 0;
// Labels. // Labels.
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "go-c.h" #include "go-c.h"
#include "gogo.h" #include "gogo.h"
#include "go-diagnostics.h" #include "go-diagnostics.h"
#include "go-encode-id.h"
#include "types.h" #include "types.h"
#include "export.h" #include "export.h"
#include "import.h" #include "import.h"
...@@ -1304,16 +1305,18 @@ Func_descriptor_expression::do_get_backend(Translate_context* context) ...@@ -1304,16 +1305,18 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
Btype* btype = this->type()->get_backend(gogo); Btype* btype = this->type()->get_backend(gogo);
Bvariable* bvar; Bvariable* bvar;
std::string asm_name(go_selectively_encode_id(var_name));
if (no->package() != NULL || is_descriptor) if (no->package() != NULL || is_descriptor)
bvar = context->backend()->immutable_struct_reference(var_name, btype, bvar = context->backend()->immutable_struct_reference(var_name, asm_name,
loc); btype, loc);
else else
{ {
Location bloc = Linemap::predeclared_location(); Location bloc = Linemap::predeclared_location();
bool is_hidden = ((no->is_function() bool is_hidden = ((no->is_function()
&& no->func_value()->enclosing() != NULL) && no->func_value()->enclosing() != NULL)
|| Gogo::is_thunk(no)); || Gogo::is_thunk(no));
bvar = context->backend()->immutable_struct(var_name, is_hidden, false, bvar = context->backend()->immutable_struct(var_name, asm_name,
is_hidden, false,
btype, bloc); btype, bloc);
Expression_list* vals = new Expression_list(); Expression_list* vals = new Expression_list();
vals->push_back(Expression::make_func_code_reference(this->fn_, bloc)); vals->push_back(Expression::make_func_code_reference(this->fn_, bloc));
...@@ -4283,9 +4286,11 @@ Unary_expression::do_get_backend(Translate_context* context) ...@@ -4283,9 +4286,11 @@ Unary_expression::do_get_backend(Translate_context* context)
// read-only, because the program is permitted to change it. // read-only, because the program is permitted to change it.
copy_to_heap = context->function() != NULL; copy_to_heap = context->function() != NULL;
} }
std::string asm_name(go_selectively_encode_id(buf));
Bvariable* implicit = Bvariable* implicit =
gogo->backend()->implicit_variable(buf, btype, true, copy_to_heap, gogo->backend()->implicit_variable(buf, asm_name,
false, 0); btype, true, copy_to_heap,
false, 0);
gogo->backend()->implicit_variable_set_init(implicit, buf, btype, gogo->backend()->implicit_variable_set_init(implicit, buf, btype,
true, copy_to_heap, false, true, copy_to_heap, false,
bexpr); bexpr);
...@@ -4299,8 +4304,10 @@ Unary_expression::do_get_backend(Translate_context* context) ...@@ -4299,8 +4304,10 @@ Unary_expression::do_get_backend(Translate_context* context)
snprintf(buf, sizeof buf, "C%u", counter); snprintf(buf, sizeof buf, "C%u", counter);
++counter; ++counter;
std::string asm_name(go_selectively_encode_id(buf));
Bvariable* decl = Bvariable* decl =
gogo->backend()->immutable_struct(buf, true, false, btype, loc); gogo->backend()->immutable_struct(buf, asm_name,
true, false, btype, loc);
gogo->backend()->immutable_struct_set_init(decl, buf, true, false, gogo->backend()->immutable_struct_set_init(decl, buf, true, false,
btype, loc, bexpr); btype, loc, bexpr);
bexpr = gogo->backend()->var_expression(decl, loc); bexpr = gogo->backend()->var_expression(decl, loc);
...@@ -15074,8 +15081,10 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) ...@@ -15074,8 +15081,10 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
&& this->type_->named_type()->named_object()->package() != NULL) && this->type_->named_type()->named_object()->package() != NULL)
{ {
Btype* btype = this->type()->get_backend(gogo); Btype* btype = this->type()->get_backend(gogo);
std::string asm_name(go_selectively_encode_id(mangled_name));
this->bvar_ = this->bvar_ =
gogo->backend()->immutable_struct_reference(mangled_name, btype, loc); gogo->backend()->immutable_struct_reference(mangled_name, asm_name,
btype, loc);
return gogo->backend()->var_expression(this->bvar_, this->location()); return gogo->backend()->var_expression(this->bvar_, this->location());
} }
...@@ -15119,7 +15128,8 @@ Interface_mtable_expression::do_get_backend(Translate_context* context) ...@@ -15119,7 +15128,8 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
Bexpression* ctor = mtable->get_backend(context); Bexpression* ctor = mtable->get_backend(context);
bool is_public = has_hidden_methods && this->type_->named_type() != NULL; bool is_public = has_hidden_methods && this->type_->named_type() != NULL;
this->bvar_ = gogo->backend()->immutable_struct(mangled_name, false, std::string asm_name(go_selectively_encode_id(mangled_name));
this->bvar_ = gogo->backend()->immutable_struct(mangled_name, asm_name, false,
!is_public, btype, loc); !is_public, btype, loc);
gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false, gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false,
!is_public, btype, loc, ctor); !is_public, btype, loc, ctor);
......
// go-encode-id.cc -- Go identifier encoding hooks
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go-location.h"
#include "go-linemap.h"
#include "go-encode-id.h"
// Return whether the character c is OK to use in the assembler.
static bool
char_needs_encoding(char c)
{
switch (c)
{
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '_': case '.': case '$': case '/':
return false;
default:
return true;
}
}
// Return whether the identifier needs to be translated because it
// contains non-ASCII characters.
bool
go_id_needs_encoding(const std::string& str)
{
for (std::string::const_iterator p = str.begin();
p != str.end();
++p)
if (char_needs_encoding(*p))
return true;
return false;
}
// Pull the next UTF-8 character out of P and store it in *PC. Return
// the number of bytes read.
static size_t
fetch_utf8_char(const char* p, unsigned int* pc)
{
unsigned char c = *p;
if ((c & 0x80) == 0)
{
*pc = c;
return 1;
}
size_t len = 0;
while ((c & 0x80) != 0)
{
++len;
c <<= 1;
}
unsigned int rc = *p & ((1 << (7 - len)) - 1);
for (size_t i = 1; i < len; i++)
{
unsigned int u = p[i];
rc <<= 6;
rc |= u & 0x3f;
}
*pc = rc;
return len;
}
// Encode an identifier using ASCII characters.
std::string
go_encode_id(const std::string &id)
{
std::string ret;
const char* p = id.c_str();
const char* pend = p + id.length();
while (p < pend)
{
unsigned int c;
size_t len = fetch_utf8_char(p, &c);
if (len == 1 && !char_needs_encoding(c))
ret += c;
else
{
ret += "$U";
char buf[30];
snprintf(buf, sizeof buf, "%x", c);
ret += buf;
ret += "$";
}
p += len;
}
return ret;
}
std::string
go_selectively_encode_id(const std::string &id)
{
if (go_id_needs_encoding(id))
return go_encode_id(id);
return std::string();
}
// go-encode-id.h -- Go identifier encoding utilities -*- C++ -*-
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef GO_ENCODE_ID_H
#define GO_ENCODE_ID_H
#include "backend.h"
// Given an identifier corresponding to a function or variable,
// this helper returns TRUE if the identifier needs special
// encoding to be used as an ASM name (symbol), FALSE if the name
// is OK as is.
extern bool
go_id_needs_encoding(const std::string& str);
// Encodes the specified identifier for ASM name safety, returning a
// string with the encoded value.
extern std::string
go_encode_id(const std::string &id);
// Returns the empty string if the specified name needs encoding,
// otherwise invokes go_encode_id() on the name and returns the
// result.
extern std::string
go_selectively_encode_id(const std::string &id);
#endif // !defined(GO_ENCODE_ID_H)
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "go-c.h" #include "go-c.h"
#include "go-diagnostics.h" #include "go-diagnostics.h"
#include "go-encode-id.h"
#include "go-dump.h" #include "go-dump.h"
#include "go-optimize.h" #include "go-optimize.h"
#include "lex.h" #include "lex.h"
...@@ -5326,6 +5327,10 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5326,6 +5327,10 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
if ((this->pragmas_ & GOPRAGMA_NOSPLIT) != 0) if ((this->pragmas_ & GOPRAGMA_NOSPLIT) != 0)
disable_split_stack = true; disable_split_stack = true;
// Encode name if asm_name not already set at this point
if (asm_name.empty() && go_id_needs_encoding(no->get_id(gogo)))
asm_name = go_encode_id(no->get_id(gogo));
// This should go into a unique section if that has been // This should go into a unique section if that has been
// requested elsewhere, or if this is a nointerface function. // requested elsewhere, or if this is a nointerface function.
// We want to put a nointerface function into a unique section // We want to put a nointerface function into a unique section
...@@ -5379,6 +5384,8 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -5379,6 +5384,8 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
asm_name.append(rtype->mangled_name(gogo)); asm_name.append(rtype->mangled_name(gogo));
} }
} }
else if (go_id_needs_encoding(no->get_id(gogo)))
asm_name = go_encode_id(no->get_id(gogo));
Btype* functype = this->fntype_->get_backend_fntype(gogo); Btype* functype = this->fntype_->get_backend_fntype(gogo);
this->fndecl_ = this->fndecl_ =
...@@ -6594,25 +6601,39 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function, ...@@ -6594,25 +6601,39 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
type = Type::make_pointer_type(type); type = Type::make_pointer_type(type);
} }
std::string n = Gogo::unpack_hidden_name(name); const std::string n = Gogo::unpack_hidden_name(name);
Btype* btype = type->get_backend(gogo); Btype* btype = type->get_backend(gogo);
Bvariable* bvar; Bvariable* bvar;
if (Map_type::is_zero_value(this)) if (Map_type::is_zero_value(this))
bvar = Map_type::backend_zero_value(gogo); bvar = Map_type::backend_zero_value(gogo);
else if (this->is_global_) else if (this->is_global_)
bvar = backend->global_variable((package == NULL {
? gogo->package_name() std::string var_name(package != NULL
: package->package_name()), ? package->package_name()
(package == NULL : gogo->package_name());
? gogo->pkgpath_symbol() var_name.push_back('.');
: package->pkgpath_symbol()), var_name.append(n);
n, std::string asm_name;
btype, if (Gogo::is_hidden_name(name))
package != NULL, asm_name = var_name;
Gogo::is_hidden_name(name), else
this->in_unique_section_, {
this->location_); asm_name = package != NULL
? package->pkgpath_symbol()
: gogo->pkgpath_symbol();
asm_name.push_back('.');
asm_name.append(n);
}
asm_name = go_encode_id(asm_name);
bvar = backend->global_variable(var_name,
asm_name,
btype,
package != NULL,
Gogo::is_hidden_name(name),
this->in_unique_section_,
this->location_);
}
else if (function == NULL) else if (function == NULL)
{ {
go_assert(saw_errors()); go_assert(saw_errors());
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "go-c.h" #include "go-c.h"
#include "gogo.h" #include "gogo.h"
#include "go-diagnostics.h" #include "go-diagnostics.h"
#include "go-encode-id.h"
#include "operator.h" #include "operator.h"
#include "expressions.h" #include "expressions.h"
#include "statements.h" #include "statements.h"
...@@ -1217,10 +1218,12 @@ Type::make_type_descriptor_var(Gogo* gogo) ...@@ -1217,10 +1218,12 @@ Type::make_type_descriptor_var(Gogo* gogo)
Type* td_type = Type::make_type_descriptor_type(); Type* td_type = Type::make_type_descriptor_type();
Btype* td_btype = td_type->get_backend(gogo); Btype* td_btype = td_type->get_backend(gogo);
const char *name = "__go_tdn_unsafe.Pointer";
std::string asm_name(go_selectively_encode_id(name));
this->type_descriptor_var_ = this->type_descriptor_var_ =
gogo->backend()->immutable_struct_reference("__go_tdn_unsafe.Pointer", gogo->backend()->immutable_struct_reference(name, asm_name,
td_btype, td_btype,
bloc); bloc);
if (phash != NULL) if (phash != NULL)
*phash = this->type_descriptor_var_; *phash = this->type_descriptor_var_;
...@@ -1239,10 +1242,11 @@ Type::make_type_descriptor_var(Gogo* gogo) ...@@ -1239,10 +1242,11 @@ Type::make_type_descriptor_var(Gogo* gogo)
const Package* dummy; const Package* dummy;
if (this->type_descriptor_defined_elsewhere(nt, &dummy)) if (this->type_descriptor_defined_elsewhere(nt, &dummy))
{ {
std::string asm_name(go_selectively_encode_id(var_name));
this->type_descriptor_var_ = this->type_descriptor_var_ =
gogo->backend()->immutable_struct_reference(var_name, gogo->backend()->immutable_struct_reference(var_name, asm_name,
initializer_btype, initializer_btype,
loc); loc);
if (phash != NULL) if (phash != NULL)
*phash = this->type_descriptor_var_; *phash = this->type_descriptor_var_;
return; return;
...@@ -1271,8 +1275,9 @@ Type::make_type_descriptor_var(Gogo* gogo) ...@@ -1271,8 +1275,9 @@ Type::make_type_descriptor_var(Gogo* gogo)
// ensure that type_descriptor_pointer will work if called while // ensure that type_descriptor_pointer will work if called while
// converting INITIALIZER. // converting INITIALIZER.
std::string asm_name(go_selectively_encode_id(var_name));
this->type_descriptor_var_ = this->type_descriptor_var_ =
gogo->backend()->immutable_struct(var_name, false, is_common, gogo->backend()->immutable_struct(var_name, asm_name, false, is_common,
initializer_btype, loc); initializer_btype, loc);
if (phash != NULL) if (phash != NULL)
*phash = this->type_descriptor_var_; *phash = this->type_descriptor_var_;
...@@ -2187,8 +2192,10 @@ Type::make_gc_symbol_var(Gogo* gogo) ...@@ -2187,8 +2192,10 @@ Type::make_gc_symbol_var(Gogo* gogo)
const Package* dummy; const Package* dummy;
if (this->type_descriptor_defined_elsewhere(nt, &dummy)) if (this->type_descriptor_defined_elsewhere(nt, &dummy))
{ {
std::string asm_name(go_selectively_encode_id(sym_name));
this->gc_symbol_var_ = this->gc_symbol_var_ =
gogo->backend()->implicit_variable_reference(sym_name, sym_btype); gogo->backend()->implicit_variable_reference(sym_name, asm_name,
sym_btype);
if (phash != NULL) if (phash != NULL)
*phash = this->gc_symbol_var_; *phash = this->gc_symbol_var_;
return; return;
...@@ -2213,8 +2220,10 @@ Type::make_gc_symbol_var(Gogo* gogo) ...@@ -2213,8 +2220,10 @@ Type::make_gc_symbol_var(Gogo* gogo)
// Since we are building the GC symbol in this package, we must create the // Since we are building the GC symbol in this package, we must create the
// variable before converting the initializer to its backend representation // variable before converting the initializer to its backend representation
// because the initializer may refer to the GC symbol for this type. // because the initializer may refer to the GC symbol for this type.
std::string asm_name(go_selectively_encode_id(sym_name));
this->gc_symbol_var_ = this->gc_symbol_var_ =
gogo->backend()->implicit_variable(sym_name, sym_btype, false, true, is_common, 0); gogo->backend()->implicit_variable(sym_name, asm_name,
sym_btype, false, true, is_common, 0);
if (phash != NULL) if (phash != NULL)
*phash = this->gc_symbol_var_; *phash = this->gc_symbol_var_;
...@@ -7034,8 +7043,10 @@ Map_type::backend_zero_value(Gogo* gogo) ...@@ -7034,8 +7043,10 @@ Map_type::backend_zero_value(Gogo* gogo)
Btype* barray_type = gogo->backend()->array_type(buint8_type, blength); Btype* barray_type = gogo->backend()->array_type(buint8_type, blength);
std::string zname = Map_type::zero_value->name(); std::string zname = Map_type::zero_value->name();
std::string asm_name(go_selectively_encode_id(zname));
Bvariable* zvar = Bvariable* zvar =
gogo->backend()->implicit_variable(zname, barray_type, false, true, true, gogo->backend()->implicit_variable(zname, asm_name,
barray_type, false, true, true,
Map_type::zero_value_align); Map_type::zero_value_align);
gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type, gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type,
false, true, true, NULL); false, true, true, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment