-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for SwiftSelf<T>
in Mono JIT and Interpreter
#104171
Changes from 7 commits
0647f6a
3008c6c
240c1b3
5bcb0a5
630e6a9
a2c1d78
e375636
692aacc
5756236
04eee19
0b05920
110534a
b902f1d
30c14b0
21f7fc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3406,6 +3406,7 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c | |
uint32_t new_param_count = 0; | ||
int align; | ||
MonoClass *swift_self = mono_class_try_get_swift_self_class (); | ||
MonoClass *swift_self_t = mono_class_try_get_swift_self_t_class (); | ||
MonoClass *swift_error = mono_class_try_get_swift_error_class (); | ||
MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); | ||
/* | ||
|
@@ -3416,6 +3417,8 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c | |
for (int idx_param = 0; idx_param < csignature->param_count; ++idx_param) { | ||
MonoType *ptype = csignature->params [idx_param]; | ||
MonoClass *klass = mono_class_from_mono_type_internal (ptype); | ||
MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); | ||
|
||
// SwiftSelf, SwiftError, and SwiftIndirectResult are special cases where we need to preserve the class information for the codegen to handle them correctly. | ||
if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error || klass == swift_indirect_result)) { | ||
SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE); | ||
|
@@ -3437,7 +3440,10 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c | |
} | ||
} else { | ||
// For structs that cannot be lowered, we change the argument to byref type | ||
ptype = mono_class_get_byref_type (mono_defaults.typed_reference_class); | ||
if (gklass && (gklass->container_class == swift_self_t)) | ||
ptype = mono_class_get_byref_type (swift_self); | ||
else | ||
ptype = mono_class_get_byref_type (mono_defaults.int_class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As with other comments, don't we just care here that the type is a simple pointer type? Why are we using a byref of a class that doesn't represents the actual contents. Shouldn't we have here, both in case of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
// Load the address of the struct | ||
interp_add_ins (td, MINT_LDLOCA_S); | ||
interp_ins_set_sreg (td->last_ins, sp_old_params [idx_param].var); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7533,6 +7533,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b | |
GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), n); | ||
uint32_t new_param_count = 0; | ||
MonoClass *swift_self = mono_class_try_get_swift_self_class (); | ||
MonoClass *swift_self_t = mono_class_try_get_swift_self_t_class (); | ||
MonoClass *swift_error = mono_class_try_get_swift_error_class (); | ||
MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); | ||
/* | ||
|
@@ -7543,6 +7544,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b | |
for (int idx_param = 0; idx_param < n; ++idx_param) { | ||
MonoType *ptype = fsig->params [idx_param]; | ||
MonoClass *klass = mono_class_from_mono_type_internal (ptype); | ||
MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); | ||
|
||
// SwiftSelf, SwiftError, and SwiftIndirectResult are special cases where we need to preserve the class information for the codegen to handle them correctly. | ||
if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error || klass == swift_indirect_result)) { | ||
|
@@ -7565,12 +7567,25 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b | |
} | ||
} else { | ||
// For structs that cannot be lowered, we change the argument to byref type | ||
ptype = mono_class_get_byref_type (mono_defaults.typed_reference_class); | ||
// Load the address of the struct | ||
if (gklass && (gklass->container_class == swift_self_t)) | ||
ptype = mono_class_get_byref_type (swift_self); | ||
else | ||
ptype = mono_class_get_byref_type (mono_defaults.int_class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jkurdek
@kotlarmilos I think it's probably worth adding some comment about the placeholder type here - it's arbitrary and not really meant to exactly capture the exact type - all we care about is that it's some kind of pointer-like argument. |
||
|
||
MonoInst *struct_base_address = mono_compile_create_var (cfg, mono_get_int_type (), OP_LOCAL); | ||
CHECK_ARG (idx_param); | ||
NEW_ARGLOADA (cfg, struct_base_address, idx_param); | ||
MONO_ADD_INS (cfg->cbb, struct_base_address); | ||
|
||
// Load the address of the struct | ||
if (gklass && (gklass->container_class == swift_self_t)) | ||
{ | ||
MonoClassField *klass_fields = m_class_get_fields (klass); | ||
MonoInst *swift_self_base_address = struct_base_address; | ||
struct_base_address = mono_compile_create_var (cfg, mono_get_int_type (), OP_LOCAL); | ||
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_ADD_IMM, struct_base_address->dreg, swift_self_base_address->dreg, klass_fields->offset); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you are right. I was missing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the only difference is that Loading a field from a vt type is offset with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't the type boxed here? The struct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So If I'm correct and this code is wrong then this also raises the question on why no tests are failing. Maybe this path is not properly tested and it needs further attention ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right. The |
||
} | ||
|
||
*sp++ = struct_base_address; | ||
|
||
++new_param_count; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this lower as
SwiftSelf<T>
instead of as the inner element type? That might be problematic since the layout ofSwiftSelf<T>
may not match the layout ofT
due to potentially added padding at the end.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are right, it seems we are lowering the generic, not the inner type. Could you share more details about when padding would be added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you referring that it should first retrieve the inner type if
klass
isSwiftSelf<T>
, and then perform the lowering?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, the Swift struct
corresponds to the C# struct
But we have
Foo
- size 5SwiftSelf<Foo>
- size 8Does this actually matter for the final lowering and ABI? Not totally sure when "self" is the last argument, actually. I wouldn't be surprised if there are cases where lowering
SwiftSelf<Foo>
instead ofFoo
ends up with some different register assignments.Right.