Skip to content
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

Clang AArch64TargetInfo does not initialize ABI correctly on Mac M1 #57529

Open
elliottslaughter opened this issue Sep 2, 2022 · 1 comment
Labels
ABI Application Binary Interface backend:AArch64 platform:macos

Comments

@elliottslaughter
Copy link

Clang is structured in a way that makes it hard to correctly initialize the target ABI for macOS M1 targets. Clang itself addresses the issue in Driver::BuildCompilation, where it sets a -target-abi flag if necessary to correctly initialize the ABI. However, clients of Clang that use the CompilerInvocation::CreateFromArgs entry point (or other, lower-level entry points) have no good way to get access to this setting, without either parsing the output of Driver::BuildCompilation or hard-coding it themselves. Such clients include LLDB and Terra (https://terralang.org/).

See terralang/terra#605 for an example of how this has caused miscompilations in Terra.

Root Cause Analysis

Clang's AArch64TargetInfo initializes an ABI of aapcs by default:

: TargetInfo(Triple), ABI("aapcs") {

You can scan the rest of the file for darwinpcs. You won't find it. Despite having (apparent) customizations for Darwin, this file does not know how to properly initialize the ABI for Darwin AArch64 targets.

To avoid miscompilations (especially with varargs), a value of darwinpcs is required. Clang sets this value in RenderAArch64ABI, which is called transitively by Driver::BuildCompilation.

void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
else if (Triple.isOSDarwin())
ABIName = "darwinpcs";
else
ABIName = "aapcs";
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}

As you can see in the code above, this value is not stored anywhere in the ToolChain. It is only stored in CmdArgs, which makes its way (eventually) into the arguments for a job constructed by Driver::BuildCompilation. Therefore, clients that use the CompilerInvocation::CreateFromArgs entry point do not take advantage of any of this logic, and have to find a way to pass the -target-abi flag themselves.

Impact

Clang itself works fine because it initializes the -target-abi flag via Driver::BuildCompilation.

However, clients of Clang that use CompilerInvocation::CreateFromArgs (or other, lower-level entry points) have no reasonable way to access this flag. The best that can be done at the moment is to run Driver::BuildCompilation, find the -cc1 job, and look through the flags for -target-abi. There is not even a helper method on Compilation or ToolChain to help fish out this information based on what Driver::BuildCompilation returns.

Reproduction

Because it requires a client of Clang other than Clang itself, the only way to reproduce is to build a Clang client. Terra as of commit f46c5cabd13632417d382e27d35b91f8eac923a4 is sufficient for this purpose, and works with LLVM 14. A minimal reproducer can be found at terralang/terra#605, along with stack traces and code analysis.

It is likely (though I have not tested this) that writing varargs code in LLDB on macOS M1 would trigger the same issue.

@llvmbot
Copy link
Member

llvmbot commented Sep 2, 2022

@llvm/issue-subscribers-backend-aarch64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ABI Application Binary Interface backend:AArch64 platform:macos
Projects
None yet
Development

No branches or pull requests

3 participants