Skip to content

Commit d3eeed8

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 19ba1f3 commit d3eeed8

File tree

1 file changed

+94
-1
lines changed

1 file changed

+94
-1
lines changed

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

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "rust-compile-intrinsic.h"
1818
#include "langhooks.h"
19+
#include "print-tree.h"
1920
#include "rust-compile-type.h"
2021
#include "rust-compile-fnparam.h"
2122
#include "rust-tree.h"
@@ -172,6 +173,8 @@ class SimpleIntrinsics
172173

173174
static tree
174175
offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
176+
static tree
177+
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
175178

176179
typedef tree (*generic_intrinsic_handler) (Context *ctx,
177180
TyTy::BaseType *fntype);
@@ -181,7 +184,8 @@ struct BuiltinGenericIntrinsic
181184
generic_intrinsic_handler handler;
182185
};
183186
static const BuiltinGenericIntrinsic generic_intrinsics[]
184-
= {{"offset", &offset_intrinsic_handler}};
187+
= {{"offset", &offset_intrinsic_handler},
188+
{"size_of", &sizeof_intrinsic_handler}};
185189

186190
#define GENERIC_INTRINSIC_SIZE \
187191
sizeof (generic_intrinsics) / sizeof (BuiltinGenericIntrinsic)
@@ -322,5 +326,94 @@ offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
322326
return fndecl;
323327
}
324328

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

0 commit comments

Comments
 (0)