Skip to content

StructValue::get_fields misbehaves for zeroinitializer, it should be using the type's info, not the operand count #708

Description

@programmerjake

Describe the Bug
StructValue doesn't correctly handle zeroinitializer, and wrongly returns no fields when using the field accessor functions (get_fields and friends), however if you use LLVMGetAggregateElement and the field count from the type, it works correctly.

To Reproduce
src/main.rs:

use inkwell::{
    context::Context,
    llvm_sys::core::LLVMGetAggregateElement,
    values::{AsValueRef, BasicValueEnum},
};

fn main() {
    let context = Context::create();
    let i8_ty = context.i8_type();
    let i16_ty = context.i16_type();
    let i8_i16_ty = context.struct_type(&[i8_ty.into(), i16_ty.into()], false);
    let ty = context.struct_type(&[i8_i16_ty.into(), i8_ty.into(), i16_ty.into()], false);
    let v = dbg!(ty.const_zero());
    dbg!(v.get_fields().collect::<Vec<_>>());
    unsafe {
        for i in 0..ty.count_fields() {
            let field = BasicValueEnum::new(LLVMGetAggregateElement(v.as_value_ref(), i));
            dbg!(field);
        }
    }
}

Cargo.toml:

[package]
name = "inkwell_bug"
version = "0.1.0"
edition = "2024"

[dependencies]
inkwell = { version = "0.10.0", features = ["no-libffi-linking", "llvm22-1", "target-powerpc", "llvm22-1-prefer-dynamic"], default-features = false }

Output I get:

[src/main.rs:13:13] ty.const_zero() = StructValue {
    struct_value: Value {
        name: "",
        address: 0x0000565064d09e80,
        is_const: true,
        is_null: true,
        is_undef: false,
        llvm_value: "{ { i8, i16 }, i8, i16 } zeroinitializer",
        llvm_type: "{ { i8, i16 }, i8, i16 }",
    },
}
[src/main.rs:14:5] v.get_fields().collect::<Vec<_>>() = []
[src/main.rs:18:13] field = StructValue(
    StructValue {
        struct_value: Value {
            name: "",
            address: 0x0000565064d0b1b0,
            is_const: true,
            is_null: true,
            is_undef: false,
            llvm_value: "{ i8, i16 } zeroinitializer",
            llvm_type: "{ i8, i16 }",
        },
    },
)
[src/main.rs:18:13] field = IntValue(
    IntValue {
        int_value: Value {
            name: "",
            address: 0x0000565064d0b1d0,
            is_const: true,
            is_null: true,
            is_undef: false,
            llvm_value: "i8 0",
            llvm_type: "i8",
        },
    },
)
[src/main.rs:18:13] field = IntValue(
    IntValue {
        int_value: Value {
            name: "",
            address: 0x0000565064d0b0c0,
            is_const: true,
            is_null: true,
            is_undef: false,
            llvm_value: "i16 0",
            llvm_type: "i16",
        },
    },
)

Expected Behavior
In the collect line, output three fields with value { i8, i16 } zeroinitializer, i8 0, and i16 0.

LLVM Version (please complete the following information):

  • LLVM Version: 22.1.8 (from apt.llvm.org)
  • Inkwell Branch Used: llvm22-1

Desktop (please complete the following information):

  • OS: Debian 13

Additional Context
AFAICT rather than assuming a constant struct has operands, you should be using the type's field count and LLVMGetAggregateElement

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions