返回寄存器中的结构 - GCC 中的 ARM ABI
在 ARM ABI 文档中,我遇到了如下定义的函数:
__value_in_regs struct bar foo(int a, int b) {
...
}
但 GCC(4.3.3) 不允许这样做,我能找到的只是对某些 RealView 编译器的引用。 GCC 有什么办法可以做到这一点吗?
我尝试过 -freg-struct-return 但没有什么区别。由于它是 ABI,我无法更改原始程序,并且返回常规结构会破坏堆栈。
如果可以避免的话,我宁愿不使用汇编,因为否则没有必要。
谢谢!
In the ARM ABI documentation I come across functions defined like:
__value_in_regs struct bar foo(int a, int b) {
...
}
but GCC(4.3.3) doesn't allow it and all I could find are references to some RealView compiler.
Is there any way of doing this from GCC?
I have tried -freg-struct-return but it doesn't make a difference. As it is an ABI I can't change the original programs, and returning a regular struct mangles the stack.
I would rather not using assembly for this if avoidable as it isn't otherwise necessary.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据请求作为答案发布:
如果您必须生成一个可以与您的编译器不支持的 ABI 一起使用的二进制文件,那么您就会遇到麻烦。在 C 中您无能为力。在这种情况下,您需要依靠汇编语言编程并执行必要的调用。有两种可能性:
这两个问题的解决方法类似。要从代码中调用,您需要在程序集中创建填充函数,这些函数围绕调用约定进行调整以匹配外部 ABI,然后从那里调用外部函数。与 C 代码的区别在于,现在要进行外部调用,您需要调用内部汇编例程,它会执行外部调用所需的任何操作,然后将返回值以您的 C 代码可以理解的格式放回,然后返回。
为了支持从外部二进制文件调用您的代码,您可以做同样的事情,但方向相反。二进制文件的入口点将是一些小的汇编例程,它将外部 ABI 转换为 C 代码可以理解的格式,调用内部函数,然后将返回值放回到外部代码可以理解的格式,然后返回。
恐怕有时没有好的解决方案。
Posting as an answer by request:
If you have to generate a binary that will work with an ABI your compiler doesn't support, you're in for some trouble. There's nothing you can do in C. In this case, you'll need to fall back on assembly language programming and thunk the necessary calls. There are two possibilities:
Both of these problems are solved similarly. To call out from your code, you'll need to make shim functions in assembly that swizzle around the calling convention to match the external ABI, and then call the external functions from there. The difference to your C code is that now to make external calls, you call your internal assembly routine, and it does whatever it needs to to call out externally, then puts the return value back in a format your C code will understand, and returns.
To support calls from the external binary into your code, you do the same thing, but in reverse. The entry points to your binary will be little assembly routines that swizzle the external ABI into a format your C code can understand, call your internal function, then put the return values back into a format the external code understands, and return.
Sometimes there's just no good solution, I'm afraid.
您可以使用“long long”对两个寄存器执行此操作,如本页中给出的“ARM 体系结构的过程调用标准”链接中指定的那样。
将被简单地编译为:
和
ret & 0xFFFFFFFF
和ret>>调用函数中的 32
将被 r0 和 r1 无缝替换。甚至可以通过使用“Containerized
矢量”:
编译为:
请注意,它在上面的文档中被引用为 SIMD/NEON 功能,但我只是在 Thumb 模式下的 Cortex M0 上实现了它,没有 NEON 支持。
You can do it for two registers by using "long long", as specified in "Procedure Call Standard for the ARM Architecture" link given in this page.
will be simply compiled as:
and the
ret & 0xFFFFFFFF
andret >> 32
in your calling function will be replaced seamlessly by r0 and r1.It is even possible to do it for registers r0 to r3 by using "Containerized
vectors":
which is compiled as:
Note that it is referenced as a SIMD/NEON feature in the document above, but I just achieved it on a Cortex M0 in Thumb mode, without NEON support.
“ARM 架构的过程调用标准”
具体地说(第 5.4 节:结果返回):
“在 R0 中返回不大于 4 字节的复合类型。”
“大于 4 个字节的复合类型...存储在内存中,调用函数时作为额外参数传递的地址...。”
我知道某些 CPU 有几种不同的“标准”ABI。
但我的印象是,几乎所有 ARM 编译器都使用相同的 ABI。
您是否有任何证据表明 GCC 不使用此标准 ABI?
您介意发布一个链接,指向与此标准 ABI 不同的 ARM ABI 上的任何信息(调用方或被调用方或两者使用的 ABI)吗?
The "Procedure Call Standard for the ARM Architecture"
specifically says (section 5.4: Result Return):
"A Composite Type not larger than 4 bytes is returned in R0."
"A Composite Type larger than 4 bytes ... is stored in memory at an address passed as an extra argument when the function was called ... ."
I know that some CPUs have several different "standard" ABIs.
But I was under the impression that practically all compilers for the ARM used this same ABI.
Do you have any evidence that GCC doesn't use this standard ABI?
Would you mind posting a link to any information on a ABI for the ARM that is different from this standard ABI -- the ABI used by the caller, or the called, or both?
我不确定这是否有效,但您可以尝试使用
pcs
功能属性:I'm not sure if this will work, but you can try using the
pcs
function attribute: