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:
Than McIntosh 2016-11-22 22:28:05 +00:00 committed by Ian Lance Taylor
parent 7e98cccbd8
commit f3878205dd
10 changed files with 303 additions and 192 deletions

View File

@ -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

View File

@ -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) $<

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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);

View 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();
}

View 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)

View File

@ -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());

View File

@ -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);