ARM Hard-Float and Soft-Float ABIs: Inspect Objects Before Mixing Vendor Libraries

For 32-bit Arm objects, floating-point instruction support and floating-point argument passing are separate compatibility questions. A library can use hardware floating-point instructions while still accepting parameters through the base calling convention. Before mixing vendor archives, inspect the ABI attributes and the actual public call boundary, not just the CPU name.

This procedure uses GCC 14.2’s ARM options and Arm’s 2025Q1 AAPCS32 and ABI addenda. It concerns AArch32 procedure calls, not AArch64 or Cortex-M interrupt context saving. No Arm cross-compiler or target execution was available here; every compile/link/runtime probe below is proposed.

Record three independent choices

Inventory the architecture/CPU, selected floating-point hardware and calling convention. In GCC terms, these involve options such as -march or -mcpu, -mfpu and -mfloat-abi. Defaults depend on the configured toolchain, so a shortened build command may conceal the important choice.

The GCC 14.2 ARM reference distinguishes soft, softfp and hard. Soft requests software floating-point operations; softfp permits hardware instructions while retaining soft-float calling conventions; hard uses the FPU calling convention. GCC warns against mixing incompatible hard- and soft-float ABIs.

Consequently, observing an FPU instruction does not establish hard-float argument passing. Nor does compiling the caller with the right CPU make a differently built callee compatible. Preserve the full compile commands and toolchain specifications for both sides.

Three independent panels distinguish Arm instruction capability, parameter/result convention and a separately compiled boundary probe, with explicit proposed-only status.
Original AAPCS32 qualification map. No cross-build or target result is claimed.

Inspect each selected object or archive member

Use the target-capable readelf -h and readelf -A to inspect ELF identity and Arm-specific attributes. For an archive, retain member names with the findings. A vendor’s top-level package label cannot replace the attributes of the members actually selected by the link.

The 2025Q1 ABI addenda distinguish Tag_FP_arch, which describes floating-point architectural requirements, from Tag_ABI_VFP_args, which describes parameter/result convention. Do not use one as a proxy for the other.

Tag_ABI_VFP_args value Meaning to preserve in the review
0 Base AAPCS parameter/result convention.
1 VFP parameter/result convention.
2 Toolchain-specific convention requiring further documentation.
3 Compatible with both variants because nonvariadic functions are not permitted to pass FP parameters or results.

Value 3 is not a general declaration that arbitrary floating-point signatures are interchangeable. Missing or incomplete attributes, especially in hand-written assembly or transformed vendor objects, need producer evidence and code review. Do not manufacture a tag or erase a diagnostic to make the linker accept an uncertain boundary.

Choose a probe that actually crosses the convention

An integer-only hello-world call may never exercise the difference. Use a separately compiled, nonvariadic function with floating-point arguments and a floating-point result. For example, a proposed provider can implement float combine(float a, float b) returning a + 2.0f * b.

Put the caller and provider in different translation units, prevent cross-boundary inlining in the controlled test and leave LTO disabled. Feed nonconstant runtime inputs, then verify a known result through a checked output path. Save the generated assembly for the call and return on both sides.

The AAPCS32 VFP variant describes eligible floating-point arguments and results in VFP registers, with detailed allocation rules. A variadic function uses the base convention. A printf-only test therefore cannot stand in for a direct nonvariadic float-returning vendor API.

Build a proposed compatibility matrix

Compile caller/provider pairs with the intended target options: soft/soft, softfp/softfp and hard/hard where the selected platform supports them. Include a soft/softfp comparison only when all other architecture, runtime and ABI requirements are deliberately matched; their common base calling convention is not a blanket endorsement of every library combination.

Add a hard-versus-base negative link case and preserve the expected attribute mismatch diagnostic when the toolchain rejects it. If an uncertain combination links, do not immediately execute it on a live product. Inspect attributes, declarations and call sequences first, because a missing diagnostic is not proof that registers agree.

Test floating-point return values as well as input parameters. Include the real API’s aggregates and callback signatures in a later product-specific extension. A scalar probe can establish one boundary while missing homogeneous-aggregate rules or a callback compiled by another component.

Account for the complete runtime selection

Inspect which compiler runtime and C/C++ libraries the driver selects for the requested options. Multilib directories and sysroot contents can differ even when the compiler executable name stays the same. Keep the selected library paths and relevant driver query output with the matrix.

A vendor archive that has the intended calling convention can still require unsupported instructions, a different endianness or incompatible structure layout. Treat the floating-point convention as one gate in a wider artifact review, not the sole ABI property.

For a shared-library image, verify the interpreter and deployment dependencies separately. For bare-metal firmware, verify startup and runtime support under that platform’s build contract. The same AAPCS32 inspection idea applies, but the runtime qualification is not interchangeable.

Resolve uncertainty at the producer boundary

Request a vendor build manifest containing compiler identity, ABI options, supported processor/FPU combinations and public headers. Rebuild from source with the product toolchain when possible. If only a binary is available, record which claims are established by attributes and which still depend on vendor evidence.

Do not change only the application’s -mfloat-abi flag while leaving every dependency unreviewed. A repair must cover the selected call graph. Likewise, suppressing linker attribute checks does not insert a calling-convention adapter.

Define acceptance without an invented test result

The deliverable is a member-level attribute inventory, caller/provider flag matrix and a separately compiled call/return probe. Acceptance requires compatible conventions, supported hardware instructions, a qualified runtime set and successful behavior on the intended target.

Here, the primary specifications and procedure were verified, but no Arm objects were produced. Keep that boundary visible until the proposed matrix is executed with the delivered toolchain and its artifacts are retained.

Similar Posts