-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/link: use more standard calling convention on arm #5113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Labels
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
Comments
No, on the 386 and amd64 the return address is stored below the top of the stack. On 386 and amd64 a function call is performed by first doing a call S (push pc and jump to S), then a sub esp, N to allocate N bytes for locals. In this scheme, the return address is stored at a higher address than any space for locals. On the arm a function call is befored by doing a bl S then a "str lr, [sp - #-N]!" to allocate N bytes for locals and store lr at the top of stack. In this scheme, the return address is stored at a lower address than any space for locals. |
The confusion in these comments owes to the conflicting meanings of bottom and top. In operating systems it is common to talk about the bottom or top of a memory segment, with bottom corresponding to numerically lower addresses. In the definition of a stack, the top element is the one most recently pushed. This conflicts with hardware stacks that grow from top to bottom of memory. For better or worse most Go code and comments use the hardware-inspired terms, so that "top of stack" refers to the top of the stack memory (i.e., oldest thing on the stack) and "bottom of stack" refers to the bottom of the stack memory (i.e. newest thing on the stack). Carl is using the data structure-inspired terms, which have the opposite meaning. If you are aware that the meaning may be the opposite of what you expect, you can usually figure it out from context. |
I figured out what the confusion was. I was talking about the return address of a called function (which is pushed onto the top of the stack), while Carl is talking about the return address of the currently executing function (which is between local stack space and incoming args). I'll stop being confused and confusing everyone else :) |
Carl, I opened http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf but I cannot find the part that talks about where to save LR on the stack. Is it really there? I agree that what you've described is what gcc does. I just can't find it in the PDF. |
I looked at the document so I could send you a page number but I am having trouble finding the very information I intended for the reader. Sorry about that. The traditional ARM prologue uses a store-multiple instruction to save the LR and all of the callee save registers. A matching load-multiple will assign the saved LR to the PC, thereby returning to the caller. You can see an example by looking at GCC generated code or here, at the ARM documentation site http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473i/BABBJEBD.html This idiom is supported by the control flow prediction http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0438h/BABGEAEF.html Because the LR is a high numbered register the store-multiple always leaves the return address in the bottom most (highest address) slot in the frame, just like on the x86. |
Owner changed to @rsc. Status changed to Started. |
For what it is worth, there is some additional information about the ARM calling convention and its "conventions" on this Wikipedia page https://en.wikipedia.org/wiki/Calling_convention#ARM |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
The text was updated successfully, but these errors were encountered: