so... you like never free, never fclose, never munmap, never pthread_join, never unlock mutexes, never close network connections or what ?
Also, all of your protoypes such as
sg_pipeline sg_alloc_pipeline() {
should really be sg_pipeline sg_alloc_pipeline(void) {
since the first one can actually be called with any number of arguments (in C, not in C++).Note also that C doesn't have return-value-optimization, hence all your struct-returning functions can possibly cause a call to memcpy (won't happen when compiled in C++ mode of course) and will generally lead to much more binary bloat than the traditional C way of passing outputs as arguments. e.g. given this trivial code in foo.c:
typedef struct _foo
{
int x;
float foo, bar;
char z[1024]; // change this to 10024 to get a memcpy!
} foo;
void do_stuff_to_foo(foo*);
foo blah()
{
foo f;
do_stuff_to_foo(&f);
return f;
}
A disassembly after compilation with gcc -std=c99 -O3 gives blah:
.LFB0:
pushq %rbp
movq %rdi, %rbp
pushq %rbx
subq $1064, %rsp
movq %fs:40, %rax
movq %rax, 1048(%rsp)
xorl %eax, %eax
movq %rsp, %rbx
movq %rbx, %rdi
call do_stuff_to_foo@PLT
movq (%rsp), %rax
leaq 8(%rbp), %rdi
movq %rbp, %rcx
andq $-8, %rdi
movq %rbx, %rsi
subq %rdi, %rcx
movq %rax, 0(%rbp)
movq 1028(%rbx), %rax
subq %rcx, %rsi
addl $1036, %ecx
movq %rax, 1028(%rbp)
shrl $3, %ecx
rep movsq
movq 1048(%rsp), %rdx
xorq %fs:40, %rdx
jne .L5
addq $1064, %rsp
movq %rbp, %rax
popq %rbx
popq %rbp
ret
The same thing built with g++ -O3 gives _Z4blahv:
pushq %rbx
movq %rdi, %rbx
call _Z15do_stuff_to_fooP4_foo@PLT
movq %rbx, %rax
popq %rbx
ret
While clang (in C mode) goes for a memcpy: blah: # @blah
pushq %r14
pushq %rbx
subq $1048, %rsp # imm = 0x418
movq %rdi, %rbx
movq %fs:40, %rax
movq %rax, 1040(%rsp)
movq %rsp, %r14
movq %r14, %rdi
callq do_stuff_to_foo@PLT
movl $1036, %edx # imm = 0x40C
movq %rbx, %rdi
movq %r14, %rsi
callq memcpy@PLT
movq %fs:40, %rax
cmpq 1040(%rsp), %rax
jne .LBB0_2
movq %rbx, %rax
addq $1048, %rsp # imm = 0x418
popq %rbx
popq %r14
retq