mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-14 14:33:40 +08:00
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
This commit is contained in:
parent
7e98cccbd8
commit
f3878205dd
@ -1,3 +1,15 @@
|
||||
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>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::Gcc_backend): Add builtin function
|
||||
|
@ -55,6 +55,7 @@ GO_OBJS = \
|
||||
go/expressions.o \
|
||||
go/go-backend.o \
|
||||
go/go-diagnostics.o \
|
||||
go/go-encode-id.o \
|
||||
go/go-dump.o \
|
||||
go/go-gcc.o \
|
||||
go/go-gcc-diagnostics.o \
|
||||
@ -230,6 +231,7 @@ CFLAGS-go/go-gcc.o += $(GOINCLUDES)
|
||||
CFLAGS-go/go-linemap.o += $(GOINCLUDES)
|
||||
CFLAGS-go/go-sha1.o += $(GOINCLUDES)
|
||||
CFLAGS-go/go-gcc-diagnostics.o += $(GOINCLUDES)
|
||||
CFLAGS-go/go-encode-id.o += $(GOINCLUDES)
|
||||
|
||||
go/%.o: go/gofrontend/%.cc
|
||||
$(COMPILE) $(GOINCLUDES) $<
|
||||
|
171
gcc/go/go-gcc.cc
171
gcc/go/go-gcc.cc
@ -412,9 +412,8 @@ class Gcc_backend : public Backend
|
||||
{ return new Bvariable(error_mark_node); }
|
||||
|
||||
Bvariable*
|
||||
global_variable(const std::string& package_name,
|
||||
const std::string& pkgpath,
|
||||
const std::string& name,
|
||||
global_variable(const std::string& var_name,
|
||||
const std::string& asm_name,
|
||||
Btype* btype,
|
||||
bool is_external,
|
||||
bool is_hidden,
|
||||
@ -440,25 +439,27 @@ class Gcc_backend : public Backend
|
||||
Location, Bstatement**);
|
||||
|
||||
Bvariable*
|
||||
implicit_variable(const std::string&, Btype*, bool, bool, bool,
|
||||
int64_t);
|
||||
implicit_variable(const std::string&, const std::string&, Btype*,
|
||||
bool, bool, bool, int64_t);
|
||||
|
||||
void
|
||||
implicit_variable_set_init(Bvariable*, const std::string&, Btype*,
|
||||
bool, bool, bool, Bexpression*);
|
||||
|
||||
Bvariable*
|
||||
implicit_variable_reference(const std::string&, Btype*);
|
||||
implicit_variable_reference(const std::string&, const std::string&, Btype*);
|
||||
|
||||
Bvariable*
|
||||
immutable_struct(const std::string&, bool, bool, Btype*, Location);
|
||||
immutable_struct(const std::string&, const std::string&,
|
||||
bool, bool, Btype*, Location);
|
||||
|
||||
void
|
||||
immutable_struct_set_init(Bvariable*, const std::string&, bool, bool, Btype*,
|
||||
Location, Bexpression*);
|
||||
|
||||
Bvariable*
|
||||
immutable_struct_reference(const std::string&, Btype*, Location);
|
||||
immutable_struct_reference(const std::string&, const std::string&,
|
||||
Btype*, Location);
|
||||
|
||||
// Labels.
|
||||
|
||||
@ -550,102 +551,6 @@ get_identifier_from_string(const std::string& str)
|
||||
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.
|
||||
|
||||
Gcc_backend::Gcc_backend()
|
||||
@ -2580,9 +2485,8 @@ Gcc_backend::non_zero_size_type(tree type)
|
||||
// Make a global variable.
|
||||
|
||||
Bvariable*
|
||||
Gcc_backend::global_variable(const std::string& package_name,
|
||||
const std::string& pkgpath,
|
||||
const std::string& name,
|
||||
Gcc_backend::global_variable(const std::string& var_name,
|
||||
const std::string& asm_name,
|
||||
Btype* btype,
|
||||
bool is_external,
|
||||
bool is_hidden,
|
||||
@ -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)
|
||||
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,
|
||||
get_identifier_from_string(var_name),
|
||||
type_tree);
|
||||
@ -2611,17 +2512,12 @@ Gcc_backend::global_variable(const std::string& package_name,
|
||||
if (!is_hidden)
|
||||
{
|
||||
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));
|
||||
}
|
||||
else if (needs_encoding(var_name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl,
|
||||
get_identifier_from_string(encode_id(var_name)));
|
||||
else
|
||||
{
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
|
||||
}
|
||||
|
||||
TREE_USED(decl) = 1;
|
||||
|
||||
@ -2814,8 +2710,9 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
|
||||
// generating GC root variables and storing the values of a slice initializer.
|
||||
|
||||
Bvariable*
|
||||
Gcc_backend::implicit_variable(const std::string& name, Btype* type,
|
||||
bool is_hidden, bool is_constant,
|
||||
Gcc_backend::implicit_variable(const std::string& name,
|
||||
const std::string& asm_name,
|
||||
Btype* type, bool is_hidden, bool is_constant,
|
||||
bool is_common, int64_t alignment)
|
||||
{
|
||||
tree type_tree = type->get_tree();
|
||||
@ -2857,8 +2754,8 @@ Gcc_backend::implicit_variable(const std::string& name, Btype* type,
|
||||
SET_DECL_ALIGN(decl, alignment * BITS_PER_UNIT);
|
||||
DECL_USER_ALIGN(decl) = 1;
|
||||
}
|
||||
if (needs_encoding(name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
|
||||
if (! asm_name.empty())
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
|
||||
|
||||
go_preserve_from_gc(decl);
|
||||
return new Bvariable(decl);
|
||||
@ -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.
|
||||
|
||||
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();
|
||||
if (type_tree == error_mark_node)
|
||||
@ -2911,8 +2810,8 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype)
|
||||
TREE_PUBLIC(decl) = 1;
|
||||
TREE_STATIC(decl) = 1;
|
||||
DECL_ARTIFICIAL(decl) = 1;
|
||||
if (needs_encoding(name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
|
||||
if (! asm_name.empty())
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
|
||||
go_preserve_from_gc(decl);
|
||||
return new Bvariable(decl);
|
||||
}
|
||||
@ -2920,7 +2819,9 @@ Gcc_backend::implicit_variable_reference(const std::string& name, Btype* btype)
|
||||
// Create a named immutable initialized data structure.
|
||||
|
||||
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)
|
||||
{
|
||||
tree type_tree = btype->get_tree();
|
||||
@ -2937,8 +2838,8 @@ Gcc_backend::immutable_struct(const std::string& name, bool is_hidden,
|
||||
DECL_ARTIFICIAL(decl) = 1;
|
||||
if (!is_hidden)
|
||||
TREE_PUBLIC(decl) = 1;
|
||||
if (needs_encoding(name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
|
||||
if (! asm_name.empty())
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
|
||||
|
||||
// When the initializer for one immutable_struct refers to another,
|
||||
// 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&,
|
||||
// defined in another package.
|
||||
|
||||
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)
|
||||
{
|
||||
tree type_tree = btype->get_tree();
|
||||
@ -3013,8 +2916,8 @@ Gcc_backend::immutable_struct_reference(const std::string& name, Btype* btype,
|
||||
DECL_ARTIFICIAL(decl) = 1;
|
||||
TREE_PUBLIC(decl) = 1;
|
||||
DECL_EXTERNAL(decl) = 1;
|
||||
if (needs_encoding(name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
|
||||
if (! asm_name.empty())
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
|
||||
go_preserve_from_gc(decl);
|
||||
return new Bvariable(decl);
|
||||
}
|
||||
@ -3104,10 +3007,8 @@ Gcc_backend::function(Btype* fntype, const std::string& name,
|
||||
return this->error_function();
|
||||
|
||||
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));
|
||||
else if (needs_encoding(name))
|
||||
SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(encode_id(name)));
|
||||
if (is_visible)
|
||||
TREE_PUBLIC(decl) = 1;
|
||||
if (is_declaration)
|
||||
|
@ -1,4 +1,4 @@
|
||||
e66f30e862cb5d02b9d55bf44ac439bb8fc4ea19
|
||||
4d8e00e730897cc7e73b1582522ecab031cfcaf2
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -482,21 +482,19 @@ class Backend
|
||||
virtual Bvariable*
|
||||
error_variable() = 0;
|
||||
|
||||
// Create a global variable. PACKAGE_NAME is the name of the
|
||||
// package where the variable is defined. PKGPATH is the package
|
||||
// path for that package, from the -fgo-pkgpath or -fgo-prefix
|
||||
// option. NAME is the name of the variable. BTYPE is the type of
|
||||
// the variable. IS_EXTERNAL is true if the variable is defined in
|
||||
// some other package. IS_HIDDEN is true if the variable is not
|
||||
// exported (name begins with a lower case letter).
|
||||
// IN_UNIQUE_SECTION is true if the variable should be put into a
|
||||
// unique section if possible; this is intended to permit the linker
|
||||
// to garbage collect the variable if it is not referenced.
|
||||
// LOCATION is where the variable was defined.
|
||||
// Create a global variable. NAME is the package-qualified name of
|
||||
// the variable. ASM_NAME is the encoded identifier for the
|
||||
// variable, incorporating the package, and made safe for the
|
||||
// assembler. BTYPE is the type of the variable. IS_EXTERNAL is
|
||||
// true if the variable is defined in some other package. IS_HIDDEN
|
||||
// is true if the variable is not exported (name begins with a lower
|
||||
// case letter). IN_UNIQUE_SECTION is true if the variable should
|
||||
// be put into a unique section if possible; this is intended to
|
||||
// permit the linker to garbage collect the variable if it is not
|
||||
// referenced. LOCATION is where the variable was defined.
|
||||
virtual Bvariable*
|
||||
global_variable(const std::string& package_name,
|
||||
const std::string& pkgpath,
|
||||
const std::string& name,
|
||||
global_variable(const std::string& name,
|
||||
const std::string& asm_name,
|
||||
Btype* btype,
|
||||
bool is_external,
|
||||
bool is_hidden,
|
||||
@ -561,6 +559,9 @@ class Backend
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// IS_HIDDEN will be true if the descriptor should only be visible
|
||||
@ -578,8 +579,9 @@ class Backend
|
||||
//
|
||||
// If ALIGNMENT is not zero, it is the desired alignment of the variable.
|
||||
virtual Bvariable*
|
||||
implicit_variable(const std::string& name, Btype* type, bool is_hidden,
|
||||
bool is_constant, bool is_common, int64_t alignment) = 0;
|
||||
implicit_variable(const std::string& name, const std::string& asm_name,
|
||||
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.
|
||||
@ -597,12 +599,15 @@ class Backend
|
||||
bool is_hidden, bool is_constant, bool is_common,
|
||||
Bexpression* init) = 0;
|
||||
|
||||
// Create a reference to a named implicit variable defined in some other
|
||||
// package. This will be a variable created by a call to implicit_variable
|
||||
// with the same NAME and TYPE and with IS_COMMON passed as false. This
|
||||
// corresponds to an extern global variable in C.
|
||||
// Create a reference to a named implicit variable defined in some
|
||||
// other package. This will be a variable created by a call to
|
||||
// implicit_variable with the same NAME, ASM_NAME and TYPE and with
|
||||
// IS_COMMON passed as false. This corresponds to an extern global
|
||||
// variable in C.
|
||||
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
|
||||
// used for type descriptors, map descriptors, and function
|
||||
@ -612,6 +617,9 @@ class Backend
|
||||
// NAME is the name to use for the initialized global variable which
|
||||
// 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
|
||||
// within the current object.
|
||||
//
|
||||
@ -630,7 +638,9 @@ class Backend
|
||||
// address. After calling this the frontend will call
|
||||
// immutable_struct_set_init.
|
||||
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;
|
||||
|
||||
// Set the initial value of a variable created by immutable_struct.
|
||||
@ -648,11 +658,12 @@ class Backend
|
||||
// Create a reference to a named immutable initialized data
|
||||
// structure defined in some other package. This will be a
|
||||
// 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.
|
||||
virtual Bvariable*
|
||||
immutable_struct_reference(const std::string& name, Btype* type,
|
||||
Location) = 0;
|
||||
immutable_struct_reference(const std::string& name,
|
||||
const std::string& asm_name,
|
||||
Btype* type, Location) = 0;
|
||||
|
||||
// Labels.
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "go-c.h"
|
||||
#include "gogo.h"
|
||||
#include "go-diagnostics.h"
|
||||
#include "go-encode-id.h"
|
||||
#include "types.h"
|
||||
#include "export.h"
|
||||
#include "import.h"
|
||||
@ -1304,16 +1305,18 @@ Func_descriptor_expression::do_get_backend(Translate_context* context)
|
||||
Btype* btype = this->type()->get_backend(gogo);
|
||||
|
||||
Bvariable* bvar;
|
||||
std::string asm_name(go_selectively_encode_id(var_name));
|
||||
if (no->package() != NULL || is_descriptor)
|
||||
bvar = context->backend()->immutable_struct_reference(var_name, btype,
|
||||
loc);
|
||||
bvar = context->backend()->immutable_struct_reference(var_name, asm_name,
|
||||
btype, loc);
|
||||
else
|
||||
{
|
||||
Location bloc = Linemap::predeclared_location();
|
||||
bool is_hidden = ((no->is_function()
|
||||
&& no->func_value()->enclosing() != NULL)
|
||||
|| 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);
|
||||
Expression_list* vals = new Expression_list();
|
||||
vals->push_back(Expression::make_func_code_reference(this->fn_, bloc));
|
||||
@ -4283,9 +4286,11 @@ Unary_expression::do_get_backend(Translate_context* context)
|
||||
// read-only, because the program is permitted to change it.
|
||||
copy_to_heap = context->function() != NULL;
|
||||
}
|
||||
std::string asm_name(go_selectively_encode_id(buf));
|
||||
Bvariable* implicit =
|
||||
gogo->backend()->implicit_variable(buf, btype, true, copy_to_heap,
|
||||
false, 0);
|
||||
gogo->backend()->implicit_variable(buf, asm_name,
|
||||
btype, true, copy_to_heap,
|
||||
false, 0);
|
||||
gogo->backend()->implicit_variable_set_init(implicit, buf, btype,
|
||||
true, copy_to_heap, false,
|
||||
bexpr);
|
||||
@ -4299,8 +4304,10 @@ Unary_expression::do_get_backend(Translate_context* context)
|
||||
snprintf(buf, sizeof buf, "C%u", counter);
|
||||
++counter;
|
||||
|
||||
std::string asm_name(go_selectively_encode_id(buf));
|
||||
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,
|
||||
btype, loc, bexpr);
|
||||
bexpr = gogo->backend()->var_expression(decl, loc);
|
||||
@ -15074,8 +15081,10 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
|
||||
&& this->type_->named_type()->named_object()->package() != NULL)
|
||||
{
|
||||
Btype* btype = this->type()->get_backend(gogo);
|
||||
std::string asm_name(go_selectively_encode_id(mangled_name));
|
||||
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());
|
||||
}
|
||||
|
||||
@ -15119,7 +15128,8 @@ Interface_mtable_expression::do_get_backend(Translate_context* context)
|
||||
Bexpression* ctor = mtable->get_backend(context);
|
||||
|
||||
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);
|
||||
gogo->backend()->immutable_struct_set_init(this->bvar_, mangled_name, false,
|
||||
!is_public, btype, loc, ctor);
|
||||
|
113
gcc/go/gofrontend/go-encode-id.cc
Normal file
113
gcc/go/gofrontend/go-encode-id.cc
Normal file
@ -0,0 +1,113 @@
|
||||
// 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();
|
||||
}
|
30
gcc/go/gofrontend/go-encode-id.h
Normal file
30
gcc/go/gofrontend/go-encode-id.h
Normal file
@ -0,0 +1,30 @@
|
||||
// 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 @@
|
||||
|
||||
#include "go-c.h"
|
||||
#include "go-diagnostics.h"
|
||||
#include "go-encode-id.h"
|
||||
#include "go-dump.h"
|
||||
#include "go-optimize.h"
|
||||
#include "lex.h"
|
||||
@ -5326,6 +5327,10 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
|
||||
if ((this->pragmas_ & GOPRAGMA_NOSPLIT) != 0)
|
||||
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
|
||||
// requested elsewhere, or if this is a nointerface function.
|
||||
// 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)
|
||||
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);
|
||||
this->fndecl_ =
|
||||
@ -6594,25 +6601,39 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
|
||||
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);
|
||||
|
||||
Bvariable* bvar;
|
||||
if (Map_type::is_zero_value(this))
|
||||
bvar = Map_type::backend_zero_value(gogo);
|
||||
else if (this->is_global_)
|
||||
bvar = backend->global_variable((package == NULL
|
||||
? gogo->package_name()
|
||||
: package->package_name()),
|
||||
(package == NULL
|
||||
? gogo->pkgpath_symbol()
|
||||
: package->pkgpath_symbol()),
|
||||
n,
|
||||
btype,
|
||||
package != NULL,
|
||||
Gogo::is_hidden_name(name),
|
||||
this->in_unique_section_,
|
||||
this->location_);
|
||||
{
|
||||
std::string var_name(package != NULL
|
||||
? package->package_name()
|
||||
: gogo->package_name());
|
||||
var_name.push_back('.');
|
||||
var_name.append(n);
|
||||
std::string asm_name;
|
||||
if (Gogo::is_hidden_name(name))
|
||||
asm_name = var_name;
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
go_assert(saw_errors());
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "go-c.h"
|
||||
#include "gogo.h"
|
||||
#include "go-diagnostics.h"
|
||||
#include "go-encode-id.h"
|
||||
#include "operator.h"
|
||||
#include "expressions.h"
|
||||
#include "statements.h"
|
||||
@ -1217,10 +1218,12 @@ Type::make_type_descriptor_var(Gogo* gogo)
|
||||
|
||||
Type* td_type = Type::make_type_descriptor_type();
|
||||
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_ =
|
||||
gogo->backend()->immutable_struct_reference("__go_tdn_unsafe.Pointer",
|
||||
td_btype,
|
||||
bloc);
|
||||
gogo->backend()->immutable_struct_reference(name, asm_name,
|
||||
td_btype,
|
||||
bloc);
|
||||
|
||||
if (phash != NULL)
|
||||
*phash = this->type_descriptor_var_;
|
||||
@ -1239,10 +1242,11 @@ Type::make_type_descriptor_var(Gogo* gogo)
|
||||
const Package* dummy;
|
||||
if (this->type_descriptor_defined_elsewhere(nt, &dummy))
|
||||
{
|
||||
std::string asm_name(go_selectively_encode_id(var_name));
|
||||
this->type_descriptor_var_ =
|
||||
gogo->backend()->immutable_struct_reference(var_name,
|
||||
initializer_btype,
|
||||
loc);
|
||||
gogo->backend()->immutable_struct_reference(var_name, asm_name,
|
||||
initializer_btype,
|
||||
loc);
|
||||
if (phash != NULL)
|
||||
*phash = this->type_descriptor_var_;
|
||||
return;
|
||||
@ -1271,8 +1275,9 @@ Type::make_type_descriptor_var(Gogo* gogo)
|
||||
// ensure that type_descriptor_pointer will work if called while
|
||||
// converting INITIALIZER.
|
||||
|
||||
std::string asm_name(go_selectively_encode_id(var_name));
|
||||
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);
|
||||
if (phash != NULL)
|
||||
*phash = this->type_descriptor_var_;
|
||||
@ -2187,8 +2192,10 @@ Type::make_gc_symbol_var(Gogo* gogo)
|
||||
const Package* dummy;
|
||||
if (this->type_descriptor_defined_elsewhere(nt, &dummy))
|
||||
{
|
||||
std::string asm_name(go_selectively_encode_id(sym_name));
|
||||
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)
|
||||
*phash = this->gc_symbol_var_;
|
||||
return;
|
||||
@ -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
|
||||
// variable before converting the initializer to its backend representation
|
||||
// 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_ =
|
||||
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)
|
||||
*phash = this->gc_symbol_var_;
|
||||
|
||||
@ -7034,8 +7043,10 @@ Map_type::backend_zero_value(Gogo* gogo)
|
||||
Btype* barray_type = gogo->backend()->array_type(buint8_type, blength);
|
||||
|
||||
std::string zname = Map_type::zero_value->name();
|
||||
std::string asm_name(go_selectively_encode_id(zname));
|
||||
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);
|
||||
gogo->backend()->implicit_variable_set_init(zvar, zname, barray_type,
|
||||
false, true, true, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user