-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C struct mapping with a single double field corrupts data on win64 #28325
Comments
Do you have clang available? It would be helpful to compare |
Actually, I'm on the machine where I have windows installed, so I can do that test: julia> struct OneWrappedInt
x::Float64
end
julia> f(x) = ccall(x, Cvoid, (OneWrappedInt,), OneWrappedInt(1.0))
...
%2 = inttoptr i64 %0 to void (i64)*
call void %2(i64 4607182418800017408) ; f64 1.0e0
... ~$ clang --target=x86_64-w64-mingw32-pc -emit-llvm -S -o - -x c -
struct OneWrappedInt
{
double x;
};
void print_one(struct OneWrappedInt x)
{
}
; ModuleID = '-'
source_filename = "-"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-gnu"
%struct.OneWrappedInt = type { double }
; Function Attrs: noinline nounwind uwtable
define void @print_one(i64) #0 {
%2 = alloca %struct.OneWrappedInt, align 8
%3 = getelementptr inbounds %struct.OneWrappedInt, %struct.OneWrappedInt* %2, i32 0, i32 0
%4 = bitcast double* %3 to i64*
store i64 %0, i64* %4, align 8
ret void
}
attributes #0 = { noinline nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 9.0.0 (clang-900.0.39.2)"} It appears we're emitting correct code, so it's probably gcc that's broken. It's much harder to see, but we can confirm that this is a GCC bug (since we believe MSVC also give correct answers) by looking at its assembly output: $ gcc -S -o - -x c -
struct OneWrappedInt
{
double x;
};
void print_one(struct OneWrappedInt x)
{
}
.file ""
.text
.globl print_one
.def print_one; .scl 2; .type 32; .endef
.seh_proc print_one
print_one:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
.seh_endprologue
movsd %xmm0, 16(%rbp)
nop
popq %rbp
ret
.seh_endproc
.ident "GCC: (GNU) 6.4.0" For comparison, with clang, that result is:
Observe that |
OK, thanks, I just remembered how handy Compiler Explorer is for this kind of thing, and it shows that MSVC indeed also uses |
For reference, here is my report: |
Sounds like this is not a Julia issue. Probably worth opening an issue at BinaryProvider.jl? |
Using the following C code:
and the following Julia code:
This yields the wrong result for the
OneWrappedInt
case (0 instead of 1) on Win64:https://ci.appveyor.com/project/barche/julia-c-struct-test#L16
I previously encountered this using mingw on Windows, but now it happens using the BinaryBuilder cross-compilation system, and CxxWrap is affected.
All other platforms, including Win64 using MSVC, seem to work.
The text was updated successfully, but these errors were encountered: