aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-04-16 10:38:42 +0100
committerGinger Bill <bill@gingerbill.org>2017-04-16 10:38:42 +0100
commitabb9930725c10d8bf8cb5560bca9afe6aad204e1 (patch)
tree812ffced8e15d7e6615d4425b9670d6d4a3ece0c /src/check_expr.c
parent169310a9f61f3d9a9d420fd3a73fe3115d995595 (diff)
IR emit C ABI compatible types for calling conventions (Only for x86/amd64 like processors at the moment)
Diffstat (limited to 'src/check_expr.c')
-rw-r--r--src/check_expr.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 1dba6dbbd..9d4eb0905 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -1014,6 +1014,50 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
return tuple;
}
+Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
+ Type *new_type = original_type;
+ // NOTE(bill): Changing the passing parameter value type is to match C's ABI
+ // IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment
+ Type *bt = core_type(original_type);
+ switch (bt->kind) {
+ // Okay to pass by value
+ // Especially the only Odin types
+ case Type_Basic: break;
+ case Type_Pointer: break;
+ case Type_Proc: break; // NOTE(bill): Just a pointer
+
+ // Odin only types
+ case Type_Slice:
+ case Type_DynamicArray:
+ case Type_Map:
+ break;
+
+ // Odin specific
+ case Type_Array:
+ case Type_Vector:
+ // Could be in C too
+ case Type_Record: {
+ i64 size = type_size_of(a, original_type);
+ switch (8*size) {
+ case 8: new_type = t_u8; break;
+ case 16: new_type = t_u16; break;
+ case 32: new_type = t_u32; break;
+ case 64: new_type = t_u64; break;
+ default:
+ // NOTE(bill): It could be an empty struct that is passed
+ // and if that is the case, no need to pass by pointer
+ // (I think..)
+ if (size > 0) {
+ new_type = make_type_pointer(a, original_type);
+ }
+ break;
+ }
+ } break;
+ }
+
+ return new_type;
+}
+
void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
ast_node(pt, ProcType, proc_type_node);
@@ -1034,6 +1078,20 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
type->Proc.result_count = result_count;
type->Proc.variadic = variadic;
type->Proc.calling_convention = pt->calling_convention;
+
+
+ type->Proc.abi_compat_params = gb_alloc_array(c->allocator, Type *, param_count);
+ for (isize i = 0; i < param_count; i++) {
+ Type *original_type = type->Proc.params->Tuple.variables[i]->type;
+ Type *new_type = type_to_abi_compat_param_type(c->allocator, original_type);
+ type->Proc.abi_compat_params[i] = new_type;
+ }
+
+ // NOTE(bill): The types are the same
+ type->Proc.abi_compat_results = gb_alloc_array(c->allocator, Type *, result_count);
+ for (isize i = 0; i < result_count; i++) {
+ type->Proc.abi_compat_results[i] = type->Proc.results->Tuple.variables[i]->type;
+ }
}