fixes for RISC-V ABI Implementation #1567 (#2937)

* fixes for RISC-V ABI Implementation #1567

Fixed RISC-V floating-point ABI by correcting the target triple to
`riscv64-unknown-linux-gnu`, adding the `target-abi` module flag, and
ensuring ABI-required CPU features are enabled.

I tested this with:
```bash
build/c3c compile-only --target linux-riscv64 rv_hello.c3
readelf -h obj/linux-riscv64/rv_hello.o | grep Flags
# Output: Flags: 0x5, RVC, double-float ABI
```

```bash
# and qemu because I don't have a riscv machine :/
qemu-riscv64-static -L /usr/riscv64-linux-gnu ./rv_hello
```

---

@lerno I purposedly left these two failing tests to clearly see the
difference.

`test/test_suite/abi/riscv64-lp64-lp64f-abi-1.c3t`
`test/test_suite/abi/riscv64-lp64-abi.c3t`

* improve Linux cross-compilation, specifically for RISC-V

- Implement automatic sysroot and CRT object discovery for RISC-V.
- Fix dynamic linker paths and emulation flags for LLD.
- Link against libgcc to resolve required arithmetic symbols.

* Update tests.

* fix linker CRT detection by centralizing host arch check

use target_host_arch() in linker.c
move target_host_arch() from hostinfo.c to target.c

* missing debug info

---------

Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
Manu Linares
2026-02-19 21:53:29 -03:00
committed by GitHub
parent 7c81bb35ca
commit 4b13ad692a
8 changed files with 209 additions and 97 deletions

View File

@@ -1594,6 +1594,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
.win_debug = WIN_DEBUG_DEFAULT,
.fp_math = FP_DEFAULT,
.x86_cpu_set = X86CPU_DEFAULT,
.riscv_cpu_set = RISCV_CPU_DEFAULT,
.riscv_abi = RISCV_ABI_DEFAULT,
.memory_environment = MEMORY_ENV_NOT_SET,
.win.crt_linking = WIN_CRT_DEFAULT,

View File

@@ -355,7 +355,9 @@ static const char *get_linux_crt_arch_glob(void)
case LINUX_AARCH64:
return "/usr/lib/aarch64*linux*/crt1.o";
case LINUX_RISCV32:
return "/usr/lib/riscv32*linux*/crt1.o";
case LINUX_RISCV64:
return "/usr/lib/riscv64*linux*/crt1.o";
default:
return "/usr/lib/*/crt1.o";
}
@@ -373,7 +375,9 @@ static const char *get_linux_crt_begin_arch_glob(void)
case LINUX_AARCH64:
return "/usr/lib/gcc/aarch64*linux*/*/crtbegin.o";
case LINUX_RISCV32:
return "/usr/lib/gcc/riscv32*linux*/*/crtbegin.o";
case LINUX_RISCV64:
return "/usr/lib/gcc/riscv64*linux*/*/crtbegin.o";
default:
return "/usr/lib/gcc/*/*/crtbegin.o";
}
@@ -382,6 +386,42 @@ static const char *get_linux_crt_begin_arch_glob(void)
static const char *find_linux_crt(void)
{
if (compiler.build.linuxpaths.crt) return compiler.build.linuxpaths.crt;
const char *arch_glob_path = get_linux_crt_arch_glob();
if (compiler.platform.arch == ARCH_TYPE_RISCV64 || compiler.platform.arch == ARCH_TYPE_RISCV32)
{
const char *is_64 = compiler.platform.arch == ARCH_TYPE_RISCV64 ? "64" : "32";
char *p1 = str_printf("/usr/*riscv%s*linux*/usr/lib/crt1.o", is_64);
const char *path = find_arch_glob_path(p1, 6);
if (path)
{
INFO_LOG("Found crt at %s", path);
return path;
}
char *p2 = str_printf("/usr/lib/riscv%s*linux*/crt1.o", is_64);
path = find_arch_glob_path(p2, 6);
if (path)
{
INFO_LOG("Found crt at %s", path);
return path;
}
}
else
{
const char *path = find_arch_glob_path(arch_glob_path, 6);
if (path)
{
INFO_LOG("Found crt at %s", path);
return path;
}
}
bool is_host_arch = compiler.platform.arch == target_host_arch();
if (is_host_arch)
{
const char *arch_linux_crt1_path = "/usr/lib/crt1.o";
const char *arch_linux_64_crt1_path = "/usr/lib64/crt1.o";
if (file_exists(arch_linux_crt1_path))
@@ -396,15 +436,10 @@ static const char *find_linux_crt(void)
INFO_LOG("Found crt at %s", arch_linux_path);
return arch_linux_path;
}
const char *arch_glob_path = get_linux_crt_arch_glob();
const char *path = find_arch_glob_path(arch_glob_path, 6);
if (!path)
{
INFO_LOG("No crt in /usr/{lib,lib64}/*/");
return NULL;
}
INFO_LOG("Found crt at %s", path);
return path;
INFO_LOG("No crt found in standard paths or via globs.");
return NULL;
}
static const char *find_linux_crt_begin(void)
@@ -423,45 +458,57 @@ static const char *find_linux_crt_begin(void)
static const char *find_linux_ld(void)
{
if (compiler.platform.environment_type == ENV_TYPE_ANDROID) return "--dynamic-linker=/system/ld-android.so";
if (compiler.platform.environment_type == ENV_TYPE_ANDROID) return "/system/ld-android.so";
switch (compiler.build.linuxpaths.libc)
{
case LINUX_LIBC_MUSL:
switch (compiler.platform.arch)
{
case ARCH_TYPE_ARM: return "--dynamic-linker=/lib/ld-musl-arm.so.1";
case ARCH_TYPE_ARMB: return "--dynamic-linker=/lib/ld-musl-armeb.so.1";
case ARCH_TYPE_AARCH64: return "--dynamic-linker=/lib/ld-musl-aarch64.so.1";
case ARCH_TYPE_AARCH64_BE: return "--dynamic-linker=/lib/ld-musl-aarch64_be.so.1";
case ARCH_TYPE_MIPS: return "--dynamic-linker=/lib/ld-musl-mips.so.1";
case ARCH_TYPE_MIPSEL: return "--dynamic-linker=/lib/ld-musl-mipsel.so.1";
case ARCH_TYPE_MIPS64: return "--dynamic-linker=/lib/ld-musl-mips64.so.1";
case ARCH_TYPE_MIPS64EL: return "--dynamic-linker=/lib/ld-musl-mips64el.so.1";
case ARCH_TYPE_PPC: return "--dynamic-linker=/lib/ld-musl-powerpc.so.1";
case ARCH_TYPE_PPC64: return "--dynamic-linker=/lib/ld-musl-powerpc64.so.1";
case ARCH_TYPE_RISCV32: return "--dynamic-linker=/lib/ld-musl-riscv32.so.1";
case ARCH_TYPE_RISCV64: return "--dynamic-linker=/lib/ld-musl-riscv64.so.1";
case ARCH_TYPE_X86: return "--dynamic-linker=/lib/ld-musl-i386.so.1";
case ARCH_TYPE_X86_64: return "--dynamic-linker=/lib/ld-musl-x86_64.so.1";
default: return "--dynamic-linker=/lib/ld-musl-unknown.so.1"; // a placeholder for now
case ARCH_TYPE_ARM: return "/lib/ld-musl-arm.so.1";
case ARCH_TYPE_ARMB: return "/lib/ld-musl-armeb.so.1";
case ARCH_TYPE_AARCH64: return "/lib/ld-musl-aarch64.so.1";
case ARCH_TYPE_AARCH64_BE: return "/lib/ld-musl-aarch64_be.so.1";
case ARCH_TYPE_MIPS: return "/lib/ld-musl-mips.so.1";
case ARCH_TYPE_MIPSEL: return "/lib/ld-musl-mipsel.so.1";
case ARCH_TYPE_MIPS64: return "/lib/ld-musl-mips64.so.1";
case ARCH_TYPE_MIPS64EL: return "/lib/ld-musl-mips64el.so.1";
case ARCH_TYPE_PPC: return "/lib/ld-musl-powerpc.so.1";
case ARCH_TYPE_PPC64: return "/lib/ld-musl-powerpc64.so.1";
case ARCH_TYPE_RISCV32: return "/lib/ld-musl-riscv32.so.1";
case ARCH_TYPE_RISCV64: return "/lib/ld-musl-riscv64.so.1";
case ARCH_TYPE_X86: return "/lib/ld-musl-i386.so.1";
case ARCH_TYPE_X86_64: return "/lib/ld-musl-x86_64.so.1";
default: return "/lib/ld-musl-unknown.so.1"; // a placeholder for now
}
UNREACHABLE;
break;
case LINUX_LIBC_GNU:
switch (compiler.platform.arch)
{
case ARCH_TYPE_ARM: return "--dynamic-linker=/lib/ld-linux.so.3";
case ARCH_TYPE_AARCH64: return "--dynamic-linker=/lib/ld-linux-aarch64.so.1";
case ARCH_TYPE_MIPS: return "--dynamic-linker=/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPSEL: return "--dynamic-linker=/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPS64: return "--dynamic-linker=/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPS64EL: return "--dynamic-linker=/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_RISCV32: return "-dynamic-linker=/lib/ld-linux-riscv32-ilp32.so.1";
case ARCH_TYPE_RISCV64: return "-dynamic-linker=/lib/ld-linux-riscv64-lp64.so.1";
case ARCH_TYPE_SPARCV9: return "--dynamic-linker=/lib/ld-linux.so.2";
case ARCH_TYPE_X86: return "--dynamic-linker=/lib64/ld-linux.so.2";
case ARCH_TYPE_X86_64: return "--dynamic-linker=/lib64/ld-linux-x86-64.so.2";
default: return "--dynamic-linker=/lib/ld-linux-unknown.so.2"; // another placeholder until we have all of them
case ARCH_TYPE_ARM: return "/lib/ld-linux.so.3";
case ARCH_TYPE_AARCH64: return "/lib/ld-linux-aarch64.so.1";
case ARCH_TYPE_MIPS: return "/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPSEL: return "/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPS64: return "/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_MIPS64EL: return "/lib/ld-linux-mipsn8.so.1";
case ARCH_TYPE_RISCV32:
{
unsigned flen = compiler.platform.riscv.flen;
if (flen == 8) return "/lib/ld-linux-riscv32-ilp32d.so.1";
if (flen == 4) return "/lib/ld-linux-riscv32-ilp32f.so.1";
return "/lib/ld-linux-riscv32-ilp32.so.1";
}
case ARCH_TYPE_RISCV64:
{
unsigned flen = compiler.platform.riscv.flen;
if (flen == 8) return "/lib/ld-linux-riscv64-lp64d.so.1";
if (flen == 4) return "/lib/ld-linux-riscv64-lp64f.so.1";
return "/lib/ld-linux-riscv64-lp64.so.1";
}
case ARCH_TYPE_SPARCV9: return "/lib/ld-linux.so.2";
case ARCH_TYPE_X86: return "/lib64/ld-linux.so.2";
case ARCH_TYPE_X86_64: return "/lib64/ld-linux-x86-64.so.2";
default: return "/lib/ld-linux-unknown.so.2"; // another placeholder until we have all of them
}
FALLTHROUGH;
default:
@@ -507,6 +554,15 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type, bool
{
error_exit("Failed to find the C runtime at link time.");
}
add_plain_arg("-m");
add_plain_arg(ld_target(compiler.platform.arch));
if (link_libc())
{
add_plain_arg("--dynamic-linker");
add_plain_arg(find_linux_ld());
}
if (is_pie_pic(compiler.platform.reloc_model))
{
add_concat_file_arg(crt_dir, "crti.o");
@@ -523,14 +579,29 @@ static void linker_setup_linux(const char ***args_ref, Linker linker_type, bool
}
add_concat_file_arg(crt_dir, "crtn.o");
add_concat_quote_arg("-L", crt_dir);
add_plain_arg(find_linux_ld());
add_concat_quote_arg("-L", crt_begin_dir);
if (compiler.platform.arch == ARCH_TYPE_RISCV64 || compiler.platform.arch == ARCH_TYPE_RISCV32)
{
const char *is_64 = compiler.platform.arch == ARCH_TYPE_RISCV64 ? "64" : "32";
char *sysroot = str_printf("/usr/riscv%s-linux-gnu", is_64);
if (file_is_dir(sysroot))
{
add_plain_arg(str_printf("--sysroot=%s", sysroot));
}
char *p1 = str_printf("/usr/riscv%s-linux-gnu/lib", is_64);
if (file_is_dir(p1)) add_plain_arg(str_printf("-L%s", p1));
char *p2 = str_printf("/usr/riscv%s-linux-gnu/usr/lib", is_64);
if (file_is_dir(p2)) add_plain_arg(str_printf("-L%s", p2));
}
if (compiler.linking.link_math) linking_add_link(&compiler.linking, "m");
linking_add_link(&compiler.linking, "pthread");
linking_add_link(&compiler.linking, "gcc");
linking_add_link(&compiler.linking, "gcc_s");
linking_add_link(&compiler.linking, "c");
add_plain_arg("-L/usr/lib/");
add_plain_arg("-L/lib/");
add_plain_arg("-m");
add_plain_arg(ld_target(compiler.platform.arch));
}
static void linker_setup_android(const char ***args_ref, Linker linker_type, bool is_dylib)

View File

@@ -165,6 +165,26 @@ void gencontext_begin_module(GenContext *c)
{
unsigned frame_pointer = compiler.platform.arch == ARCH_TYPE_AARCH64 ? 1 : 2;
llvm_set_module_flag(c, LLVMModuleFlagBehaviorWarning, "frame-pointer", frame_pointer, type_uint);
if (compiler.platform.arch == ARCH_TYPE_RISCV64 || compiler.platform.arch == ARCH_TYPE_RISCV32)
{
const char *abi_str = NULL;
if (compiler.platform.arch == ARCH_TYPE_RISCV64)
{
unsigned flen = compiler.platform.riscv.flen;
if (flen == 8) abi_str = "lp64d";
else if (flen == 4) abi_str = "lp64f";
else abi_str = "lp64";
}
else
{
unsigned flen = compiler.platform.riscv.flen;
if (flen == 8) abi_str = "ilp32d";
else if (flen == 4) abi_str = "ilp32f";
else abi_str = "ilp32";
}
LLVMMetadataRef val = LLVMValueAsMetadata(LLVMMDStringInContext(c->context, abi_str, strlen(abi_str)));
LLVMAddModuleFlag(c->module, LLVMModuleFlagBehaviorError, "target-abi", 10, val);
}
}
if (compiler.build.debug_info != DEBUG_INFO_NONE)

View File

@@ -1198,9 +1198,9 @@ static char *arch_to_target_triple(ArchOsTarget target, LinuxLibc linux_libc)
case ELF_AARCH64: return "aarch64-unknown-elf";
case WINDOWS_AARCH64: return "aarch64-pc-windows-msvc";
case NETBSD_AARCH64: return "aarch64-unknown-netbsd";
case LINUX_RISCV32: return linux_libc == LINUX_LIBC_MUSL ? "riscv32-unknown-linux-musl" : "riscv32-unknown-linux";
case LINUX_RISCV32: return linux_libc == LINUX_LIBC_MUSL ? "riscv32-unknown-linux-musl" : "riscv32-unknown-linux-gnu";
case ELF_RISCV32: return "riscv32-unknown-elf";
case LINUX_RISCV64: return linux_libc == LINUX_LIBC_MUSL ? "riscv64-unknown-linux-musl" : "riscv64-unknown-linux";
case LINUX_RISCV64: return linux_libc == LINUX_LIBC_MUSL ? "riscv64-unknown-linux-musl" : "riscv64-unknown-linux-gnu";
case ELF_RISCV64: return "riscv64-unknown-elf";
case ELF_XTENSA: return "xtensa-unknown-elf";
case WASM32: return "wasm32-unknown-unknown";
@@ -1218,6 +1218,8 @@ static bool arch_is_supported(ArchType arch)
case ARCH_TYPE_WASM64:
case ARCH_TYPE_X86_64:
case ARCH_TYPE_AARCH64:
case ARCH_TYPE_RISCV32:
case ARCH_TYPE_RISCV64:
return true;
default:
return false;
@@ -2026,6 +2028,7 @@ static void target_setup_riscv_abi(BuildTarget *target)
cpu_features_add_feature_single(&features, RISCV_FEAT_32BIT);
if (cpu == RISCV_CPU_DEFAULT) cpu = RISCV_CPU_RVI;
}
INFO_LOG("RISC-V Setup: cpu=%d, current_abi=%d", (int)cpu, (int)target->feature.riscv_abi);
if (target->feature.riscv_abi == RISCV_ABI_DEFAULT)
{
switch (cpu)
@@ -2083,6 +2086,16 @@ static void target_setup_riscv_abi(BuildTarget *target)
cpu_features_add_feature_single(&features, RISCV_FEAT_C);
break;
}
if (target->feature.riscv_abi >= RISCV_ABI_FLOAT)
{
cpu_features_add_feature_single(&features, RISCV_FEAT_F);
cpu_features_add_feature_single(&features, RISCV_FEAT_ZICSR);
}
if (target->feature.riscv_abi >= RISCV_ABI_DOUBLE)
{
cpu_features_add_feature_single(&features, RISCV_FEAT_D);
}
#if LLVM_VERSION_MAJOR < 18
// Not supported prior to LLVM 18
cpu_features_remove_feature(&features, RISCV_FEAT_I);
@@ -2372,3 +2385,41 @@ void target_setup(BuildTarget *build_target)
}
static bool host_is_le(void)
{
unsigned int i = 1;
char *c = (char *)&i;
return (*c == 1);
}
ArchType target_host_arch(void)
{
#if defined(__x86_64__) || defined(_M_X64)
return ARCH_TYPE_X86_64;
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return ARCH_TYPE_X86;
#elif (defined(__arm__) && !defined(__thumb__)) || (defined(__TARGET_ARCH_ARM) && !defined(__TARGET_ARCH_THUMB)) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return host_is_le() ? ARCH_TYPE_ARM : ARCH_TYPE_ARMB;
#elif defined(__thumb__) || defined(__TARGET_ARCH_THUMB) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return host_is_le() ? ARCH_TYPE_THUMB : ARCH_TYPE_THUMBEB;
#elif defined(__aarch64__) || defined(_M_ARM64)
return host_is_le() ? ARCH_TYPE_AARCH64 : ARCH_TYPE_AARCH64_BE;
#elif defined(mips) || defined(__mips__) || defined(__mips)
return ARCH_UNSUPPORTED;
#elif defined(__sh__)
return ARCH_UNSUPPORTED;
#elif defined(__riscv) && defined(__riscv32)
return ARCH_TYPE_RISCV32;
#elif defined(__riscv) && defined(__riscv64)
return ARCH_TYPE_RISCV64;
#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__powerpc64__)
return host_is_le() ? ARCH_TYPE_PPC64LE : ARCH_TYPE_PPC64;
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
return ARCH_TYPE_PPC;
#elif defined(__sparc__) || defined(__sparc)
return ARCH_UNSUPPORTED;
#else
return ARCH_TYPE_UNKNOWN;
#endif
}

View File

@@ -187,6 +187,8 @@ typedef struct
} PlatformTarget;
ArchType target_host_arch(void);
static inline bool is_pie_pic(RelocModel reloc)
{
switch (reloc)

View File

@@ -3,43 +3,11 @@
#include "hostinfo.h"
#include <stdlib.h>
static int is_le(void)
{
unsigned int i = 1;
char *c;
c = (char *) &i;
return (*c == 1);
}
ArchType hostinfo_arch_type(void)
{
#if defined(__x86_64__) || defined(_M_X64)
return ARCH_TYPE_X86_64;
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return ARCH_TYPE_X86;
#elif (defined(__arm__) && !defined(__thumb__)) || (defined(__TARGET_ARCH_ARM) && !defined(__TARGET_ARCH_THUMB)) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return is_le() ? ARCH_TYPE_ARM : ARCH_TYPE_ARMB;
#elif defined(__thumb__) || defined(__TARGET_ARCH_THUMB) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return is_le() ? ARCH_TYPE_THUMB : ARCH_TYPE_THUMBEB;
#elif defined(__aarch64__) || defined(_M_ARM64)
return is_le() ? ARCH_TYPE_AARCH64 : ARCH_TYPE_AARCH64_BE;
#elif defined(mips) || defined(__mips__) || defined(__mips)
return ARCH_UNSUPPORTED;
#elif defined(__sh__)
return ARCH_UNSUPPORTED;
#elif defined(__riscv) && defined(__riscv32)
return ARCH_TYPE_RISCV32;
#elif defined(__riscv) && defined(__riscv64)
return ARCH_TYPE_RISCV64;
#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__powerpc64__)
return is_le() ? ARCH_TYPE_PPC64LE : ARCH_TYPE_PPC64;
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
return ARCH_TYPE_PPC;
#elif defined(__sparc__) || defined(__sparc)
return ARCH_UNSUPPORTED;
#else
return ARCH_TYPE_UNKNOWN;
#endif
return target_host_arch();
}
static const char *llvm_arch_name(ArchType ty)

View File

@@ -8,7 +8,7 @@ struct Large
typedef V32i8 = char[<32>] @simd;
fn int f_scalar_stack_1(int a, int128 b, float c, float128 d, V32i8 e, char f, char g, char h)
fn int f_scalar_stack_1(int a, int128 b, float c, float128 d, V32i8 e, char f, ichar g, char h)
{
return g + h;
}
@@ -20,15 +20,15 @@ fn Large f_scalar_stack_2(double a, int128 b, float128 c, V32i8 d, char e, ichar
/* #expect: test.ll
define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, float %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7)
define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, float %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 signext %6, i8 %7) #0 {
entry:
%zext = zext i8 %6 to i32
%zext1 = zext i8 %7 to i32
%add = add i32 %zext, %zext1
%sext = sext i8 %6 to i32
%zext = zext i8 %7 to i32
%add = add i32 %sext, %zext
ret i32 %add
}
; Function Attrs:
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 signext %6, i8 %7) #0 {
entry:
%literal = alloca %Large, align 8
%fpsi = fptosi double %1 to i64

View File

@@ -24,7 +24,7 @@ fn Large f_scalar_stack_2(double a, int128 b, float128 c, Char32V d, char e, ich
/* #expect: test.ll
define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, double %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, double %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 signext %6, i8 %7) #0 {
entry:
%sext = sext i8 %6 to i32
%zext = zext i8 %7 to i32
@@ -32,8 +32,7 @@ entry:
ret i32 %add
}
; Function Attrs:
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 {
define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 8 %0, double %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 signext %6, i8 %7) #0 {
entry:
%literal = alloca %Large, align 8
%fpsi = fptosi double %1 to i64