When simple built-in types are used inside single-field structures, the structure gets erased and only a bare type stays in LLVM IR. For example, this code:
struct S(u64);
fn test() -> S { S(0) }
produces this LLVM IR:
define i64 @test() {
start:
ret i64 0
}
Simple type S(u64) was replaced with its inner u64 and the code is a lot simpler.
However similar code with field type:
struct S(__zkllvm_field_pallas_base);
fn test() -> S { S(0g) }
produces a wrapping structure instead of bare type:
%S = type { __zkllvm_field_pallas_base }
define void @test(ptr sret(%S) %0) {
start:
store __zkllvm_field_pallas_base f0x0, ptr %0, align 1
ret void
}
Despite second LLVM IR is correct, it's not optimal, especially when speaking about assigner public input. Probably field and curve types are missing some optimizations, which are made for integer types. Because all the code around manipulations with fields should be as simple as possible, we really want field structures to behave the same as integer structures.
When simple built-in types are used inside single-field structures, the structure gets erased and only a bare type stays in LLVM IR. For example, this code:
produces this LLVM IR:
Simple type
S(u64)
was replaced with its inneru64
and the code is a lot simpler.However similar code with field type:
produces a wrapping structure instead of bare type:
Despite second LLVM IR is correct, it's not optimal, especially when speaking about
assigner
public input. Probably field and curve types are missing some optimizations, which are made for integer types. Because all the code around manipulations with fields should be as simple as possible, we really want field structures to behave the same as integer structures.