Recently I’ve been working on an issue about supporting the
RTD instruction in m68k LLVM backend (well, it turned out to be not directly related to the instruction itself but we will talk about that shortly).
The gist of that issue goes like this: the backend bailed out when it tried to lower a certain kind of return statement to
RTD, if we’re targeting 68020 or later1.
RTD is a variant of return instruction that subtracts some bytes, whose quantity is indicated by the instruction’s operand, from stack pointer (which effectively pops the stack) before returning.
It can be used to implement a special kind of calling convention in which the callee has to clean out the space allocated for arguments passed from the stack.
Though you don’t have to use
RTD to implement the said calling convention, as long as you pop the arguments upon returning.
In m68k GCC, this calling convention is not enabled by default unless the
-mrtd flag is present.
Since this project is aiming to be compatible with its GCC counterpart (and the fact that this calling convention was not commonly used even in the good ol’ days), we want to implement the same behavior.
Cool, I guess we need to add
-mrtd to Clang. Because given “rtd” being such an odd name and sounds really 68k-specific, there is no way it’s already there…
“So, I have been digging into this now and what I found is that
-mno-rtdis actually already handled by Clang:
def mrtd: Flag<["-"], "mrtd">, Group<m_Group>;
def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
Also documented here: https://clang.llvm.org/docs/ClangCommandLineReference.html”
– Quoted (and slightly edited) from one of the comments by Adrian.
-mrtd is already there? That’s a little weird…
It seems like X86 is the only user of that flag. Specifically, only the 32-bit i386 which uses it to enable the
stdcall calling convention, a CC that also requires callee functions to pop out incoming arguments on the stack.
stdcall is primarily adopted by Win32 API.
stdcall’s similarity with our special CC mentioned earlier, it’s not quite obvious why the flag is named after something unrelated to i386.
Rest of this post is served to answer a simple question: why do i386 Clang and GCC use the name “(m)rtd?”. It’s important to note that this article is NOT meant to criticize / compare any naming choice or convention made in the past between different compiler backends and implementations, but merely a historical study.
Why is it called “(m)rtd”?
The first assumption I came out was that maybe there is an instruction called “rtd” in i386, specifically the old 80386 processor. Given how iron-fisting Intel is on maintaining backward compatibility, it’s nearly impossible that any instruction has been removed from the ISA since 80386. Therefore, looking up a relatively modern 32-bit x86 ISA manual should suffice.
Unfortunately, a simple search will tell you that i386 only has
RETI (return from interrupt).
RET does have a variant that takes an immediate-value operand, acting just like
RTD in 68k we mentioned earlier. But, well, it’s still called “ret” rather than “rtd”.
Now, maybe there are some clues in the patch that introduced this flag to Clang or even GCC – time to dig into the past.
Let’s start from the Clang/LLVM side. The
-mrtd flag was added to Clang by 65b88cd in 2011.
Unfortunately, there wasn’t any commit message or code comment attached to shed some lights on the choice of flag name.
But luckily Clang, as a compiler driver, is supposed to be compatible with GCC. So one can safely assume that this flag is originated from GCC.
Digging into GCC’s source code, at hindsight 6ac4959 added
-mrtd to i386 GCC in 2005, residing in file
But if we look closer, that patch was merely transferring flag declarations to the newer generator-based approach with *.opt files.
The original definition of
-mrtd flag in
config/i386/i386.h can actually be traced all the way back to the initial version of i386 backend!
Specifically, c98f874 authored on Feb 9th 1992.
Here was my assumption:
The name “-mrtd” in i386 GCC was reused or copied from its m68k counterpart.
So I looked into the first commit that introduced
-mrtd to m68k GCC, which was 3d339ad.
But the timestamp showed that it was authored on Feb 18th 1992, 9 days after the first file in the initial version of i386 GCC!
Is it possible that m68k GCC’s
-mrtd was actually copied from i386 GCC?
It turns out GCC not only has used several different VCS (Version Control System) in the past, it was not even managed with a VCS at the very beginning. According to GCC’s History, the first (beta) release was put…on a FTP server located in MIT.
So the Feb 9th 1992 date we just mentioned was merely the time i386 backend was checked into GCC’s VCS from a plain source tree. Same for the Feb 18th 1992 date of its m68k counterpart. In other words, it’s highly likely that the code for i386 and m68k backend was already there before any VCS adoption. The best way to answer this is to grab GCC’s pre-VCS era source code. Unfortunately, while the FTP server that originally hosted GCC is still there, I no longer can find that particular copy of source code. We can only make some educated guesses now.
There are three pieces of clues I found useful here:
-mrtdwas also used for one of the obselete (and ancient) architectures called Gmicro. A comment about
-mrtdin Gmicro backend said: “…On the m68k this is an RTD option, so I use the same name for the Gmicro. The option name may be changed in the future.”
- The initial version of
config/m68k/m68k.hshared a nearly identical line of the comments related to
-mrtdhandlings (i386 line v.s. m68k line). The only difference between them is the supported processor name (i.e. “80386” v.s. “68010”).
- From the announcement of the first GCC beta release made by RMS (circa March 1987), it’s high likely that m68k and VAX were the only two supported targets.
Item (1) suggests that reusing a flag name, despite having little to do with the respective instruction name (in Gmicro the corresponding instruction is called
RTD) was a thing, and might even be a common practice;
item (2) is likely to be a trail of boilerplate copy-n-paste on not just the comment but also the code, as well as the flag.
Finally, item (3) further affirms that if both (1) and (2) hold, it’s likely that
-mrtd was reused or copied from m68k to i386 GCC rather than the other way around.
Though there isn’t any direct evidence2 showing that
-mrtd was borrowed from m68k GCC to i386 GCC (and eventually rippled to Clang), from the artifacts I presented it’s very likely the case.
A small victory for the m68k LLVM community nonetheless!