mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
345 lines
11 KiB
C
345 lines
11 KiB
C
// #target: macos-x64
|
|
|
|
macro testbitcast(expr, $Type)
|
|
{
|
|
$assert($sizeof(expr) == $Type.sizeof, "Cannot bitcast between types of different size.");
|
|
$Type x = void;
|
|
var $size = (usize)($sizeof(expr));
|
|
|
|
$if ($alignof(expr) >= 8 && $alignof($Type) >= 8):
|
|
ulong *b = (ulong*)(&expr);
|
|
ulong *to = (ulong*)(&x);
|
|
for (usize i = 0; i < $size; i += 8)
|
|
{
|
|
to[i] = b[i];
|
|
}
|
|
$elif ($alignof(expr) >= 4 && $alignof($Type) >= 4):
|
|
uint* b = (uint*)(&expr);
|
|
uint* to = (uint*)(&x);
|
|
for (usize i = 0; i < $size; i += 4)
|
|
{
|
|
to[i] = b[i];
|
|
}
|
|
$elif ($alignof(expr) >= 2 && $alignof($Type) >= 2):
|
|
ushort* b = (ushort*)(&expr);
|
|
ushort* to = (ushort*)(&x);
|
|
for (usize i = 0; i < $size; i += 2)
|
|
{
|
|
to[i] = b[i];
|
|
}
|
|
$else:
|
|
char* b = (char*)(&expr);
|
|
char* to = (char*)(&x);
|
|
for (usize i = 0; i < $size; i++)
|
|
{
|
|
to[i] = b[i];
|
|
}
|
|
$endif;
|
|
return x;
|
|
}
|
|
|
|
extern fn void printf(char*, ...);
|
|
|
|
struct Foo
|
|
{
|
|
short a;
|
|
char b;
|
|
char c;
|
|
short d;
|
|
short e;
|
|
}
|
|
|
|
fn ulong testFoo(short x)
|
|
{
|
|
Foo z;
|
|
z.a = x;
|
|
return testbitcast(z, ulong);
|
|
}
|
|
|
|
fn char[4] test(float x)
|
|
{
|
|
return testbitcast(x, char[4]);
|
|
}
|
|
|
|
fn void main()
|
|
{
|
|
float f = 12.353;
|
|
int i = testbitcast(f, int);
|
|
float f2 = testbitcast(i, float);
|
|
printf("%f => %d => %f\n", f, i, f2);
|
|
double d = 12.353e267;
|
|
ulong l = testbitcast(d, ulong);
|
|
double d2 = testbitcast(d, double);
|
|
printf("%e => %llu => %e\n", d, l, d2);
|
|
|
|
}
|
|
|
|
/* #expect: userland_bitcast.ll
|
|
|
|
%Foo = type { i16, i8, i8, i16, i16 }
|
|
|
|
@.typeid.userland_bitcast.Foo = linkonce constant { i8, i64 } { i8 10, i64 5 }, align 8
|
|
@.str = private unnamed_addr constant [16 x i8] c"%f => %d => %f\0A\00", align 1
|
|
@.str.1 = private unnamed_addr constant [18 x i8] c"%e => %llu => %e\0A\00", align 1
|
|
|
|
define i64 @userland_bitcast.testFoo(i16 signext %0) #0 {
|
|
entry:
|
|
%z = alloca %Foo, align 2
|
|
%expr = alloca %Foo, align 2
|
|
%x = alloca i64, align 8
|
|
%b = alloca i16*, align 8
|
|
%to = alloca i16*, align 8
|
|
%i = alloca i64, align 8
|
|
%1 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 0
|
|
store i16 0, i16* %1, align 2
|
|
%2 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 1
|
|
store i8 0, i8* %2, align 2
|
|
%3 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 2
|
|
store i8 0, i8* %3, align 1
|
|
%4 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 3
|
|
store i16 0, i16* %4, align 2
|
|
%5 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 4
|
|
store i16 0, i16* %5, align 2
|
|
%6 = getelementptr inbounds %Foo, %Foo* %z, i32 0, i32 0
|
|
store i16 %0, i16* %6, align 2
|
|
%7 = load %Foo, %Foo* %z, align 2
|
|
store %Foo %7, %Foo* %expr, align 2
|
|
%ptrptr = bitcast %Foo* %expr to i16*
|
|
store i16* %ptrptr, i16** %b, align 8
|
|
%ptrptr1 = bitcast i64* %x to i16*
|
|
store i16* %ptrptr1, i16** %to, align 8
|
|
store i64 0, i64* %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond: ; preds = %loop.body, %entry
|
|
%8 = load i64, i64* %i, align 8
|
|
%lt = icmp ult i64 %8, 8
|
|
br i1 %lt, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%9 = load i16*, i16** %to, align 8
|
|
%10 = load i64, i64* %i, align 8
|
|
%ptroffset = getelementptr inbounds i16, i16* %9, i64 %10
|
|
%11 = load i16*, i16** %b, align 8
|
|
%12 = load i64, i64* %i, align 8
|
|
%ptroffset2 = getelementptr inbounds i16, i16* %11, i64 %12
|
|
%13 = load i16, i16* %ptroffset2, align 2
|
|
store i16 %13, i16* %ptroffset, align 2
|
|
%14 = load i64, i64* %i, align 8
|
|
%add = add i64 %14, 2
|
|
store i64 %add, i64* %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
%15 = load i64, i64* %x, align 8
|
|
ret i64 %15
|
|
}
|
|
|
|
define i32 @userland_bitcast.test(float %0) #0 {
|
|
entry:
|
|
%expr = alloca float, align 4
|
|
%x = alloca [4 x i8], align 1
|
|
%b = alloca i8*, align 8
|
|
%to = alloca i8*, align 8
|
|
%i = alloca i64, align 8
|
|
%tempcoerce = alloca i32, align 4
|
|
store float %0, float* %expr, align 4
|
|
%ptrptr = bitcast float* %expr to i8*
|
|
store i8* %ptrptr, i8** %b, align 8
|
|
%ptrptr1 = bitcast [4 x i8]* %x to i8*
|
|
store i8* %ptrptr1, i8** %to, align 8
|
|
store i64 0, i64* %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond: ; preds = %loop.body, %entry
|
|
%1 = load i64, i64* %i, align 8
|
|
%lt = icmp ult i64 %1, 4
|
|
br i1 %lt, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%2 = load i8*, i8** %to, align 8
|
|
%3 = load i64, i64* %i, align 8
|
|
%ptroffset = getelementptr inbounds i8, i8* %2, i64 %3
|
|
%4 = load i8*, i8** %b, align 8
|
|
%5 = load i64, i64* %i, align 8
|
|
%ptroffset2 = getelementptr inbounds i8, i8* %4, i64 %5
|
|
%6 = load i8, i8* %ptroffset2, align 1
|
|
store i8 %6, i8* %ptroffset, align 1
|
|
%7 = load i64, i64* %i, align 8
|
|
%add = add i64 %7, 1
|
|
store i64 %add, i64* %i, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
%8 = bitcast i32* %tempcoerce to i8*
|
|
%9 = bitcast [4 x i8]* %x to i8*
|
|
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %8, i8* align 1 %9, i32 4, i1 false)
|
|
%10 = load i32, i32* %tempcoerce, align 4
|
|
ret i32 %10
|
|
}
|
|
|
|
define void @userland_bitcast.main() #0 {
|
|
entry:
|
|
%f = alloca float, align 4
|
|
%i = alloca i32, align 4
|
|
%expr = alloca float, align 4
|
|
%x = alloca i32, align 4
|
|
%b = alloca i32*, align 8
|
|
%to = alloca i32*, align 8
|
|
%i1 = alloca i64, align 8
|
|
%f2 = alloca float, align 4
|
|
%expr3 = alloca i32, align 4
|
|
%x4 = alloca float, align 4
|
|
%b5 = alloca i32*, align 8
|
|
%to6 = alloca i32*, align 8
|
|
%i8 = alloca i64, align 8
|
|
%d = alloca double, align 8
|
|
%l = alloca i64, align 8
|
|
%expr17 = alloca double, align 8
|
|
%x18 = alloca i64, align 8
|
|
%b19 = alloca i64*, align 8
|
|
%to21 = alloca i64*, align 8
|
|
%i22 = alloca i64, align 8
|
|
%d2 = alloca double, align 8
|
|
%expr30 = alloca double, align 8
|
|
%x31 = alloca double, align 8
|
|
%b32 = alloca i64*, align 8
|
|
%to34 = alloca i64*, align 8
|
|
%i36 = alloca i64, align 8
|
|
store float 0x4028B4BC60000000, float* %f, align 4
|
|
%0 = load float, float* %f, align 4
|
|
store float %0, float* %expr, align 4
|
|
%ptrptr = bitcast float* %expr to i32*
|
|
store i32* %ptrptr, i32** %b, align 8
|
|
store i32* %x, i32** %to, align 8
|
|
store i64 0, i64* %i1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.cond: ; preds = %loop.body, %entry
|
|
%1 = load i64, i64* %i1, align 8
|
|
%lt = icmp ult i64 %1, 4
|
|
br i1 %lt, label %loop.body, label %loop.exit
|
|
|
|
loop.body: ; preds = %loop.cond
|
|
%2 = load i32*, i32** %to, align 8
|
|
%3 = load i64, i64* %i1, align 8
|
|
%ptroffset = getelementptr inbounds i32, i32* %2, i64 %3
|
|
%4 = load i32*, i32** %b, align 8
|
|
%5 = load i64, i64* %i1, align 8
|
|
%ptroffset2 = getelementptr inbounds i32, i32* %4, i64 %5
|
|
%6 = load i32, i32* %ptroffset2, align 4
|
|
store i32 %6, i32* %ptroffset, align 4
|
|
%7 = load i64, i64* %i1, align 8
|
|
%add = add i64 %7, 4
|
|
store i64 %add, i64* %i1, align 8
|
|
br label %loop.cond
|
|
|
|
loop.exit: ; preds = %loop.cond
|
|
%8 = load i32, i32* %x, align 4
|
|
store i32 %8, i32* %i, align 4
|
|
%9 = load i32, i32* %i, align 4
|
|
store i32 %9, i32* %expr3, align 4
|
|
store i32* %expr3, i32** %b5, align 8
|
|
%ptrptr7 = bitcast float* %x4 to i32*
|
|
store i32* %ptrptr7, i32** %to6, align 8
|
|
store i64 0, i64* %i8, align 8
|
|
br label %loop.cond9
|
|
|
|
loop.cond9: ; preds = %loop.body11, %loop.exit
|
|
%10 = load i64, i64* %i8, align 8
|
|
%lt10 = icmp ult i64 %10, 4
|
|
br i1 %lt10, label %loop.body11, label %loop.exit15
|
|
|
|
loop.body11: ; preds = %loop.cond9
|
|
%11 = load i32*, i32** %to6, align 8
|
|
%12 = load i64, i64* %i8, align 8
|
|
%ptroffset12 = getelementptr inbounds i32, i32* %11, i64 %12
|
|
%13 = load i32*, i32** %b5, align 8
|
|
%14 = load i64, i64* %i8, align 8
|
|
%ptroffset13 = getelementptr inbounds i32, i32* %13, i64 %14
|
|
%15 = load i32, i32* %ptroffset13, align 4
|
|
store i32 %15, i32* %ptroffset12, align 4
|
|
%16 = load i64, i64* %i8, align 8
|
|
%add14 = add i64 %16, 4
|
|
store i64 %add14, i64* %i8, align 8
|
|
br label %loop.cond9
|
|
|
|
loop.exit15: ; preds = %loop.cond9
|
|
%17 = load float, float* %x4, align 4
|
|
store float %17, float* %f2, align 4
|
|
%18 = load float, float* %f, align 4
|
|
%fpfpext = fpext float %18 to double
|
|
%19 = load i32, i32* %i, align 4
|
|
%20 = load float, float* %f2, align 4
|
|
%fpfpext16 = fpext float %20 to double
|
|
call void (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i32 0, i32 0), double %fpfpext, i32 %19, double %fpfpext16)
|
|
store double 1.235300e+268, double* %d, align 8
|
|
%21 = load double, double* %d, align 8
|
|
store double %21, double* %expr17, align 8
|
|
%ptrptr20 = bitcast double* %expr17 to i64*
|
|
store i64* %ptrptr20, i64** %b19, align 8
|
|
store i64* %x18, i64** %to21, align 8
|
|
store i64 0, i64* %i22, align 8
|
|
br label %loop.cond23
|
|
|
|
loop.cond23: ; preds = %loop.body25, %loop.exit15
|
|
%22 = load i64, i64* %i22, align 8
|
|
%lt24 = icmp ult i64 %22, 8
|
|
br i1 %lt24, label %loop.body25, label %loop.exit29
|
|
|
|
loop.body25: ; preds = %loop.cond23
|
|
%23 = load i64*, i64** %to21, align 8
|
|
%24 = load i64, i64* %i22, align 8
|
|
%ptroffset26 = getelementptr inbounds i64, i64* %23, i64 %24
|
|
%25 = load i64*, i64** %b19, align 8
|
|
%26 = load i64, i64* %i22, align 8
|
|
%ptroffset27 = getelementptr inbounds i64, i64* %25, i64 %26
|
|
%27 = load i64, i64* %ptroffset27, align 8
|
|
store i64 %27, i64* %ptroffset26, align 8
|
|
%28 = load i64, i64* %i22, align 8
|
|
%add28 = add i64 %28, 8
|
|
store i64 %add28, i64* %i22, align 8
|
|
br label %loop.cond23
|
|
|
|
loop.exit29: ; preds = %loop.cond23
|
|
%29 = load i64, i64* %x18, align 8
|
|
store i64 %29, i64* %l, align 8
|
|
%30 = load double, double* %d, align 8
|
|
store double %30, double* %expr30, align 8
|
|
%ptrptr33 = bitcast double* %expr30 to i64*
|
|
store i64* %ptrptr33, i64** %b32, align 8
|
|
%ptrptr35 = bitcast double* %x31 to i64*
|
|
store i64* %ptrptr35, i64** %to34, align 8
|
|
store i64 0, i64* %i36, align 8
|
|
br label %loop.cond37
|
|
|
|
loop.cond37: ; preds = %loop.body39, %loop.exit29
|
|
%31 = load i64, i64* %i36, align 8
|
|
%lt38 = icmp ult i64 %31, 8
|
|
br i1 %lt38, label %loop.body39, label %loop.exit43
|
|
|
|
loop.body39: ; preds = %loop.cond37
|
|
%32 = load i64*, i64** %to34, align 8
|
|
%33 = load i64, i64* %i36, align 8
|
|
%ptroffset40 = getelementptr inbounds i64, i64* %32, i64 %33
|
|
%34 = load i64*, i64** %b32, align 8
|
|
%35 = load i64, i64* %i36, align 8
|
|
%ptroffset41 = getelementptr inbounds i64, i64* %34, i64 %35
|
|
%36 = load i64, i64* %ptroffset41, align 8
|
|
store i64 %36, i64* %ptroffset40, align 8
|
|
%37 = load i64, i64* %i36, align 8
|
|
%add42 = add i64 %37, 8
|
|
store i64 %add42, i64* %i36, align 8
|
|
br label %loop.cond37
|
|
|
|
loop.exit43: ; preds = %loop.cond37
|
|
%38 = load double, double* %x31, align 8
|
|
store double %38, double* %d2, align 8
|
|
%39 = load double, double* %d, align 8
|
|
%40 = load i64, i64* %l, align 8
|
|
%41 = load double, double* %d2, align 8
|
|
call void (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i32 0, i32 0), double %39, i64 %40, double %41)
|
|
ret void
|
|
}
|
|
|