aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-05-28 01:07:52 +0100
committerGinger Bill <bill@gingerbill.org>2017-05-28 01:07:52 +0100
commit06185e176988085ed7e77793f128b9e431eedd5e (patch)
tree6cb0c5d8ddfa0db8beed18b83b6e4edaf980d169 /src/check_expr.c
parentf8fa7fe3801114da153a28064c68177e13ecece0 (diff)
Try a different ABI type for return values on Windows
Diffstat (limited to 'src/check_expr.c')
-rw-r--r--src/check_expr.c68
1 files changed, 64 insertions, 4 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 0854fd17d..0ee819913 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -1154,6 +1154,69 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
return new_type;
}
+Type *reduce_tuple_to_single_type(Type *original_type) {
+ if (original_type != NULL) {
+ Type *t = core_type(original_type);
+ if (t->kind == Type_Tuple && t->Tuple.variable_count == 1) {
+ return t->Tuple.variables[0]->type;
+ }
+ }
+ return original_type;
+}
+
+Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
+ Type *new_type = original_type;
+ if (new_type == NULL) {
+ return NULL;
+ }
+ GB_ASSERT(is_type_tuple(original_type));
+
+
+
+ if (str_eq(build_context.ODIN_OS, str_lit("windows"))) {
+ Type *bt = core_type(reduce_tuple_to_single_type(original_type));
+ // NOTE(bill): This is just reversed engineered from LLVM IR output
+ switch (bt->kind) {
+ // Okay to pass by value
+ // Especially the only Odin types
+ case Type_Pointer: break;
+ case Type_Proc: break; // NOTE(bill): Just a pointer
+ case Type_Basic: break;
+
+
+ default: {
+ i64 align = type_align_of(a, original_type);
+ i64 size = type_size_of(a, original_type);
+ switch (8*size) {
+#if 1
+ 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;
+#endif
+ }
+ } break;
+ }
+ } else if (str_eq(build_context.ODIN_OS, str_lit("linux"))) {
+
+ } else {
+ // IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
+ // their architectures
+ }
+
+ if (new_type != original_type) {
+ Type *tuple = make_type_tuple(a);
+ tuple->Tuple.variable_count = 1;
+ tuple->Tuple.variables = gb_alloc_array(a, Entity *, 1);
+ tuple->Tuple.variables[0] = make_entity_param(a, original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false);
+ new_type = tuple;
+ }
+
+
+ // return reduce_tuple_to_single_type(new_type);
+ return new_type;
+}
+
void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
ast_node(pt, ProcType, proc_type_node);
@@ -1184,10 +1247,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
}
// 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;
- }
+ type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
}