Skip to content

Nonzero pointer address spaces are silently erased in generated bindings and static wrappers #3404

Description

@lwz23

Input C/C++ Header

static inline int __attribute__((address_space(1))) *
phase8_as1_identity(
    int __attribute__((address_space(1))) *value
) {
    return value;
}

Clang accepts this declaration on the target used below. The function takes
and returns an address space 1 pointer.

Bindgen Invocation

$ bindgen input.h \
    --wrap-static-fns \
    --wrap-static-fns-path wrapper \
    --rust-target 1.75 \
    --no-layout-tests \
    --no-rustfmt-bindings \
    --output bindings.rs

Actual Results

The generated Rust declaration silently uses ordinary pointers:

extern "C" {
    #[link_name = "phase8_as1_identity__extern"]
    pub fn phase8_as1_identity(
        value: *mut ::std::os::raw::c_int,
    ) -> *mut ::std::os::raw::c_int;
}

The generated C wrapper drops the address space too:

int *phase8_as1_identity__extern(int *value) {
    return phase8_as1_identity(value);
}

Clang rejects that wrapper:

error: passing 'int *' to parameter of type
'__attribute__((address_space(1))) int *' changes address space of pointer

The two declarations also lower to different LLVM function types. These are
the signatures from the tools listed below:

; clang-15, correct C wrapper
define dso_local i32 addrspace(1)* @phase8_as1_identity__extern(
    i32 addrspace(1)* %value)

; rustc 1.75, caller using the generated binding
declare noundef ptr @phase8_as1_identity__extern(ptr noundef)

Expected Results

Bindgen should not emit an ordinary pointer for a nonzero address space.

The C wrapper can preserve the source declaration:

int __attribute__((address_space(1))) *
phase8_as1_identity__extern(
    int __attribute__((address_space(1))) *value
) {
    return phase8_as1_identity(value);
}

Stable Rust does not have a general source-level pointer type for arbitrary
LLVM address spaces. If the selected Rust output cannot represent this type,
I would expect bindgen to diagnose it and omit the misleading declaration
instead of changing it to *mut c_int.

Environment

bindgen current main: 9d26c6eddeff9192ddedb563192abe3128fc5aae
bindgen release:      0.72.1
clang:                15.0.7
rustc:                1.75.0
target:               x86_64-unknown-linux-gnu

Current main and 0.72.1 both generate the same invalid wrapper at O0 and O2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions