Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions gcc/rust/backend/rust-compile-extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "rust-compile-type.h"
#include "rust-diagnostics.h"
#include "rust-hir-full-decls.h"
#include "rust-attributes.h"
#include "rust-attribute-values.h"

namespace Rust {
namespace Compile {
Expand Down Expand Up @@ -57,8 +59,7 @@ class CompileExternItem : public HIRCompileBase,
rust_assert (ok);

std::string name = item.get_item_name ().as_string ();
// FIXME this is assuming C ABI
std::string asm_name = name;
GGC::Ident asm_name = get_link_name (item);

tree type = TyTyResolveCompile::compile (ctx, resolved_type);
bool is_external = true;
Expand Down Expand Up @@ -124,16 +125,7 @@ class CompileExternItem : public HIRCompileBase,

tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
std::string ir_symbol_name = function.get_item_name ().as_string ();
std::string asm_name = function.get_item_name ().as_string ();
if (fntype->get_abi () == ABI::RUST)
{
// then we need to get the canonical path of it and mangle it
auto canonical_path = ctx->get_mappings ().lookup_canonical_path (
function.get_mappings ().get_nodeid ());

ir_symbol_name = canonical_path->get () + fntype->subst_as_string ();
asm_name = ctx->mangle_item (fntype, *canonical_path);
}
GGC::Ident asm_name = get_link_name (function);

const unsigned int flags = Backend::function_is_declaration;
tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name,
Expand All @@ -158,6 +150,36 @@ class CompileExternItem : public HIRCompileBase,
ref_locus (ref_locus)
{}

template <typename T> static GGC::Ident get_link_name (T &obj)
{
AST::Attribute *use_attr = nullptr;

for (auto &attr : obj.get_outer_attrs ())
{
if (attr.get_path ().as_string () == Values::Attributes::LINK_NAME)
{
// later attributes override earlier ones
// TODO: add warning -- should duplicate
// attributes be folded elsewhere?
use_attr = &attr;
}
}

if (use_attr)
{
auto link_name
= Analysis::Attributes::extract_string_literal (*use_attr);

if (!link_name.has_value ())
rust_error_at (use_attr->get_locus (),
"malformed %<link_name%> attribute input");
else
return *link_name;
}

return obj.get_item_name ();
}

TyTy::BaseType *concrete;
tree reference;
location_t ref_locus;
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/util/rust-attribute-values.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Attributes
static constexpr auto &DOC = "doc";
static constexpr auto &MUST_USE = "must_use";
static constexpr auto &LANG = "lang";
static constexpr auto &LINK_NAME = "link_name";
static constexpr auto &LINK_SECTION = "link_section";
static constexpr auto &NO_MANGLE = "no_mangle";
static constexpr auto &REPR = "repr";
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/util/rust-attributes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::DOC, HIR_LOWERING},
{Attrs::MUST_USE, STATIC_ANALYSIS},
{Attrs::LANG, HIR_LOWERING},
{Attrs::LINK_NAME, CODE_GENERATION},
{Attrs::LINK_SECTION, CODE_GENERATION},
{Attrs::NO_MANGLE, CODE_GENERATION},
{Attrs::REPR, CODE_GENERATION},
Expand Down
3 changes: 3 additions & 0 deletions gcc/rust/util/rust-ggc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.

#include "rust-ggc.h"
#include "rust-ast.h"
#include "stringpool.h"

namespace Rust {
Expand All @@ -29,6 +30,8 @@ Ident::Ident (const std::string &str)
: inner (get_identifier_with_length (str.c_str (), str.length ()))
{}

Ident::Ident (const Rust::Identifier &ident) : Ident (ident.as_string ()) {}

bool
Ident::operator== (const std::string &other) const
{
Expand Down
4 changes: 4 additions & 0 deletions gcc/rust/util/rust-ggc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

namespace Rust {

// forward declare
class Identifier;

namespace GGC {

class Ident
Expand All @@ -33,6 +36,7 @@ class Ident
public:
Ident (const char *str);
Ident (const std::string &str);
Ident (const Rust::Identifier &ident);

bool operator== (const Ident &other) const { return inner == other.inner; }
bool operator== (const std::string &other) const;
Expand Down
16 changes: 16 additions & 0 deletions gcc/testsuite/rust/execute/torture/link-name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// { dg-additional-options "-fdump-rtl-final" }
// { dg-final { scan-rtl-dump "printf" "final" } }
// { dg-output "gcc\r*\n" }

extern "C" {
#[link_name = "printf"]
fn druckt(fmt: *const i8, ...);
}

fn main() -> i32 {
let a = "gcc\0";

unsafe { druckt("%s\n\0" as *const str as *const i8, a as *const str as *const i8); }

0
}
Loading