mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-02 08:47:57 +00:00
Fix indentations
Fix Objective-C wrapper procs not forwarding return value
This commit is contained in:
@@ -389,77 +389,77 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan
|
||||
} break;
|
||||
|
||||
case BuiltinProc_objc_ivar_get:
|
||||
{
|
||||
Type *self_type = nullptr;
|
||||
Type *ivar_type = nullptr;
|
||||
{
|
||||
Type *self_type = nullptr;
|
||||
Type *ivar_type = nullptr;
|
||||
|
||||
Operand self = {};
|
||||
check_expr_or_type(c, &self, ce->args[0]);
|
||||
Operand self = {};
|
||||
check_expr_or_type(c, &self, ce->args[0]);
|
||||
|
||||
if (!is_operand_value(self) || !check_is_assignable_to(c, &self, t_objc_id)) {
|
||||
gbString e = expr_to_string(self.expr);
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got '%s' of type %s", LIT(builtin_name), e, t);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return false;
|
||||
} else if (!is_type_pointer(self.type)) {
|
||||
gbString e = expr_to_string(self.expr);
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a pointer of a value derived from intrinsics.objc_object, got '%s' of type %s", LIT(builtin_name), e, t);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return false;
|
||||
}
|
||||
if (!is_operand_value(self) || !check_is_assignable_to(c, &self, t_objc_id)) {
|
||||
gbString e = expr_to_string(self.expr);
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got '%s' of type %s", LIT(builtin_name), e, t);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return false;
|
||||
} else if (!is_type_pointer(self.type)) {
|
||||
gbString e = expr_to_string(self.expr);
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a pointer of a value derived from intrinsics.objc_object, got '%s' of type %s", LIT(builtin_name), e, t);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
self_type = type_deref(self.type);
|
||||
self_type = type_deref(self.type);
|
||||
|
||||
if (!(self_type->kind == Type_Named &&
|
||||
self_type->Named.type_name != nullptr &&
|
||||
self_type->Named.type_name->TypeName.objc_class_name != "")) {
|
||||
gbString t = type_to_string(self_type);
|
||||
error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=<string>) , got type %s", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
if (!(self_type->kind == Type_Named &&
|
||||
self_type->Named.type_name != nullptr &&
|
||||
self_type->Named.type_name->TypeName.objc_class_name != "")) {
|
||||
gbString t = type_to_string(self_type);
|
||||
error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=<string>) , got type %s", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self_type->Named.type_name->TypeName.objc_ivar == nullptr) {
|
||||
gbString t = type_to_string(self_type);
|
||||
error(self.expr, "'%.*s' requires that type %s have the attribute @(obj_ivar=<ivar_type_name>).", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
if (self_type->Named.type_name->TypeName.objc_ivar == nullptr) {
|
||||
gbString t = type_to_string(self_type);
|
||||
error(self.expr, "'%.*s' requires that type %s have the attribute @(obj_ivar=<ivar_type_name>).", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
|
||||
Operand ivar = {};
|
||||
check_expr_or_type(c, &ivar, ce->args[1]);
|
||||
if (ivar.mode == Addressing_Type) {
|
||||
ivar_type = ivar.type;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Operand ivar = {};
|
||||
check_expr_or_type(c, &ivar, ce->args[1]);
|
||||
if (ivar.mode == Addressing_Type) {
|
||||
ivar_type = ivar.type;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self_type->Named.type_name->TypeName.objc_ivar != ivar_type) {
|
||||
gbString name_self = type_to_string(self_type);
|
||||
gbString name_expected = type_to_string(self_type->Named.type_name->TypeName.objc_ivar);
|
||||
gbString name_given = type_to_string(ivar_type);
|
||||
error(self.expr, "'%.*s' ivar type %s does not match @obj_ivar type %s on Objective-C class %s.",
|
||||
LIT(builtin_name), name_given, name_expected, name_self);
|
||||
gb_string_free(name_self);
|
||||
gb_string_free(name_expected);
|
||||
gb_string_free(name_given);
|
||||
return false;
|
||||
}
|
||||
if (self_type->Named.type_name->TypeName.objc_ivar != ivar_type) {
|
||||
gbString name_self = type_to_string(self_type);
|
||||
gbString name_expected = type_to_string(self_type->Named.type_name->TypeName.objc_ivar);
|
||||
gbString name_given = type_to_string(ivar_type);
|
||||
error(self.expr, "'%.*s' ivar type %s does not match @obj_ivar type %s on Objective-C class %s.",
|
||||
LIT(builtin_name), name_given, name_expected, name_self);
|
||||
gb_string_free(name_self);
|
||||
gb_string_free(name_expected);
|
||||
gb_string_free(name_given);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type_hint != nullptr && type_hint->kind == Type_Pointer && type_hint->Pointer.elem == ivar_type) {
|
||||
operand->type = type_hint;
|
||||
} else {
|
||||
operand->type = alloc_type_pointer(ivar_type);
|
||||
}
|
||||
if (type_hint != nullptr && type_hint->kind == Type_Pointer && type_hint->Pointer.elem == ivar_type) {
|
||||
operand->type = type_hint;
|
||||
} else {
|
||||
operand->type = alloc_type_pointer(ivar_type);
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->mode = Addressing_Value;
|
||||
|
||||
return true;
|
||||
} break;
|
||||
return true;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2206,7 +2206,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
case BuiltinProc_objc_find_class:
|
||||
case BuiltinProc_objc_register_selector:
|
||||
case BuiltinProc_objc_register_class:
|
||||
case BuiltinProc_objc_ivar_get:
|
||||
case BuiltinProc_objc_ivar_get:
|
||||
return check_builtin_objc_procedure(c, operand, call, id, type_hint);
|
||||
|
||||
case BuiltinProc___entry_point:
|
||||
|
||||
@@ -526,68 +526,68 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr,
|
||||
check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac);
|
||||
if (e->kind == Entity_TypeName && ac.objc_class != "") {
|
||||
e->TypeName.objc_class_name = ac.objc_class;
|
||||
e->TypeName.objc_superclass = ac.objc_superclass;
|
||||
e->TypeName.objc_ivar = ac.objc_ivar;
|
||||
e->TypeName.objc_superclass = ac.objc_superclass;
|
||||
e->TypeName.objc_ivar = ac.objc_ivar;
|
||||
e->TypeName.objc_context_provider = ac.objc_context_provider;
|
||||
|
||||
if (ac.objc_is_implementation) {
|
||||
e->TypeName.objc_is_implementation = true;
|
||||
mpsc_enqueue(&ctx->info->objc_class_implementations, e); // TODO(harold): Don't need this for anything? See if needed when using explicit @export
|
||||
if (ac.objc_is_implementation) {
|
||||
e->TypeName.objc_is_implementation = true;
|
||||
mpsc_enqueue(&ctx->info->objc_class_implementations, e); // TODO(harold): Don't need this for anything? See if needed when using explicit @export
|
||||
|
||||
GB_ASSERT(e->TypeName.objc_ivar == nullptr || e->TypeName.objc_ivar->kind == Type_Named);
|
||||
GB_ASSERT(e->TypeName.objc_ivar == nullptr || e->TypeName.objc_ivar->kind == Type_Named);
|
||||
|
||||
// Enqueue the proc to be checked when resolved
|
||||
if (e->TypeName.objc_context_provider != nullptr) {
|
||||
mpsc_enqueue(&ctx->checker->procs_with_objc_context_provider_to_check, e);
|
||||
}
|
||||
// Enqueue the proc to be checked when resolved
|
||||
if (e->TypeName.objc_context_provider != nullptr) {
|
||||
mpsc_enqueue(&ctx->checker->procs_with_objc_context_provider_to_check, e);
|
||||
}
|
||||
|
||||
// @TODO(harold): I think there's a Check elsewhere in the checker for checking cycles.
|
||||
// See about moving this to the right location.
|
||||
// Ensure superclass hierarchy are all Objective-C classes and does not cycle
|
||||
Type *super = ac.objc_superclass;
|
||||
if (super != nullptr) {
|
||||
TypeSet super_set{};
|
||||
type_set_init(&super_set, 8);
|
||||
defer (type_set_destroy(&super_set));
|
||||
// @TODO(harold): I think there's a Check elsewhere in the checker for checking cycles.
|
||||
// See about moving this to the right location.
|
||||
// Ensure superclass hierarchy are all Objective-C classes and does not cycle
|
||||
Type *super = ac.objc_superclass;
|
||||
if (super != nullptr) {
|
||||
TypeSet super_set{};
|
||||
type_set_init(&super_set, 8);
|
||||
defer (type_set_destroy(&super_set));
|
||||
|
||||
type_set_update(&super_set, e->type);
|
||||
type_set_update(&super_set, e->type);
|
||||
|
||||
for (;;) {
|
||||
if (type_set_update(&super_set, super)) {
|
||||
error(e->token, "@(objc_superclass) Superclass hierarchy cycle encountered");
|
||||
break;
|
||||
}
|
||||
for (;;) {
|
||||
if (type_set_update(&super_set, super)) {
|
||||
error(e->token, "@(objc_superclass) Superclass hierarchy cycle encountered");
|
||||
break;
|
||||
}
|
||||
|
||||
if (super->kind != Type_Named) {
|
||||
error(e->token, "@(objc_superclass) References type must be a named struct.");
|
||||
break;
|
||||
}
|
||||
if (super->kind != Type_Named) {
|
||||
error(e->token, "@(objc_superclass) References type must be a named struct.");
|
||||
break;
|
||||
}
|
||||
|
||||
Type* named_type = base_type(super->Named.type_name->type);
|
||||
if (!is_type_objc_object(named_type)) {
|
||||
error(e->token, "@(objc_superclass) Superclass must be an Objective-C class.");
|
||||
break;
|
||||
}
|
||||
Type* named_type = base_type(super->Named.type_name->type);
|
||||
if (!is_type_objc_object(named_type)) {
|
||||
error(e->token, "@(objc_superclass) Superclass must be an Objective-C class.");
|
||||
break;
|
||||
}
|
||||
|
||||
super = super->Named.type_name->TypeName.objc_superclass;
|
||||
if (super == nullptr) {
|
||||
break;
|
||||
}
|
||||
super = super->Named.type_name->TypeName.objc_superclass;
|
||||
if (super == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(harold): Is this the right way to do this??? The referenced entity must be already resolved
|
||||
// so that we can access its objc_superclass attribute
|
||||
check_single_global_entity(ctx->checker, super->Named.type_name, super->Named.type_name->decl_info);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (e->TypeName.objc_superclass != nullptr) {
|
||||
error(e->token, "@(objc_superclass) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
} else if (e->TypeName.objc_ivar != nullptr) {
|
||||
error(e->token, "@(objc_ivar) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
} else if (e->TypeName.objc_context_provider != nullptr) {
|
||||
error(e->token, "@(objc_context_provider) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
}
|
||||
}
|
||||
// TODO(harold): Is this the right way to do this??? The referenced entity must be already resolved
|
||||
// so that we can access its objc_superclass attribute
|
||||
check_single_global_entity(ctx->checker, super->Named.type_name, super->Named.type_name->decl_info);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (e->TypeName.objc_superclass != nullptr) {
|
||||
error(e->token, "@(objc_superclass) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
} else if (e->TypeName.objc_ivar != nullptr) {
|
||||
error(e->token, "@(objc_ivar) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
} else if (e->TypeName.objc_context_provider != nullptr) {
|
||||
error(e->token, "@(objc_context_provider) can only be applied when the @(obj_implement) attribute is also applied");
|
||||
}
|
||||
}
|
||||
|
||||
if (type_size_of(e->type) > 0) {
|
||||
error(e->token, "@(objc_class) marked type must be of zero size");
|
||||
@@ -1005,37 +1005,37 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon
|
||||
error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope");
|
||||
} else {
|
||||
|
||||
if (ac.objc_is_implementation) {
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
if (ac.objc_is_implementation) {
|
||||
GB_ASSERT(e->kind == Entity_Procedure);
|
||||
|
||||
Type *proc_type = e->type;
|
||||
Type *proc_type = e->type;
|
||||
|
||||
if (!tn->TypeName.objc_is_implementation) {
|
||||
error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied");
|
||||
} else if (proc_type->Proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) {
|
||||
error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set");
|
||||
} else if (ac.objc_is_class_method && proc_type->Proc.calling_convention != ProcCC_CDecl) {
|
||||
error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention");
|
||||
} else {
|
||||
if (!tn->TypeName.objc_is_implementation) {
|
||||
error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied");
|
||||
} else if (proc_type->Proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) {
|
||||
error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set");
|
||||
} else if (ac.objc_is_class_method && proc_type->Proc.calling_convention != ProcCC_CDecl) {
|
||||
error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention");
|
||||
} else {
|
||||
|
||||
auto method = ObjcMethodData{ ac, e };
|
||||
method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name;
|
||||
method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name;
|
||||
|
||||
CheckerInfo *info = ctx->info;
|
||||
mutex_lock(&info->objc_method_mutex);
|
||||
defer (mutex_unlock(&info->objc_method_mutex));
|
||||
CheckerInfo *info = ctx->info;
|
||||
mutex_lock(&info->objc_method_mutex);
|
||||
defer (mutex_unlock(&info->objc_method_mutex));
|
||||
|
||||
Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t);
|
||||
if (method_list) {
|
||||
array_add(method_list, method);
|
||||
} else {
|
||||
auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8);
|
||||
list[0] = method;
|
||||
Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t);
|
||||
if (method_list) {
|
||||
array_add(method_list, method);
|
||||
} else {
|
||||
auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8);
|
||||
list[0] = method;
|
||||
|
||||
map_set(&info->objc_method_implementations, t, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
map_set(&info->objc_method_implementations, t, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&global_type_name_objc_metadata_mutex);
|
||||
defer (mutex_unlock(&global_type_name_objc_metadata_mutex));
|
||||
|
||||
138
src/checker.cpp
138
src/checker.cpp
@@ -1351,12 +1351,12 @@ gb_internal void init_universal(void) {
|
||||
t_objc_object = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_object"), alloc_type_struct_complete());
|
||||
t_objc_selector = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_selector"), alloc_type_struct_complete());
|
||||
t_objc_class = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_class"), alloc_type_struct_complete());
|
||||
t_objc_ivar = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_ivar"), alloc_type_struct_complete());
|
||||
t_objc_ivar = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_ivar"), alloc_type_struct_complete());
|
||||
|
||||
t_objc_id = alloc_type_pointer(t_objc_object);
|
||||
t_objc_SEL = alloc_type_pointer(t_objc_selector);
|
||||
t_objc_Class = alloc_type_pointer(t_objc_class);
|
||||
t_objc_Ivar = alloc_type_pointer(t_objc_ivar);
|
||||
t_objc_Ivar = alloc_type_pointer(t_objc_ivar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1389,8 +1389,8 @@ gb_internal void init_checker_info(CheckerInfo *i) {
|
||||
array_init(&i->defineables, a);
|
||||
|
||||
map_init(&i->objc_msgSend_types);
|
||||
mpsc_init(&i->objc_class_implementations, a);
|
||||
map_init(&i->objc_method_implementations);
|
||||
mpsc_init(&i->objc_class_implementations, a);
|
||||
map_init(&i->objc_method_implementations);
|
||||
|
||||
string_map_init(&i->load_file_cache);
|
||||
array_init(&i->all_procedures, heap_allocator());
|
||||
@@ -3352,10 +3352,10 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
ac->test = true;
|
||||
return true;
|
||||
} else if (name == "export") {
|
||||
if (ac->objc_is_implementation) {
|
||||
error(value, "Setting @(export) explicitly is not allowed when @(objc_implement) is set. It is exported implicitly.");
|
||||
return false;
|
||||
}
|
||||
if (ac->objc_is_implementation) {
|
||||
error(value, "Setting @(export) explicitly is not allowed when @(objc_implement) is set. It is exported implicitly.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_Invalid) {
|
||||
@@ -3369,10 +3369,10 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
return true;
|
||||
} else if (name == "linkage") {
|
||||
|
||||
if (ac->objc_is_implementation) {
|
||||
error(value, "Explicit linkage not allowed when @(objc_implement) is set. It is set implicitly");
|
||||
return false;
|
||||
}
|
||||
if (ac->objc_is_implementation) {
|
||||
error(value, "Explicit linkage not allowed when @(objc_implement) is set. It is set implicitly");
|
||||
return false;
|
||||
}
|
||||
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind != ExactValue_String) {
|
||||
@@ -3681,23 +3681,23 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_implement") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_Bool) {
|
||||
ac->objc_is_implementation = ev.value_bool;
|
||||
} else if (ev.kind == ExactValue_Invalid) {
|
||||
ac->objc_is_implementation = true;
|
||||
} else {
|
||||
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
|
||||
}
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_Bool) {
|
||||
ac->objc_is_implementation = ev.value_bool;
|
||||
} else if (ev.kind == ExactValue_Invalid) {
|
||||
ac->objc_is_implementation = true;
|
||||
} else {
|
||||
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
|
||||
}
|
||||
|
||||
// This implies exported, strongly linked
|
||||
if (ac->objc_is_implementation) {
|
||||
ac->is_export = true;
|
||||
ac->linkage = str_lit("strong");
|
||||
}
|
||||
// This implies exported, strongly linked
|
||||
if (ac->objc_is_implementation) {
|
||||
ac->is_export = true;
|
||||
ac->linkage = str_lit("strong");
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (name == "objc_selector") {
|
||||
return true;
|
||||
} else if (name == "objc_selector") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_String) {
|
||||
if (string_is_valid_identifier(ev.value_string)) {
|
||||
@@ -3949,52 +3949,52 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) {
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_implement") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_Bool) {
|
||||
ac->objc_is_implementation = ev.value_bool;
|
||||
} else if (ev.kind == ExactValue_Invalid) {
|
||||
ac->objc_is_implementation = true;
|
||||
} else {
|
||||
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_superclass") {
|
||||
Type *objc_superclass = check_type(c, value);
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_Bool) {
|
||||
ac->objc_is_implementation = ev.value_bool;
|
||||
} else if (ev.kind == ExactValue_Invalid) {
|
||||
ac->objc_is_implementation = true;
|
||||
} else {
|
||||
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_superclass") {
|
||||
Type *objc_superclass = check_type(c, value);
|
||||
|
||||
if (objc_superclass != nullptr) {
|
||||
ac->objc_superclass = objc_superclass;
|
||||
} else {
|
||||
error(value, "'%.*s' expected a named type", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_ivar") {
|
||||
Type *objc_ivar = check_type(c, value);
|
||||
if (objc_superclass != nullptr) {
|
||||
ac->objc_superclass = objc_superclass;
|
||||
} else {
|
||||
error(value, "'%.*s' expected a named type", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_ivar") {
|
||||
Type *objc_ivar = check_type(c, value);
|
||||
|
||||
if (objc_ivar != nullptr) {
|
||||
ac->objc_ivar = objc_ivar;
|
||||
} else {
|
||||
error(value, "'%.*s' expected a named type", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_context_provider") {
|
||||
Operand o = {};
|
||||
check_expr(c, &o, value);
|
||||
Entity *e = entity_of_node(o.expr);
|
||||
if (objc_ivar != nullptr) {
|
||||
ac->objc_ivar = objc_ivar;
|
||||
} else {
|
||||
error(value, "'%.*s' expected a named type", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_context_provider") {
|
||||
Operand o = {};
|
||||
check_expr(c, &o, value);
|
||||
Entity *e = entity_of_node(o.expr);
|
||||
|
||||
if (e != nullptr) {
|
||||
if (ac->objc_context_provider != nullptr) {
|
||||
error(elem, "Previous usage of a 'objc_context_provider' attribute");
|
||||
}
|
||||
if (e->kind != Entity_Procedure) {
|
||||
error(elem, "'objc_context_provider' must refer to a procedure");
|
||||
} else {
|
||||
ac->objc_context_provider = e;
|
||||
}
|
||||
if (e != nullptr) {
|
||||
if (ac->objc_context_provider != nullptr) {
|
||||
error(elem, "Previous usage of a 'objc_context_provider' attribute");
|
||||
}
|
||||
if (e->kind != Entity_Procedure) {
|
||||
error(elem, "'objc_context_provider' must refer to a procedure");
|
||||
} else {
|
||||
ac->objc_context_provider = e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -148,13 +148,13 @@ struct AttributeContext {
|
||||
|
||||
String objc_class;
|
||||
String objc_name;
|
||||
String objc_selector;
|
||||
String objc_selector;
|
||||
Type * objc_type;
|
||||
Type * objc_superclass;
|
||||
Type * objc_ivar;
|
||||
Type * objc_superclass;
|
||||
Type * objc_ivar;
|
||||
Entity *objc_context_provider;
|
||||
bool objc_is_class_method : 1;
|
||||
bool objc_is_implementation : 1; // This struct or proc provides a class/method implementation, not a binding to an existing type.
|
||||
bool objc_is_implementation : 1; // This struct or proc provides a class/method implementation, not a binding to an existing type.
|
||||
|
||||
String require_target_feature; // required by the target micro-architecture
|
||||
String enable_target_feature; // will be enabled for the procedure only
|
||||
@@ -371,8 +371,8 @@ struct ObjcMsgData {
|
||||
};
|
||||
|
||||
struct ObjcMethodData {
|
||||
AttributeContext ac;
|
||||
Entity *proc_entity;
|
||||
AttributeContext ac;
|
||||
Entity *proc_entity;
|
||||
};
|
||||
|
||||
enum LoadFileTier {
|
||||
@@ -489,10 +489,10 @@ struct CheckerInfo {
|
||||
BlockingMutex objc_types_mutex;
|
||||
PtrMap<Ast *, ObjcMsgData> objc_msgSend_types;
|
||||
|
||||
MPSCQueue<Entity *> objc_class_implementations;
|
||||
MPSCQueue<Entity *> objc_class_implementations;
|
||||
|
||||
BlockingMutex objc_method_mutex;
|
||||
PtrMap<Type *, Array<ObjcMethodData>> objc_method_implementations;
|
||||
BlockingMutex objc_method_mutex;
|
||||
PtrMap<Type *, Array<ObjcMethodData>> objc_method_implementations;
|
||||
|
||||
|
||||
BlockingMutex load_file_mutex;
|
||||
|
||||
@@ -331,7 +331,7 @@ BuiltinProc__type_end,
|
||||
BuiltinProc_objc_find_class,
|
||||
BuiltinProc_objc_register_selector,
|
||||
BuiltinProc_objc_register_class,
|
||||
BuiltinProc_objc_ivar_get,
|
||||
BuiltinProc_objc_ivar_get,
|
||||
|
||||
BuiltinProc_constant_utf16_cstring,
|
||||
|
||||
@@ -674,7 +674,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("objc_find_class"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("objc_register_selector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
|
||||
{STR_LIT("objc_register_class"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
|
||||
{STR_LIT("ivar_get"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
|
||||
{STR_LIT("ivar_get"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
|
||||
|
||||
{STR_LIT("constant_utf16_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
@@ -235,9 +235,9 @@ struct Entity {
|
||||
Type * type_parameter_specialization;
|
||||
String ir_mangled_name;
|
||||
bool is_type_alias;
|
||||
bool objc_is_implementation;
|
||||
Type* objc_superclass;
|
||||
Type* objc_ivar;
|
||||
bool objc_is_implementation;
|
||||
Type* objc_superclass;
|
||||
Type* objc_ivar;
|
||||
Entity*objc_context_provider;
|
||||
String objc_class_name;
|
||||
TypeNameObjCMetadata *objc_metadata;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -196,7 +196,7 @@ struct lbModule {
|
||||
|
||||
StringMap<lbAddr> objc_classes;
|
||||
StringMap<lbAddr> objc_selectors;
|
||||
StringMap<lbAddr> objc_ivars;
|
||||
StringMap<lbAddr> objc_ivars;
|
||||
|
||||
PtrMap<u64/*type hash*/, lbAddr> map_cell_info_map; // address of runtime.Map_Info
|
||||
PtrMap<u64/*type hash*/, lbAddr> map_info_map; // address of runtime.Map_Cell_Info
|
||||
@@ -220,7 +220,7 @@ struct lbObjCGlobal {
|
||||
gbString global_name;
|
||||
String name;
|
||||
Type * type;
|
||||
Type * class_impl_type; // This is set when the class has the objc_implement attribute set to true.
|
||||
Type * class_impl_type; // This is set when the class has the objc_implement attribute set to true.
|
||||
};
|
||||
|
||||
struct lbGenerator : LinkerData {
|
||||
@@ -242,7 +242,7 @@ struct lbGenerator : LinkerData {
|
||||
MPSCQueue<lbEntityCorrection> entities_to_correct_linkage;
|
||||
MPSCQueue<lbObjCGlobal> objc_selectors;
|
||||
MPSCQueue<lbObjCGlobal> objc_classes;
|
||||
MPSCQueue<lbObjCGlobal> objc_ivars;
|
||||
MPSCQueue<lbObjCGlobal> objc_ivars;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
|
||||
|
||||
string_map_init(&m->objc_classes);
|
||||
string_map_init(&m->objc_selectors);
|
||||
string_map_init(&m->objc_ivars);
|
||||
string_map_init(&m->objc_ivars);
|
||||
|
||||
map_init(&m->map_info_map, 0);
|
||||
map_init(&m->map_cell_info_map, 0);
|
||||
@@ -174,7 +174,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
||||
mpsc_init(&gen->entities_to_correct_linkage, heap_allocator());
|
||||
mpsc_init(&gen->objc_selectors, heap_allocator());
|
||||
mpsc_init(&gen->objc_classes, heap_allocator());
|
||||
mpsc_init(&gen->objc_ivars, heap_allocator());
|
||||
mpsc_init(&gen->objc_ivars, heap_allocator());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3290,7 +3290,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
case BuiltinProc_objc_find_class: return lb_handle_objc_find_class(p, expr);
|
||||
case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr);
|
||||
case BuiltinProc_objc_register_class: return lb_handle_objc_register_class(p, expr);
|
||||
case BuiltinProc_objc_ivar_get: return lb_handle_objc_ivar_get(p, expr);
|
||||
case BuiltinProc_objc_ivar_get: return lb_handle_objc_ivar_get(p, expr);
|
||||
|
||||
|
||||
case BuiltinProc_constant_utf16_cstring:
|
||||
|
||||
@@ -2157,8 +2157,8 @@ gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String
|
||||
|
||||
gb_internal lbAddr lb_handle_objc_find_or_register_ivar(lbModule *m, Type *self_type) {
|
||||
|
||||
String name = self_type->Named.type_name->TypeName.objc_class_name;
|
||||
GB_ASSERT(name != "");
|
||||
String name = self_type->Named.type_name->TypeName.objc_class_name;
|
||||
GB_ASSERT(name != "");
|
||||
|
||||
lbAddr *found = string_map_get(&m->objc_ivars, name);
|
||||
if (found) {
|
||||
@@ -2170,7 +2170,7 @@ gb_internal lbAddr lb_handle_objc_find_or_register_ivar(lbModule *m, Type *self_
|
||||
gbString global_name = gb_string_make(permanent_allocator(), "__$objc_ivar::");
|
||||
global_name = gb_string_append_length(global_name, name.text, name.len);
|
||||
|
||||
// Create a global variable to store offset of the ivar in an instance of an object
|
||||
// Create a global variable to store offset of the ivar in an instance of an object
|
||||
LLVMTypeRef t = lb_type(m, t_u32);
|
||||
|
||||
lbValue g = {};
|
||||
@@ -2209,10 +2209,10 @@ gb_internal lbValue lb_handle_objc_ivar_for_objc_object_pointer(lbProcedure *p,
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) {
|
||||
ast_node(ce, CallExpr, expr);
|
||||
ast_node(ce, CallExpr, expr);
|
||||
|
||||
GB_ASSERT(ce->args[0]->tav.type->kind == Type_Pointer);
|
||||
lbValue self = lb_build_expr(p, ce->args[0]);
|
||||
GB_ASSERT(ce->args[0]->tav.type->kind == Type_Pointer);
|
||||
lbValue self = lb_build_expr(p, ce->args[0]);
|
||||
|
||||
return lb_handle_objc_ivar_for_objc_object_pointer(p, self);
|
||||
}
|
||||
@@ -2282,7 +2282,7 @@ gb_internal lbValue lb_handle_objc_id(lbProcedure *p, Ast *expr) {
|
||||
GB_ASSERT(e->kind == Entity_TypeName);
|
||||
String name = e->TypeName.objc_class_name;
|
||||
|
||||
Type *class_impl_type = e->TypeName.objc_is_implementation ? type : nullptr;
|
||||
Type *class_impl_type = e->TypeName.objc_is_implementation ? type : nullptr;
|
||||
|
||||
return lb_addr_load(p, lb_handle_objc_find_or_register_class(p, name, class_impl_type));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user