Implement interface dispatch to COM for ARM64 (dotnet/coreclr#20618)
authorDavid Wrighton <davidwr@microsoft.com>
Fri, 26 Oct 2018 18:30:55 +0000 (11:30 -0700)
committerGitHub <noreply@github.com>
Fri, 26 Oct 2018 18:30:55 +0000 (11:30 -0700)
* Implement interface dispatch to COM for ARM64
- Implement missing stub (GenericComPlusCallStub)

* Re-enable IDispatch test for Arm64 (Fix issue dotnet/coreclr#20580 )

Commit migrated from https://github.com/dotnet/coreclr/commit/992c02371ef4f69746ac00080a3621111bf75995

src/coreclr/src/vm/arm64/asmhelpers.asm
src/coreclr/src/vm/arm64/stubs.cpp
src/coreclr/tests/issues.targets

index e9edec1..0cbc0a8 100644 (file)
@@ -59,6 +59,9 @@
     IMPORT JIT_GetSharedNonGCStaticBase_Helper
     IMPORT JIT_GetSharedGCStaticBase_Helper
 
+#ifdef FEATURE_COMINTEROP
+    IMPORT CLRToCOMWorker
+#endif // FEATURE_COMINTEROP
     TEXTAREA
 
 ;; LPVOID __stdcall GetCurrentIP(void);
@@ -514,6 +517,89 @@ LNullThis
 #ifdef FEATURE_COMINTEROP
 
 ; ------------------------------------------------------------------
+; setStubReturnValue
+; w0 - size of floating point return value (MetaSig::GetFPReturnSize())
+; x1 - pointer to the return buffer in the stub frame
+    LEAF_ENTRY setStubReturnValue
+
+        cbz     w0, NoFloatingPointRetVal
+
+        ;; Float return case
+        cmp     x0, #4
+        bne     LNoFloatRetVal
+        ldr     s0, [x1]
+        ret
+LNoFloatRetVal
+
+        ;; Double return case
+        cmp     w0, #8
+        bne     LNoDoubleRetVal
+        ldr     d0, [x1]
+        ret
+LNoDoubleRetVal
+
+        cmp     w0, #16
+        bne     LNoFloatHFARetVal
+        ldp     s0, s1, [x1]
+        ldp     s2, s3, [x1, #8]
+        ret
+LNoFloatHFARetVal
+
+        cmp     w0, #32
+        bne     LNoDoubleHFARetVal
+        ldp     d0, d1, [x1]
+        ldp     d2, d3, [x1, #16]
+        ret
+LNoDoubleHFARetVal
+
+        EMIT_BREAKPOINT ; Unreachable
+
+NoFloatingPointRetVal
+
+        ;; Restore the return value from retbuf
+        ldr     x0, [x1]
+        ldr     x1, [x1, #8]
+        ret
+
+    LEAF_END
+
+; ------------------------------------------------------------------
+; GenericComPlusCallStub that erects a ComPlusMethodFrame and calls into the runtime
+; (CLRToCOMWorker) to dispatch rare cases of the interface call.
+;
+; On entry:
+;   x0          : 'this' object
+;   x12         : Interface MethodDesc*
+;   plus user arguments in registers and on the stack
+;
+; On exit:
+;   x0/x1/s0-s3/d0-d3 set to return value of the call as appropriate
+;
+    NESTED_ENTRY GenericComPlusCallStub
+
+        PROLOG_WITH_TRANSITION_BLOCK 0x20
+
+        add         x0, sp, #__PWTB_TransitionBlock ; pTransitionBlock
+        mov         x1, x12                         ; pMethodDesc
+
+        ; Call CLRToCOMWorker(TransitionBlock *, ComPlusCallMethodDesc *). 
+        ; This call will set up the rest of the frame (including the vfptr, the GS cookie and
+        ; linking to the thread), make the client call and return with correct registers set 
+        ; (x0/x1/s0-s3/d0-d3 as appropriate).
+
+        bl          CLRToCOMWorker
+
+        ; x0 = fpRetSize
+
+        ; return value is stored before float argument registers
+        add         x1, sp, #(__PWTB_FloatArgumentRegisters - 0x20)
+        bl          setStubReturnValue
+
+        EPILOG_WITH_TRANSITION_BLOCK_RETURN
+
+    NESTED_END
+
+; ------------------------------------------------------------------
 ; COM to CLR stub called the first time a particular method is invoked.
 ;
 ; On entry:
index 248a103..846ce36 100644 (file)
@@ -1219,14 +1219,6 @@ AdjustContextForVirtualStub(
 }
 #endif // !(DACCESS_COMPILE && CROSSGEN_COMPILE)
 
-#ifdef FEATURE_COMINTEROP
-extern "C" void GenericComPlusCallStub(void)
-{
-    // This is not required for coreclr scenarios
-    throw "GenericComPlusCallStub is not implemented yet.";    
-}
-#endif // FEATURE_COMINTEROP
-
 UMEntryThunk * UMEntryThunk::Decode(void *pCallback)
 {
     _ASSERTE(offsetof(UMEntryThunkCode, m_code) == 0);
index c80eadc..e252b89 100644 (file)
         <ExcludeList Include="$(XunitTestBinBase)/JIT/jit64/mcc/interop/mcc_i73/*">
             <Issue>Needs Triage</Issue>
         </ExcludeList>
-        <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/IDispatch/NETClientIDispatch/*">
-            <Issue>20580</Issue>
-        </ExcludeList>
     </ItemGroup>
 
     <!-- arm32 All OS specific excludes -->