aboutsummaryrefslogtreecommitdiff
path: root/core/c/libc/stdarg.odin
blob: 5b87585e41aa24a5da185cad0cec548f69800e1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package libc

// 7.16 Variable arguments

import "core:intrinsics"
import "core:runtime"
import "core:mem"

@(private="file")
@(default_calling_convention="none")
foreign _ {
	@(link_name="llvm.va_start") _va_start :: proc(arglist: ^i8) ---;
	@(link_name="llvm.va_end")   _va_end   :: proc(arglist: ^i8) ---;
	@(link_name="llvm.va_copy")  _va_copy  :: proc(dst, src: ^i8) ---;
}

// Since there are no types in C with an alignment larger than that of
// max_align_t, which cannot be larger than sizeof(long double) as any other
// exposed type wouldn't be valid C, the maximum alignment possible in a
// strictly conformant C implementation is 16 on the platforms we care about.
// The choice of 4096 bytes for storage of this type is more than enough on all
// relevant platforms.
va_list :: struct #align 16 {
	_: [4096]u8,
};

va_start :: #force_inline proc(ap: ^va_list, _: any) {
	_va_start(cast(^i8)ap);
}

va_end :: #force_inline proc(ap: ^va_list) {
	_va_end(cast(^i8)ap);
}

va_copy :: #force_inline proc(dst, src: ^va_list) {
	_va_copy(cast(^i8)dst, cast(^i8)src);
}

// We cannot provide va_arg as there is no way to create "C" style procedures
// in Odin which take variable arguments the C way. The #c_vararg attribute only
// exists for foreign imports. That being said, being able to copy a va_list,
// as well as start and end one is necessary in some functions, the va_list
// taking functions in libc as an example.