{"action":"created","issue":{"url":"https://api.github.com/repos/kripken/emscripten/issues/6259","repository_url":"https://api.github.com/repos/kripken/emscripten","labels_url":"https://api.github.com/repos/kripken/emscripten/issues/6259/labels{/name}","comments_url":"https://api.github.com/repos/kripken/emscripten/issues/6259/comments","events_url":"https://api.github.com/repos/kripken/emscripten/issues/6259/events","html_url":"https://github.com/kripken/emscripten/issues/6259","id":298474036,"number":6259,"title":"Mismatched calling convention linking to function returning struct","user":{"login":"morganbr","id":11641665,"avatar_url":"https://avatars1.githubusercontent.com/u/11641665?v=4","gravatar_id":"","url":"https://api.github.com/users/morganbr","html_url":"https://github.com/morganbr","followers_url":"https://api.github.com/users/morganbr/followers","following_url":"https://api.github.com/users/morganbr/following{/other_user}","gists_url":"https://api.github.com/users/morganbr/gists{/gist_id}","starred_url":"https://api.github.com/users/morganbr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/morganbr/subscriptions","organizations_url":"https://api.github.com/users/morganbr/orgs","repos_url":"https://api.github.com/users/morganbr/repos","events_url":"https://api.github.com/users/morganbr/events{/privacy}","received_events_url":"https://api.github.com/users/morganbr/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-02-20T05:14:34Z","updated_at":"2018-02-20T19:44:21Z","closed_at":null,"author_association":"NONE","body":"In linking a C++ module to a module of [generated ](https://github.com/dotnet/corert)bitcode, I'm seeing a couple of the C++ functions that return pointer-sized structs get different generated calling conventions than their callers. The callers seem to be trying to add the stack pointer as a hidden first argument, expecting the callee to write the return value to it, but the callee is just returning the struct instead. This misaligns the arguments and drops the last one.\r\n\r\nChanging the caller to expect an i32 return type instead of a struct works, but isn't ideal since it means modifying the source code (since I'm building a compiler, I don't always control that). I'm seeing similar results with both Asm.JS and Webassembly. My SDK info is below (I can't update due to #6251):\r\nemcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.37.30\r\nclang version 4.0.0  (emscripten 1.37.30 : 1.37.30)\r\n\r\nFor example:\r\n\r\nCallee in C++:\r\n```\r\nstruct TypeManagerHandle { void* _value; };\r\nextern \"C\" TypeManagerHandle RhGetModuleFromEEType (EEType * pEEType)\r\n{\r\n    return *pEEType->GetTypeManagerPtr(); // Dereferences and returns a TypeManagerHandle\r\n}\r\n```\r\n\r\nCallee in LLVM bitcode:\r\n```\r\n; Function Attrs: noinline sspstrong\r\ndefine hidden i8* @RhGetModuleFromEEType(%class.EEType*) #0 !dbg !24172 {\r\n  // snip\r\n  %9 = load i8*, i8** %8, align 4, !dbg !24180\r\n  ret i8* %9, !dbg !24180\r\n}\r\n```\r\n\r\nCaller in LLVM bitcode:\r\n```\r\n// I've tried treating the return value as a 4-i8 array, a struct with an i32 member\r\n// and a struct with 4 i8 members and got same result in all cases\r\ndeclare [4 x i8] @RhGetModuleFromEEType(i8*)\r\n\r\n%call = call [4 x i8] @RhGetModuleFromEEType(i8* %ldtemp)\r\n```\r\n\r\nCaller in wast:\r\n```\r\n// Prolog puts the stack pointer in $$call\r\n  (set_local $$call\r\n   (get_local $sp)\r\n  )\r\n\r\n//snip\r\n\r\n// Set up the argument we meant to pass\r\n(set_local $$ldtemp\r\n   (i32.load\r\n    (get_local $$8)\r\n   )\r\n  )\r\n// Pass the stack pointer instead and drop the return value\r\n  (drop\r\n   (call $_RhGetModuleFromEEType\r\n    (get_local $$call)\r\n   )\r\n  )\r\n// Try to load the return value from the stack\r\n(set_local $$call$sreg$field\r\n   (i32.load8_s\r\n    (get_local $$call)\r\n   )\r\n  )\r\n```\r\n\r\nCallee in wast:\r\n```\r\n // Still just takes one i32 and returns an i32\r\n (func $_RhGetModuleFromEEType (; 15487 ;) (param $$0 i32) (result i32)\r\n// snip\r\n  (return\r\n   (get_local $$5)\r\n  )\r\n)\r\n```\r\n\r\nThis also triggers misleading linker warnings like:\r\n```\r\nwarning : unexpected number of arguments 2 in call to 'RhGetModuleFromEEType', should be 1 \r\nwarning : unexpected return type void in call to 'RhGetModuleFromEEType', should be i8*\r\n```"},"comment":{"url":"https://api.github.com/repos/kripken/emscripten/issues/comments/367096019","html_url":"https://github.com/kripken/emscripten/issues/6259#issuecomment-367096019","issue_url":"https://api.github.com/repos/kripken/emscripten/issues/6259","id":367096019,"user":{"login":"kripken","id":173661,"avatar_url":"https://avatars0.githubusercontent.com/u/173661?v=4","gravatar_id":"","url":"https://api.github.com/users/kripken","html_url":"https://github.com/kripken","followers_url":"https://api.github.com/users/kripken/followers","following_url":"https://api.github.com/users/kripken/following{/other_user}","gists_url":"https://api.github.com/users/kripken/gists{/gist_id}","starred_url":"https://api.github.com/users/kripken/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kripken/subscriptions","organizations_url":"https://api.github.com/users/kripken/orgs","repos_url":"https://api.github.com/users/kripken/repos","events_url":"https://api.github.com/users/kripken/events{/privacy}","received_events_url":"https://api.github.com/users/kripken/received_events","type":"User","site_admin":false},"created_at":"2018-02-20T19:44:21Z","updated_at":"2018-02-20T19:44:21Z","author_association":"OWNER","body":"Interesting, if it's different in the LLVM wasm backend then it's likely ABI differences there. In that case the same should happen when @sunfishcode updates the asm.js ABI to match the LLVM wasm one, which is planned.\r\n"}}
{"actor":{"display_login":"kripken"}}