Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
3c31841c
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3c31841c
编写于
7月 13, 2015
作者:
L
Luqman Aden
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rust_trans: struct argument over ffi were passed incorrectly in some situations on x86_64.
上级
56a14192
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
395 addition
and
6 deletion
+395
-6
src/librustc_trans/trans/cabi_x86_64.rs
src/librustc_trans/trans/cabi_x86_64.rs
+41
-6
src/test/run-make/extern-fn-struct-passing-abi/Makefile
src/test/run-make/extern-fn-struct-passing-abi/Makefile
+5
-0
src/test/run-make/extern-fn-struct-passing-abi/test.c
src/test/run-make/extern-fn-struct-passing-abi/test.c
+215
-0
src/test/run-make/extern-fn-struct-passing-abi/test.rs
src/test/run-make/extern-fn-struct-passing-abi/test.rs
+134
-0
未找到文件。
src/librustc_trans/trans/cabi_x86_64.rs
浏览文件 @
3c31841c
...
...
@@ -410,18 +410,53 @@ fn x86_64_ty<F>(ccx: &CrateContext,
}
}
let
mut
arg_tys
=
Vec
::
new
();
for
t
in
atys
{
let
ty
=
x86_64_ty
(
ccx
,
*
t
,
|
cls
|
cls
.is_pass_byval
(),
Attribute
::
ByVal
);
arg_tys
.push
(
ty
);
}
let
mut
int_regs
=
6
;
// RDI, RSI, RDX, RCX, R8, R9
let
mut
sse_regs
=
8
;
let
ret_ty
=
if
ret_def
{
x86_64_ty
(
ccx
,
rty
,
|
cls
|
cls
.is_ret_bysret
(),
Attribute
::
StructRet
)
x86_64_ty
(
ccx
,
rty
,
|
cls
|
{
if
cls
.is_ret_bysret
()
{
// `sret` parameter thus one less register available
int_regs
-=
1
;
true
}
else
{
false
}
},
Attribute
::
StructRet
)
}
else
{
ArgType
::
direct
(
Type
::
void
(
ccx
),
None
,
None
,
None
)
};
let
mut
arg_tys
=
Vec
::
new
();
for
t
in
atys
{
let
ty
=
x86_64_ty
(
ccx
,
*
t
,
|
cls
|
{
let
needed_int
=
cls
.iter
()
.filter
(|
&&
c
|
c
==
Int
)
.count
();
let
needed_sse
=
cls
.iter
()
.filter
(|
c
|
c
.is_sse
())
.count
();
let
in_mem
=
cls
.is_pass_byval
()
||
int_regs
<
needed_int
||
sse_regs
<
needed_sse
;
if
in_mem
{
// `byval` parameter thus one less integer register available
int_regs
-=
1
;
}
else
{
// split into sized chunks passed individually
int_regs
-=
needed_int
;
sse_regs
-=
needed_sse
;
}
in_mem
},
Attribute
::
ByVal
);
arg_tys
.push
(
ty
);
// An integer, pointer, double or float parameter
// thus the above closure passed to `x86_64_ty` won't
// get called.
if
t
.kind
()
==
Integer
||
t
.kind
()
==
Pointer
{
int_regs
-=
1
;
}
else
if
t
.kind
()
==
Double
||
t
.kind
()
==
Float
{
sse_regs
-=
1
;
}
}
return
FnType
{
arg_tys
:
arg_tys
,
ret_ty
:
ret_ty
,
...
...
src/test/run-make/extern-fn-struct-passing-abi/Makefile
0 → 100644
浏览文件 @
3c31841c
-include
../tools.mk
all
:
$(call NATIVE_STATICLIB
,
test)
$(RUSTC)
test.rs
$(
call
RUN,test
)
||
exit
1
src/test/run-make/extern-fn-struct-passing-abi/test.c
0 → 100644
浏览文件 @
3c31841c
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#include <assert.h>
#include <stdint.h>
struct
Rect
{
int32_t
a
;
int32_t
b
;
int32_t
c
;
int32_t
d
;
};
struct
BiggerRect
{
struct
Rect
s
;
int32_t
a
;
int32_t
b
;
};
struct
FloatRect
{
int32_t
a
;
int32_t
b
;
double
c
;
};
struct
Huge
{
int32_t
a
;
int32_t
b
;
int32_t
c
;
int32_t
d
;
int32_t
e
;
};
// SysV ABI:
// a, b, c, d, e should be in registers
// s should be byval pointer
void
byval_rect
(
int32_t
a
,
int32_t
b
,
int32_t
c
,
int32_t
d
,
int32_t
e
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
c
==
3
);
assert
(
d
==
4
);
assert
(
e
==
5
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
}
// SysV ABI:
// a, b, c, d, e, f, g should be in sse registers
// s should be split across 2 registers
// t should be byval pointer
void
byval_rect_floats
(
float
a
,
float
b
,
double
c
,
float
d
,
float
e
,
float
f
,
double
g
,
struct
Rect
s
,
struct
FloatRect
t
)
{
assert
(
a
==
1
.);
assert
(
b
==
2
.);
assert
(
c
==
3
.);
assert
(
d
==
4
.);
assert
(
e
==
5
.);
assert
(
f
==
6
.);
assert
(
g
==
7
.);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
assert
(
t
.
a
==
3489
);
assert
(
t
.
b
==
3490
);
assert
(
t
.
c
==
8
.);
}
// SysV ABI:
// a, b, d, e should be in registers
// c passed via sse registers
// s should be byval pointer
void
byval_rect_with_float
(
int32_t
a
,
int32_t
b
,
float
c
,
int32_t
d
,
int32_t
e
,
int32_t
f
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
c
==
3
.);
assert
(
d
==
4
);
assert
(
e
==
5
);
assert
(
f
==
6
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
}
// SysV ABI:
// a, b should be in registers
// s should be split across 2 registers
void
split_rect
(
int32_t
a
,
int32_t
b
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
}
// SysV ABI:
// a, b should be in sse registers
// s should be split across int32_t & sse registers
void
split_rect_floats
(
float
a
,
float
b
,
struct
FloatRect
s
)
{
assert
(
a
==
1
.);
assert
(
b
==
2
.);
assert
(
s
.
a
==
3489
);
assert
(
s
.
b
==
3490
);
assert
(
s
.
c
==
8
.);
}
// SysV ABI:
// a, b, d, f should be in registers
// c, e passed via sse registers
// s should be split across 2 registers
void
split_rect_with_floats
(
int32_t
a
,
int32_t
b
,
float
c
,
int32_t
d
,
float
e
,
int32_t
f
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
c
==
3
.);
assert
(
d
==
4
);
assert
(
e
==
5
.);
assert
(
f
==
6
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
}
// SysV ABI:
// a, b, c should be in registers
// s should be split across 2 registers
// t should be a byval pointer
void
split_and_byval_rect
(
int32_t
a
,
int32_t
b
,
int32_t
c
,
struct
Rect
s
,
struct
Rect
t
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
c
==
3
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
assert
(
t
.
a
==
553
);
assert
(
t
.
b
==
554
);
assert
(
t
.
c
==
555
);
assert
(
t
.
d
==
556
);
}
// SysV ABI:
// a, b should in registers
// s and return should be split across 2 registers
struct
Rect
split_ret_byval_struct
(
int32_t
a
,
int32_t
b
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
return
s
;
}
// SysV ABI:
// a, b, c, d should be in registers
// return should be in a hidden sret pointer
// s should be a byval pointer
struct
BiggerRect
sret_byval_struct
(
int32_t
a
,
int32_t
b
,
int32_t
c
,
int32_t
d
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
c
==
3
);
assert
(
d
==
4
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
struct
BiggerRect
t
;
t
.
s
=
s
;
t
.
a
=
27834
;
t
.
b
=
7657
;
return
t
;
}
// SysV ABI:
// a, b should be in registers
// return should be in a hidden sret pointer
// s should be split across 2 registers
struct
BiggerRect
sret_split_struct
(
int32_t
a
,
int32_t
b
,
struct
Rect
s
)
{
assert
(
a
==
1
);
assert
(
b
==
2
);
assert
(
s
.
a
==
553
);
assert
(
s
.
b
==
554
);
assert
(
s
.
c
==
555
);
assert
(
s
.
d
==
556
);
struct
BiggerRect
t
;
t
.
s
=
s
;
t
.
a
=
27834
;
t
.
b
=
7657
;
return
t
;
}
// SysV ABI:
// s should be byval pointer (since sizeof(s) > 16)
// return should in a hidden sret pointer
struct
Huge
huge_struct
(
struct
Huge
s
)
{
assert
(
s
.
a
==
5647
);
assert
(
s
.
b
==
5648
);
assert
(
s
.
c
==
5649
);
assert
(
s
.
d
==
5650
);
assert
(
s
.
e
==
5651
);
return
s
;
}
src/test/run-make/extern-fn-struct-passing-abi/test.rs
0 → 100644
浏览文件 @
3c31841c
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Passing structs via FFI should work regardless of whether
// the functions gets passed in multiple registers or is a hidden pointer
#[derive(Clone,
Copy,
Debug,
PartialEq)]
#[repr(C)]
struct
Rect
{
a
:
i32
,
b
:
i32
,
c
:
i32
,
d
:
i32
}
#[derive(Clone,
Copy,
Debug,
PartialEq)]
#[repr(C)]
struct
BiggerRect
{
s
:
Rect
,
a
:
i32
,
b
:
i32
}
#[derive(Clone,
Copy,
Debug,
PartialEq)]
#[repr(C)]
struct
FloatRect
{
a
:
i32
,
b
:
i32
,
c
:
f64
}
#[derive(Clone,
Copy,
Debug,
PartialEq)]
#[repr(C)]
struct
Huge
{
a
:
i32
,
b
:
i32
,
c
:
i32
,
d
:
i32
,
e
:
i32
}
#[link(name
=
"test"
,
kind
=
"static"
)]
extern
{
// SysV ABI:
// a, b, c, d, e should be in registers
// s should be byval pointer
fn
byval_rect
(
a
:
i32
,
b
:
i32
,
c
:
i32
,
d
:
i32
,
e
:
i32
,
s
:
Rect
);
// SysV ABI:
// a, b, c, d, e, f, g should be in sse registers
// s should be split across 2 registers
// t should be byval pointer
fn
byval_rect_floats
(
a
:
f32
,
b
:
f32
,
c
:
f64
,
d
:
f32
,
e
:
f32
,
f
:
f32
,
g
:
f64
,
s
:
Rect
,
t
:
FloatRect
);
// SysV ABI:
// a, b, d, e should be in registers
// c passed via sse registers
// s should be byval pointer
fn
byval_rect_with_float
(
a
:
i32
,
b
:
i32
,
c
:
f32
,
d
:
i32
,
e
:
i32
,
f
:
i32
,
s
:
Rect
);
// SysV ABI:
// a, b should be in registers
// s should be split across 2 registers
fn
split_rect
(
a
:
i32
,
b
:
i32
,
s
:
Rect
);
// SysV ABI:
// a, b should be in sse registers
// s should be split across int & sse registers
fn
split_rect_floats
(
a
:
f32
,
b
:
f32
,
s
:
FloatRect
);
// SysV ABI:
// a, b, d, f should be in registers
// c, e passed via sse registers
// s should be split across 2 registers
fn
split_rect_with_floats
(
a
:
i32
,
b
:
i32
,
c
:
f32
,
d
:
i32
,
e
:
f32
,
f
:
i32
,
s
:
Rect
);
// SysV ABI:
// a, b, c should be in registers
// s should be split across 2 registers
// t should be a byval pointer
fn
split_and_byval_rect
(
a
:
i32
,
b
:
i32
,
c
:
i32
,
s
:
Rect
,
t
:
Rect
);
// SysV ABI:
// a, b should in registers
// s and return should be split across 2 registers
fn
split_ret_byval_struct
(
a
:
i32
,
b
:
i32
,
s
:
Rect
)
->
Rect
;
// SysV ABI:
// a, b, c, d should be in registers
// return should be in a hidden sret pointer
// s should be a byval pointer
fn
sret_byval_struct
(
a
:
i32
,
b
:
i32
,
c
:
i32
,
d
:
i32
,
s
:
Rect
)
->
BiggerRect
;
// SysV ABI:
// a, b should be in registers
// return should be in a hidden sret pointer
// s should be split across 2 registers
fn
sret_split_struct
(
a
:
i32
,
b
:
i32
,
s
:
Rect
)
->
BiggerRect
;
// SysV ABI:
// s should be byval pointer (since sizeof(s) > 16)
// return should in a hidden sret pointer
fn
huge_struct
(
s
:
Huge
)
->
Huge
;
}
fn
main
()
{
let
s
=
Rect
{
a
:
553
,
b
:
554
,
c
:
555
,
d
:
556
};
let
t
=
BiggerRect
{
s
:
s
,
a
:
27834
,
b
:
7657
};
let
u
=
FloatRect
{
a
:
3489
,
b
:
3490
,
c
:
8
.
};
let
v
=
Huge
{
a
:
5647
,
b
:
5648
,
c
:
5649
,
d
:
5650
,
e
:
5651
};
unsafe
{
byval_rect
(
1
,
2
,
3
,
4
,
5
,
s
);
byval_rect_floats
(
1
.
,
2
.
,
3
.
,
4
.
,
5
.
,
6
.
,
7
.
,
s
,
u
);
byval_rect_with_float
(
1
,
2
,
3.0
,
4
,
5
,
6
,
s
);
split_rect
(
1
,
2
,
s
);
split_rect_floats
(
1
.
,
2
.
,
u
);
split_rect_with_floats
(
1
,
2
,
3.0
,
4
,
5.0
,
6
,
s
);
split_and_byval_rect
(
1
,
2
,
3
,
s
,
s
);
split_rect
(
1
,
2
,
s
);
assert_eq!
(
huge_struct
(
v
),
v
);
assert_eq!
(
split_ret_byval_struct
(
1
,
2
,
s
),
s
);
assert_eq!
(
sret_byval_struct
(
1
,
2
,
3
,
4
,
s
),
t
);
assert_eq!
(
sret_split_struct
(
1
,
2
,
s
),
t
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录