https://gcc.gnu.org/g:29605ae6596503a587700d854e2dbdd994cbaa61
commit r17-4310-g29605ae6596503a587700d854e2dbdd994cbaa61 Author: Yap Zhi Heng <[email protected]> Date: Sat Aug 29 16:11:37 2026 +0800 gccrs: Implement 1-to-1 adapters for compiling LLVM built-ins signatures with GCC built-ins Similar to the previous commit, but for FORWARD_ARGUMENTS cases in CompileExternItem::visit (ExternalFunctionItem). Compiled 006t.original output from compiling llvm_builtins.rs for only the enabled FORWARD_ARGUMENT cases (): ``` u8 llvm_addcarryx_u32 (const u8 a, const u32 b, const u32 c, u8 * const {ref-all} d) { return (u8) __builtin_ia32_addcarryx_u32 ((unsigned char) a, (u32) b, (u32) c, (u32 *) d); } u8 llvm_addcarryx_u64 (const u8 a, const u64 b, const u64 c, u8 * const {ref-all} d) { return (u8) __builtin_ia32_addcarryx_u64 ((unsigned char) a, (unsigned long) b, (unsigned long) c, (unsigned long *) d); } ``` vcvtph2ps and vcvtps2ph functions are not supported yet as gccrs doesn't support SIMD types yet. gcc/rust/ChangeLog: * backend/rust-builtins.cc (BuiltinsContext::register_llvm_to_gcc_builtin): Add entries for vcvtph2ps & vcvtps2ph cases (currently unused due to the reason mentioned above). * backend/rust-compile-extern.h (CompileExternItem::visit(HIR::ExternalFunctionItem)): Remove placeholder function in the FORWARD_ARGUMENTS case under compilation of UNADJUSTED ABI. (CompileExternItem::compile_x86_forwarding_adapter): New function to adapt LLVM's addcarryx function signatures by simply forwarding the parameters and return var without changes. gcc/testsuite/ChangeLog: * rust/compile/llvm_builtins.rs: Enable addcarryx cases, add TODO comment for vcvtph2ps & vcvtps2ph cases. Signed-off-by: Yap Zhi Heng <[email protected]> Diff: --- gcc/rust/backend/rust-builtins.cc | 12 +++- gcc/rust/backend/rust-compile-extern.h | 88 +++++++++++++++++++++++++++-- gcc/testsuite/rust/compile/llvm_builtins.rs | 10 ++-- 3 files changed, 100 insertions(+), 10 deletions(-) diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index 569c42576e03..de2d97eb1de5 100644 --- a/gcc/rust/backend/rust-builtins.cc +++ b/gcc/rust/backend/rust-builtins.cc @@ -416,7 +416,17 @@ BuiltinsContext::register_llvm_to_gcc_builtin () {"__builtin_ia32_addcarryx_u64", LlvmBuiltinAdapter::FORWARD_ARGUMENTS}}, {"llvm.x86.subborrow.64", {"__builtin_ia32_sbb_u64", - LlvmBuiltinAdapter::OUTPUT_POINTER_STATUS_VALUE}}}; + LlvmBuiltinAdapter::OUTPUT_POINTER_STATUS_VALUE}}, + + {"llvm.x86.vcvtph2ps.128", + {"__builtin_ia32_vcvtph2ps", LlvmBuiltinAdapter::FORWARD_ARGUMENTS}}, + {"llvm.x86.vcvtph2ps.256", + {"__builtin_ia32_vcvtph2ps256", LlvmBuiltinAdapter::FORWARD_ARGUMENTS}}, + {"llvm.x86.vcvtps2ph.128", + {"__builtin_ia32_vcvtps2ph", LlvmBuiltinAdapter::FORWARD_ARGUMENTS}}, + {"llvm.x86.vcvtps2ph.256", + {"__builtin_ia32_vcvtps2ph256", LlvmBuiltinAdapter::FORWARD_ARGUMENTS}}, + }; } void diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index f9aecef5b873..b2237b77c246 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -171,10 +171,9 @@ public: function.get_locus ()); break; case LlvmBuiltinAdapter::FORWARD_ARGUMENTS: - // TODO placeholder - adapter_tree = compile_x86_output_pointer_adapter ( - ctx, fntype, resolved, OutputTupleOrder::STATUS_VALUE, - function.get_locus ()); + adapter_tree + = compile_x86_forwarding_adapter (ctx, fntype, resolved, + function.get_locus ()); break; } @@ -262,7 +261,7 @@ private: * @param order whether the LLVM built-in returns (value, status) or (status, * value) * @param locus - * @return tree + * @return tree the resultant wrapper function */ static tree compile_x86_output_pointer_adapter (Context *ctx, TyTy::FnType *fntype, @@ -393,6 +392,85 @@ private: return fndecl; } + /** + * Compiles a 1-to-1 wrapper for LLVM built-ins that wraps around GCC + * built-ins. + * + * @param ctx + * @param fntype the LLVM built-in function type + * @param gcc_builtin the GCC built-in function + * @param locus + * @return tree the resultant wrapper function + */ + static tree compile_x86_forwarding_adapter (Context *ctx, + TyTy::FnType *fntype, + tree gcc_builtin, + location_t locus) + { + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + + const auto &path = fntype->get_ident ().path; + std::string ir_name = path.get () + fntype->subst_as_string (); + std::string asm_name = ctx->mangle_item (fntype, path); + + // start building the wrapper function + tree fndecl + = Backend::function (compiled_fn_type, ir_name, asm_name, 0, locus); + + TREE_PUBLIC (fndecl) = 0; + DECL_ARTIFICIAL (fndecl) = 1; + DECL_EXTERNAL (fndecl) = 0; + DECL_DECLARED_INLINE_P (fndecl) = 1; + + // compile params for the rust wrapper + std::vector<Bvariable *> param_vars; + param_vars.reserve (fntype->get_params ().size ()); + for (auto ¶m : fntype->get_params ()) + { + auto &pattern = param.get_pattern (); + tree type = TyTyResolveCompile::compile (ctx, param.get_type ()); + Bvariable *variable + = CompileFnParam::compile (ctx, fndecl, pattern, type, + pattern.get_locus ()); + param_vars.emplace_back (variable); + } + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + // forward the rust params, convert each into the corresponding gcc + // built-in param type + std::vector<tree> call_arguments; + call_arguments.reserve (param_vars.size ()); + tree gcc_argument_types = TYPE_ARG_TYPES (TREE_TYPE (gcc_builtin)); + for (Bvariable *param : param_vars) + { + tree argument = param->get_tree (locus); + tree expected_type = TREE_VALUE (gcc_argument_types); + argument = Backend::convert_expression (expected_type, argument, locus); + call_arguments.emplace_back (argument); + gcc_argument_types = TREE_CHAIN (gcc_argument_types); + } + + tree builtin_call + = build_call_expr_loc_array (locus, gcc_builtin, + static_cast<int> (call_arguments.size ()), + call_arguments.data ()); + tree wrapper_ret_type = TREE_TYPE (DECL_RESULT (fndecl)); + + builtin_call + = Backend::convert_expression (wrapper_ret_type, builtin_call, locus); + tree block = Backend::block (fndecl, NULL_TREE, {}, locus, locus); + ctx->push_block (block); + ctx->add_statement ( + Backend::return_statement (fndecl, builtin_call, locus)); + tree body = ctx->pop_block (); + DECL_SAVED_TREE (fndecl) = body; + + ctx->push_function (fndecl); + return fndecl; + } + TyTy::BaseType *concrete; tree reference; location_t ref_locus; diff --git a/gcc/testsuite/rust/compile/llvm_builtins.rs b/gcc/testsuite/rust/compile/llvm_builtins.rs index 6503c0be2bde..7f44eb02fa9d 100644 --- a/gcc/testsuite/rust/compile/llvm_builtins.rs +++ b/gcc/testsuite/rust/compile/llvm_builtins.rs @@ -19,17 +19,19 @@ extern "unadjusted" { #[link_name = "llvm.x86.addcarry.32"] fn llvm_addcarry_u32(a: u8, b: u32, c: u32) -> (u8, u32); - // #[link_name = "llvm.x86.addcarryx.u32"] - // fn llvm_addcarryx_u32(a: u8, b: u32, c: u32, d: *mut u8) -> u8; + #[link_name = "llvm.x86.addcarryx.u32"] + fn llvm_addcarryx_u32(a: u8, b: u32, c: u32, d: *mut u8) -> u8; #[link_name = "llvm.x86.subborrow.32"] fn llvm_subborrow_u32(a: u8, b: u32, c: u32) -> (u8, u32); #[link_name = "llvm.x86.addcarry.64"] fn llvm_addcarry_u64(a: u8, b: u64, c: u64) -> (u8, u64); - // #[link_name = "llvm.x86.addcarryx.u64"] - // fn llvm_addcarryx_u64(a: u8, b: u64, c: u64, d: *mut u8) -> u8; + #[link_name = "llvm.x86.addcarryx.u64"] + fn llvm_addcarryx_u64(a: u8, b: u64, c: u64, d: *mut u8) -> u8; #[link_name = "llvm.x86.subborrow.64"] fn llvm_subborrow_u64(a: u8, b: u64, c: u64) -> (u8, u64); + // TODO implement the SIMD types (i16x8, f32x4, f32x8) before + // enabling these tests // #[link_name = "llvm.x86.vcvtph2ps.128"] // fn llvm_vcvtph2ps_128(a: i16x8) -> f32x4; // #[link_name = "llvm.x86.vcvtph2ps.256"]
