<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Miscompilation when linking an LTO version of newlib for ARM"
href="https://bugs.llvm.org/show_bug.cgi?id=45524">45524</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Miscompilation when linking an LTO version of newlib for ARM
</td>
</tr>
<tr>
<th>Product</th>
<td>new-bugs
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>new bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>chaosdefinition@hotmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Hi,
I'm working on an embedded ARM project using LLVM to do cross compilation, in
which we need to do whole-program transformations on both the application and
libraries (statically linked newlib and compiler-rt). We therefore chose to
compile and link everything with LTO. However, miscompilation happens where a
printf("\n") in C is compiled into a call to @llvm.trap() and an unreachable
instruction in IR when we link against an LTO version of newlib.
After some debugging, we found out that the problem is caused by mismatched
calling convention. Specifically,
1. In the compiling stage, LibCallSimplifier replaces the original call to
printf() with ARM AAPCS calling convention by a call to putchar() with LLVM's
default calling convention.
2. In the function importing stage of LTO, the function body of putchar() with
ARM AAPCS calling convention is imported from the LTO newlib into the single
module.
3. When running InstCombine pass in LTO, due to mismatched calling convention
(default in the CallInst vs. ARM AAPCS in putchar()'s definition), the CallInst
is transformed into an unreachable instruction (An explanation can be found in
<a href="https://llvm.org/docs/FAQ.html#why-does-instcombine-simplifycfg-turn-a-call-to-a-function-with-a-mismatched-calling-convention-into-unreachable-why-not-make-the-verifier-reject-it">https://llvm.org/docs/FAQ.html#why-does-instcombine-simplifycfg-turn-a-call-to-a-function-with-a-mismatched-calling-convention-into-unreachable-why-not-make-the-verifier-reject-it</a>).
I don't know if LLVM should support compiling low-level infrastructure (such as
C library) with LTO, but my speculation is that LibCallSimplifier assumes the C
library to be in native code which makes it disregard the original call's
calling convention.
Another interesting fact is that this is not only the case with LTO, but also
with ThinLTO. Specifically, I tried the following combinations, some of which
are actually working:
application:LTO + newlib:LTO -> unreachable
application:ThinLTO + newlib:ThinLTO -> unreachable
application:LTO + newlib:ThinLTO -> working
application:ThinLTO + newlib:LTO -> working
For now I'm using one of the last two working configurations for my project,
but it would be great to see all of the above working.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>