Skip to content

Commit

Permalink
Adds support for compilation of extern "C" functions.
Browse files Browse the repository at this point in the history
This adds extern block compilation support. It currently assumes the C abi
and does not perform any name mangling. It does not support varadic
arguments yet but its the initial support to get this working.

Fixes #421
  • Loading branch information
philberty committed Jul 27, 2021
1 parent b176f38 commit 8d97ff8
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
150 changes: 150 additions & 0 deletions gcc/rust/backend/rust-compile-extern.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (C) 2020 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.

#ifndef RUST_COMPILE_EXTERN_ITEM
#define RUST_COMPILE_EXTERN_ITEM

#include "rust-compile-base.h"
#include "rust-compile-tyty.h"
#include "rust-compile-implitem.h"
#include "rust-compile-var-decl.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
#include "rust-compile-fnparam.h"

namespace Rust {
namespace Compile {

class CompileExternItem : public HIRCompileBase
{
using Rust::Compile::HIRCompileBase::visit;

public:
static void compile (HIR::ExternalItem *item, Context *ctx,
bool compile_fns = true,
TyTy::BaseType *concrete = nullptr)
{
CompileExternItem compiler (ctx, compile_fns, concrete);
item->accept_vis (compiler);
}

void visit (HIR::ExternalStaticItem &item) override
{
TyTy::BaseType *resolved_type = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (item.get_mappings ().get_hirid (),
&resolved_type);
rust_assert (ok);

std::string name = item.get_item_name ();

// FIXME
// this is assuming C ABI
std::string asm_name = "_" + name;

Btype *type = TyTyResolveCompile::compile (ctx, resolved_type);
bool is_external = true;
bool is_hidden = false;
bool in_unique_section = false;

Bvariable *static_global
= ctx->get_backend ()->global_variable (name, asm_name, type, is_external,
is_hidden, in_unique_section,
item.get_locus ());
ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global);
ctx->push_var (static_global);
}

void visit (HIR::ExternalFunctionItem &function) override
{
if (!compile_fns)
return;

TyTy::BaseType *fntype_tyty;
if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
&fntype_tyty))
{
rust_fatal_error (function.get_locus (),
"failed to lookup function type");
return;
}

rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
if (fntype->has_subsititions_defined ())
{
// we cant do anything for this only when it is used and a concrete type
// is given
if (concrete == nullptr)
return;
else
{
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
fntype = static_cast<TyTy::FnType *> (concrete);
}
}

// items can be forward compiled which means we may not need to invoke this
// code. We might also have already compiled this generic function as well.
Bfunction *lookup = nullptr;
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, fntype))
{
// has this been added to the list then it must be finished
if (ctx->function_completed (lookup))
{
Bfunction *dummy = nullptr;
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
ctx->insert_function_decl (fntype->get_ty_ref (), lookup, fntype);

return;
}
}

if (fntype->has_subsititions_defined ())
{
// override the Hir Lookups for the substituions in this context
fntype->override_context ();
}

::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);

const unsigned int flags
= Backend::function_is_declaration | Backend::function_is_visible;

std::string ir_symbol_name = function.get_item_name ();
// FIXME this assumes C ABI
std::string asm_name = function.get_item_name ();

Bfunction *fndecl
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
asm_name, flags, function.get_locus ());
ctx->insert_function_decl (fntype->get_ty_ref (), fndecl, fntype);
}

private:
CompileExternItem (Context *ctx, bool compile_fns, TyTy::BaseType *concrete)
: HIRCompileBase (ctx), compile_fns (compile_fns), concrete (concrete)
{}

bool compile_fns;
TyTy::BaseType *concrete;
};

} // namespace Compile
} // namespace Rust

#endif // RUST_COMPILE_EXTERN_ITEM
9 changes: 9 additions & 0 deletions gcc/rust/backend/rust-compile-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
#include "rust-compile-fnparam.h"
#include "rust-compile-extern.h"

namespace Rust {
namespace Compile {
Expand Down Expand Up @@ -274,6 +275,14 @@ class CompileItem : public HIRCompileBase
compile_fns);
}

void visit (HIR::ExternBlock &extern_block) override
{
for (auto &item : extern_block.get_extern_items ())
{
CompileExternItem::compile (item.get (), ctx, compile_fns, concrete);
}
}

private:
CompileItem (Context *ctx, bool compile_fns, TyTy::BaseType *concrete)
: HIRCompileBase (ctx), compile_fns (compile_fns), concrete (concrete)
Expand Down

0 comments on commit 8d97ff8

Please sign in to comment.