rust/src/rt/rust_test_helpers.c
Björn Steinbrink 5e720aac42 Add missing attributes to indirect calls for foreign functions
When calling a foreign function, some arguments and/or return value
attributes are required to conform to the foreign ABI. Currently those
attributes are only added to the declaration of foreign functions. With
direct calls, this is no problem, because LLVM can see that those
attributes apply to the call. But with an indirect call, LLVM cannot do
that and the attribute is missing.

To fix that, we have to add those attribute to the calls to foreign
functions as well.

This also allows to remove the special handling of the SRet attribute,
which is ABI-dependent and will be set via the `attr` field of the
return type's `ArgType`.
2014-06-21 19:59:58 +02:00

220 lines
3.7 KiB
C

// Copyright 2013 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.
// Helper functions used only in tests
#include <stdint.h>
#include <assert.h>
// These functions are used in the unit tests for C ABI calls.
uint32_t
rust_dbg_extern_identity_u32(uint32_t u) {
return u;
}
uint64_t
rust_dbg_extern_identity_u64(uint64_t u) {
return u;
}
double
rust_dbg_extern_identity_double(double u) {
return u;
}
char
rust_dbg_extern_identity_u8(char u) {
return u;
}
typedef void *(*dbg_callback)(void*);
void *
rust_dbg_call(dbg_callback cb, void *data) {
return cb(data);
}
void rust_dbg_do_nothing() { }
struct TwoU8s {
uint8_t one;
uint8_t two;
};
struct TwoU8s
rust_dbg_extern_return_TwoU8s() {
struct TwoU8s s;
s.one = 10;
s.two = 20;
return s;
}
struct TwoU8s
rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) {
return u;
}
struct TwoU16s {
uint16_t one;
uint16_t two;
};
struct TwoU16s
rust_dbg_extern_return_TwoU16s() {
struct TwoU16s s;
s.one = 10;
s.two = 20;
return s;
}
struct TwoU16s
rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) {
return u;
}
struct TwoU32s {
uint32_t one;
uint32_t two;
};
struct TwoU32s
rust_dbg_extern_return_TwoU32s() {
struct TwoU32s s;
s.one = 10;
s.two = 20;
return s;
}
struct TwoU32s
rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) {
return u;
}
struct TwoU64s {
uint64_t one;
uint64_t two;
};
struct TwoU64s
rust_dbg_extern_return_TwoU64s() {
struct TwoU64s s;
s.one = 10;
s.two = 20;
return s;
}
struct TwoU64s
rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) {
return u;
}
struct TwoDoubles {
double one;
double two;
};
struct TwoDoubles
rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
return u;
}
struct ManyInts {
int8_t arg1;
int16_t arg2;
int32_t arg3;
int16_t arg4;
int8_t arg5;
struct TwoU8s arg6;
};
struct Empty {
};
void
rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
assert(v1.arg1 == v2.arg1 + 1);
assert(v1.arg2 == v2.arg2 + 1);
assert(v1.arg3 == v2.arg3 + 1);
assert(v1.arg4 == v2.arg4 + 1);
assert(v1.arg5 == v2.arg5 + 1);
assert(v1.arg6.one == v2.arg6.one + 1);
assert(v1.arg6.two == v2.arg6.two + 1);
}
intptr_t
rust_get_test_int() {
return 1;
}
/* Debug helpers strictly to verify ABI conformance.
*
* FIXME (#2665): move these into a testcase when the testsuite
* understands how to have explicit C files included.
*/
struct quad {
uint64_t a;
uint64_t b;
uint64_t c;
uint64_t d;
};
struct floats {
double a;
uint8_t b;
double c;
};
struct quad
rust_dbg_abi_1(struct quad q) {
struct quad qq = { q.c + 1,
q.d - 1,
q.a + 1,
q.b - 1 };
return qq;
}
struct floats
rust_dbg_abi_2(struct floats f) {
struct floats ff = { f.c + 1.0,
0xff,
f.a - 1.0 };
return ff;
}
int
rust_dbg_static_mut;
int rust_dbg_static_mut = 3;
void
rust_dbg_static_mut_check_four() {
assert(rust_dbg_static_mut == 4);
}
struct S {
uint64_t x;
uint64_t y;
uint64_t z;
};
uint64_t get_x(struct S s) {
return s.x;
}
uint64_t get_y(struct S s) {
return s.y;
}
uint64_t get_z(struct S s) {
return s.z;
}