[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[mono] Add SwiftError support for Swift reverse pinvokes - #101122

Merged
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes
May 6, 2024
Merged

[mono] Add SwiftError support for Swift reverse pinvokes#101122
jkurdek merged 7 commits into
dotnet:mainfrom
jkurdek:swift-reverse-pinvokes

Conversation

@jkurdek

@jkurdekjkurdek commented Apr 16, 2024

Copy link
Copy Markdown
Contributor

Adds support for SwiftError in Swift reverse pinvokes. With this changes basic pinvokes using primitive types and SwiftSelf/SwiftError arguments should work. Contributes to #100010

Works on arm64/amd64.

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks great! Do you plan to include the amd64 support in this PR?

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);
} else if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_R21, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_ldrx (code, ARMREG_R21, ARMREG_R21, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here for clarity.

Comment threadsrc/mono/mono/mini/mini-arm64.c Outdated
}
if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
code = emit_ldrx (code, ARMREG_IP0, cfg->arch.swift_error_var->inst_basereg, GTMREG_TO_INT (cfg->arch.swift_error_var->inst_offset));
code = emit_strx (code, ARMREG_R21, ARMREG_IP0, 0);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this align with the CoreCLR implementation? It seems intuitive to load swifterror reg into the SwiftError argument, but I wonder if such cases are expected.

@amanasifkhalidamanasifkhalidApr 16, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the CoreCLR implementation, RyuJIT does not load the error register's current value into the SwiftError arg upon method entry. The JIT implementation represents the error value by creating a SwiftError "pseudo-local", and converts all usages of the SwiftError* out parameter into usages of the local's address (see #100692). This approach allows us to be quite liberal in optimizing uses of the SwiftError* parameter (for example, we can promote the SwiftError::Value member to its own local, and enregister it), but with our implementation, I believe the initial error value upon method entry is undefined.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos do we want to remove loading swifterror reg into the SwiftError to align?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's beneficial to align with the CoreCLR implementation. However, since it is undefined and if there are no performance implications, we can leave it as is.

@amanasifkhalidamanasifkhalid left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM so far -- thanks!

cfg->arch.swift_error_var = ins;
cfg->used_int_regs |= 1 << ARMREG_R21;
if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
cfg->used_int_regs |= 1 << ARMREG_R21;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be helpful to explain here that in the NATIVE_TO_MANAGED case, the error register is functioning as an extra return register, and thus isn't treated as callee-save.

@jkurdekjkurdek changed the title [Mono] Add basic support for Swift reverse pinvokes[mono] Add SwiftError support for Swift reverse pinvokesApr 17, 2024
@matouskozak

matouskozak commented Apr 18, 2024

Copy link
Copy Markdown
Member

Good job! Note for the CI test coverage, we have a good coverage for osx-x64 (mini and interpreter) on the runtime pipeline. For arm64, we only have interpreter coverage running on runtime-extra-platforms pipeline.

@kotlarmilos

Copy link
Copy Markdown
Member

/azp run runtime-extra-platforms

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@kotlarmiloskotlarmilos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

ins->inst_offset = ainfo->offset + ARGS_OFFSET;
offset = ALIGN_TO (offset, sizeof (target_mgreg_t));
ins->inst_basereg = cfg->frame_reg;
ins->inst_offset = offset;

@kotlarmiloskotlarmilosApr 25, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it doesn't include the ARGS_OFFSET offset between fp and the first argument in the callee?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ainfo->offset was always 0 here. So it was always allocated at ARGS_OFFSET from the beginning. I think that offset already includes information about the distance.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Swift types are specified either at the beginning or the end of signature. We don't enforce strict signature rules, but it would be beneficial to make them more general if possible. Can it still function if SwiftError is specified as the last argument, using ainfo->offset instead of offset?

@amanasifkhalid, what are the limitations from the CoreCLR side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't enforce any signature rules, either. The Swift special register types can appear anywhere in the signature's parameter list.

@jkurdekjkurdekApr 25, 2024

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kotlarmilos i think for that to work with ainfo->offset without any modifications, the error would have to be the first argument. We could probably update ainfo->offset in get_call_info so that it works for every position. I'm not sure what are the benefits of using ainfo->offset though, as the current solution works for every position.

@kotlarmiloskotlarmilosApr 26, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds good. I forgot that the ainfo->offset is always 0 for swifterror in the get_call_info.

@jkurdek

Copy link
Copy Markdown
ContributorAuthor

@lambdageek could you take a look?

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. although by this point you and Milos know way more about how the calling convention code works.

@jkurdek
jkurdek merged commit 5e949e1 into dotnet:mainMay 6, 2024
michaelgsharp pushed a commit to michaelgsharp/runtime that referenced this pull request May 9, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this pull request May 30, 2024
* initialized swift reverse pinvokes for mini jit arm64
* added comments
* fixed reverse pinvokes error passing on arm64
* implemented swift reverse pinvoke error passing on amd64
* disable SwiftErrorHandling tests on mono interpreter for now
* add comments
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 6, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkurdek@matouskozak@kotlarmilos@lambdageek@amanasifkhalid