@@ -174,11 +174,14 @@ static tree
174
174
offset_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
175
175
static tree
176
176
sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
177
+ static tree
178
+ transmute_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype);
177
179
178
180
static const std::map<std::string,
179
181
std::function<tree (Context *, TyTy::BaseType *)>>
180
182
generic_intrinsics = {{" offset" , &offset_intrinsic_handler},
181
- {" size_of" , &sizeof_intrinsic_handler}};
183
+ {" size_of" , &sizeof_intrinsic_handler},
184
+ {" transmute" , &transmute_intrinsic_handler}};
182
185
183
186
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
184
187
@@ -340,7 +343,7 @@ sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
340
343
fntype->override_context ();
341
344
}
342
345
343
- // offset intrinsic has two params dst pointer and offset isize
346
+ // size_of has _zero_ parameters its parameter is the generic one
344
347
if (fntype->get_params ().size () != 0 )
345
348
{
346
349
rust_error_at (fntype->get_ident ().locus ,
@@ -396,5 +399,113 @@ sizeof_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
396
399
return fndecl;
397
400
}
398
401
402
+ static tree
403
+ transmute_intrinsic_handler (Context *ctx, TyTy::BaseType *fntype_tyty)
404
+ {
405
+ rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
406
+ TyTy::FnType *fntype = static_cast <TyTy::FnType *> (fntype_tyty);
407
+ const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path ;
408
+
409
+ // items can be forward compiled which means we may not need to invoke this
410
+ // code. We might also have already compiled this generic function as well.
411
+ tree lookup = NULL_TREE;
412
+ if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
413
+ fntype->get_id (), fntype))
414
+ {
415
+ // has this been added to the list then it must be finished
416
+ if (ctx->function_completed (lookup))
417
+ {
418
+ tree dummy = NULL_TREE;
419
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
420
+ {
421
+ ctx->insert_function_decl (fntype, lookup);
422
+ }
423
+ return lookup;
424
+ }
425
+ }
426
+
427
+ if (fntype->has_subsititions_defined ())
428
+ {
429
+ // override the Hir Lookups for the substituions in this context
430
+ fntype->override_context ();
431
+ }
432
+
433
+ // transmute intrinsic has one parameter
434
+ if (fntype->get_params ().size () != 1 )
435
+ {
436
+ rust_error_at (fntype->get_ident ().locus ,
437
+ " invalid number of parameters for transmute intrinsic" );
438
+ return error_mark_node;
439
+ }
440
+
441
+ // build the intrinsic function
442
+ tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
443
+ std::string ir_symbol_name
444
+ = canonical_path.get () + fntype->subst_as_string ();
445
+ std::string asm_name = ctx->mangle_item (fntype, canonical_path);
446
+
447
+ unsigned int flags = 0 ;
448
+ tree fndecl
449
+ = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name,
450
+ flags, fntype->get_ident ().locus );
451
+ TREE_PUBLIC (fndecl) = 0 ;
452
+ TREE_READONLY (fndecl) = 1 ;
453
+ DECL_ARTIFICIAL (fndecl) = 1 ;
454
+ DECL_EXTERNAL (fndecl) = 0 ;
455
+ DECL_DECLARED_INLINE_P (fndecl) = 1 ;
456
+
457
+ // setup the params
458
+ std::vector<Bvariable *> param_vars;
459
+ for (auto &parm : fntype->get_params ())
460
+ {
461
+ auto &referenced_param = parm.first ;
462
+ auto ¶m_tyty = parm.second ;
463
+ auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty);
464
+
465
+ Location param_locus = referenced_param->get_locus ();
466
+ Bvariable *compiled_param_var
467
+ = CompileFnParam::compile (ctx, fndecl, referenced_param,
468
+ compiled_param_type, param_locus);
469
+
470
+ param_vars.push_back (compiled_param_var);
471
+ }
472
+
473
+ rust_assert (param_vars.size () == 1 );
474
+ if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
475
+ return error_mark_node;
476
+
477
+ // param to convert
478
+ Bvariable *convert_me_param = param_vars.at (0 );
479
+ tree convert_me_expr
480
+ = ctx->get_backend ()->var_expression (convert_me_param, Location ());
481
+
482
+ tree enclosing_scope = NULL_TREE;
483
+ Location start_location = Location ();
484
+ Location end_location = Location ();
485
+
486
+ tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
487
+ start_location, end_location);
488
+ ctx->push_block (code_block);
489
+
490
+ // BUILTIN transmute FN BODY BEGIN
491
+ tree result_type_tree = TREE_TYPE (DECL_RESULT (fndecl));
492
+ tree result_expr
493
+ = ctx->get_backend ()->convert_expression (result_type_tree,
494
+ convert_me_expr, Location ());
495
+ auto return_statement
496
+ = ctx->get_backend ()->return_statement (fndecl, {result_expr},
497
+ Location ());
498
+ ctx->add_statement (return_statement);
499
+ // BUILTIN transmute FN BODY END
500
+
501
+ tree bind_tree = ctx->pop_block ();
502
+
503
+ gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
504
+ DECL_SAVED_TREE (fndecl) = bind_tree;
505
+ ctx->push_function (fndecl);
506
+
507
+ return fndecl;
508
+ }
509
+
399
510
} // namespace Compile
400
511
} // namespace Rust
0 commit comments