Skip to content

Commit

Permalink
Add size_of intrinsic
Browse files Browse the repository at this point in the history
This is another type of intrisic since the function contains no parameters
but the argument for the size_of is the generic parameter T. Which uses
TYPE_SIZE_UNIT to get the type size in bytes. GCC will optimize the
function call away when you turn optimizations on.

Addresses #658
  • Loading branch information
philberty committed Mar 10, 2022
1 parent ffb6ade commit 7679cbe
Showing 1 changed file with 94 additions and 1 deletion.
95 changes: 94 additions & 1 deletion gcc/rust/backend/rust-compile-intrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "rust-compile-intrinsic.h"
#include "langhooks.h"
#include "print-tree.h"
#include "rust-compile-type.h"
#include "rust-compile-fnparam.h"
#include "rust-tree.h"
Expand Down Expand Up @@ -172,6 +173,8 @@ class SimpleIntrinsics

static tree
offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
static tree
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);

typedef tree (*generic_intrinsic_handler) (Context *ctx,
TyTy::BaseType *fntype);
Expand All @@ -181,7 +184,8 @@ struct BuiltinGenericIntrinsic
generic_intrinsic_handler handler;
};
static const BuiltinGenericIntrinsic generic_intrinsics[]
= {{"offset", &offset_intrinsic_handler}};
= {{"offset", &offset_intrinsic_handler},
{"size_of", &sizeof_intrinsic_handler}};

#define GENERIC_INTRINSIC_SIZE \
sizeof (generic_intrinsics) / sizeof (BuiltinGenericIntrinsic)
Expand Down Expand Up @@ -322,5 +326,94 @@ offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
return fndecl;
}

static tree
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
{
rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path;

// 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.
tree lookup = NULL_TREE;
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
fntype->get_id (), fntype))
{
// has this been added to the list then it must be finished
if (ctx->function_completed (lookup))
{
tree dummy = NULL_TREE;
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
{
ctx->insert_function_decl (fntype, lookup);
}
return lookup;
}
}

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

// offset intrinsic has two params dst pointer and offset isize
if (fntype->get_params ().size () != 0)
{
rust_error_at (fntype->get_ident ().locus,
"invalid number of parameters for size of intrinsic");
return error_mark_node;
}

// get the template parameter type tree fn size_of<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);

// build the intrinsic function
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
std::string ir_symbol_name
= canonical_path.get () + fntype->subst_as_string ();
std::string asm_name = ctx->mangle_item (fntype, canonical_path);

unsigned int flags = 0;
tree fndecl
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name,
flags, fntype->get_ident ().locus);
TREE_PUBLIC (fndecl) = 0;
TREE_READONLY (fndecl) = 1;
DECL_ARTIFICIAL (fndecl) = 1;
DECL_EXTERNAL (fndecl) = 0;
DECL_DECLARED_INLINE_P (fndecl) = 1;

tree enclosing_scope = NULL_TREE;
Location start_location = Location ();
Location end_location = Location ();

tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
start_location, end_location);
ctx->push_block (code_block);

// BUILTIN size_of FN BODY BEGIN
tree size_expr = TYPE_SIZE_UNIT (template_parameter_type);
auto return_statement
= ctx->get_backend ()->return_statement (fndecl, {size_expr}, Location ());
ctx->add_statement (return_statement);
// BUILTIN size_of FN BODY END

tree bind_tree = ctx->pop_block ();

gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
DECL_SAVED_TREE (fndecl) = bind_tree;

ctx->pop_fn ();
ctx->push_function (fndecl);

return fndecl;
}

} // namespace Compile
} // namespace Rust

0 comments on commit 7679cbe

Please sign in to comment.