You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust传递结构体采用何种ABI?x86_64下与C的差异解析

Rust x86_64下结构体返回的ABI规则解析

在x86_64系统中,通用调用约定为:当返回值大小≤16字节时,通过寄存器RAX和RDX传递;当返回值大小>16字节时,通过第一个sret参数传递。但Rust的表现似乎和这一规则不符。

C语言示例及表现

代码实现

struct test_struct {
   int a;
   int b;
   int c;
};

struct test_struct foo() {
    struct test_struct a = {1,2,3};
    return a;
}

对应LLVM IR

define dso_local { i64, i32 } @foo() 

该结构体大小为12字节(≤16字节),可见返回值通过寄存器传递,符合x86_64通用约定。

Rust语言示例及表现

代码实现

pub struct test_struct {
   a: i32,
   b: i32,
   c: i32,
}
pub fn foo() -> test_struct {
   let data = test_struct {
       a: 0,
       b: 1,
       c: 2,
   };

   data
}

对应LLVM IR

define void @_ZN7example3foo17hd5941535b576c335E(ptr sret(%test_struct) %0) unnamed_addr

同样是12字节的结构体,却使用sret参数传递返回值,和C的表现不一致。

Rust的结构体返回ABI规则

Rust默认使用Rust专用ABI,而非C的System V ABI,该ABI设计更侧重编译器优化与语言内存安全需求,和C的约定存在明显差异:

  • 几乎所有结构体返回都会通过sret参数传递(调用者预先分配内存,函数将结果写入该地址),无论结构体大小是否≤16字节。
  • 仅当结构体是可拆分为整数类型的简单标量组合(如单个i32、两个i64组成的结构体等),编译器才可能优化为寄存器传递,且依赖编译优化级别。
  • 若需让Rust函数遵循C的System V ABI,只需给函数添加#[no_mangle]和extern "C"注解,此时结构体返回行为会和C一致。

示例修改后的Rust代码:

#[no_mangle]
pub extern "C" fn foo() -> test_struct {
   let data = test_struct {
       a: 0,
       b: 1,
       c: 2,
   };

   data
}

对应的LLVM IR会和C版本类似,采用寄存器传递返回值。


内容的提问来源于stack exchange,提问作者super_jh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:13:20