Skip to content

Commit f057445

Browse files
committed
Add size_of intrinsic
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
1 parent 796c978 commit f057445

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

gcc/rust/backend/rust-compile-intrinsic.cc

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,13 @@ class SimpleIntrinsics
172172

173173
static tree
174174
offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
175+
static tree
176+
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
175177

176178
static const std::map<std::string,
177179
std::function<tree (Context *, TyTy::BaseType *)>>
178-
generic_intrinsics = {{"offset", &offset_intrinsic_handler}};
180+
generic_intrinsics = {{"offset", &offset_intrinsic_handler},
181+
{"size_of", &sizeof_intrinsic_handler}};
179182

180183
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
181184

@@ -308,5 +311,94 @@ offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
308311
return fndecl;
309312
}
310313

314+
static tree
315+
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
316+
{
317+
rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
318+
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
319+
const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path;
320+
321+
// items can be forward compiled which means we may not need to invoke this
322+
// code. We might also have already compiled this generic function as well.
323+
tree lookup = NULL_TREE;
324+
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
325+
fntype->get_id (), fntype))
326+
{
327+
// has this been added to the list then it must be finished
328+
if (ctx->function_completed (lookup))
329+
{
330+
tree dummy = NULL_TREE;
331+
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
332+
{
333+
ctx->insert_function_decl (fntype, lookup);
334+
}
335+
return lookup;
336+
}
337+
}
338+
339+
if (fntype->has_subsititions_defined ())
340+
{
341+
// override the Hir Lookups for the substituions in this context
342+
fntype->override_context ();
343+
}
344+
345+
// offset intrinsic has two params dst pointer and offset isize
346+
if (fntype->get_params ().size () != 0)
347+
{
348+
rust_error_at (fntype->get_ident ().locus,
349+
"invalid number of parameters for size of intrinsic");
350+
return error_mark_node;
351+
}
352+
353+
// get the template parameter type tree fn size_of<T>();
354+
rust_assert (fntype->get_num_substitutions () == 1);
355+
auto &param_mapping = fntype->get_substs ().at (0);
356+
const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
357+
TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
358+
tree template_parameter_type
359+
= TyTyResolveCompile::compile (ctx, resolved_tyty);
360+
361+
// build the intrinsic function
362+
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
363+
std::string ir_symbol_name
364+
= canonical_path.get () + fntype->subst_as_string ();
365+
std::string asm_name = ctx->mangle_item (fntype, canonical_path);
366+
367+
unsigned int flags = 0;
368+
tree fndecl
369+
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name,
370+
flags, fntype->get_ident ().locus);
371+
TREE_PUBLIC (fndecl) = 0;
372+
TREE_READONLY (fndecl) = 1;
373+
DECL_ARTIFICIAL (fndecl) = 1;
374+
DECL_EXTERNAL (fndecl) = 0;
375+
DECL_DECLARED_INLINE_P (fndecl) = 1;
376+
377+
tree enclosing_scope = NULL_TREE;
378+
Location start_location = Location ();
379+
Location end_location = Location ();
380+
381+
tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
382+
start_location, end_location);
383+
ctx->push_block (code_block);
384+
385+
// BUILTIN size_of FN BODY BEGIN
386+
tree size_expr = TYPE_SIZE_UNIT (template_parameter_type);
387+
auto return_statement
388+
= ctx->get_backend ()->return_statement (fndecl, {size_expr}, Location ());
389+
ctx->add_statement (return_statement);
390+
// BUILTIN size_of FN BODY END
391+
392+
tree bind_tree = ctx->pop_block ();
393+
394+
gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
395+
DECL_SAVED_TREE (fndecl) = bind_tree;
396+
397+
ctx->pop_fn ();
398+
ctx->push_function (fndecl);
399+
400+
return fndecl;
401+
}
402+
311403
} // namespace Compile
312404
} // namespace Rust

0 commit comments

Comments
 (0)