mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Optimized and improved aggregate initialization. Compound literal updated to Foo({ 1, 2 })-style. ".name = x" style initialization for named arguments and designated initializers. Added runtime messages on panics. subarrays convert implictly to pointers. len/len() functions. Fix taking slice of pointer. Vararg fixes
Consistent length typedef.
First stab at initializers.
Change compound literal to Foo({ 1, 2 }) style.
Fixed up some tests.
Optimize the zero struct codegen.
Optimize union empty initializer.
Fix issues with unions. Added alignment to globals. Added some union tests.
Use puts to emit error messages during runtime. Fixup of int[] -> int* style conversions.
Fix implicit conversion of int[3]* -> int*
Fix int[] size. Use () to invoke the length of a subarray. Fix taking a slice of a pointer. Limit the number of members in a struct.
Fixes to vararg using debug and cleanups to slices.
This commit is contained in:
@@ -5,12 +5,14 @@ struct Test
|
||||
int x;
|
||||
}
|
||||
|
||||
Test foo = {};
|
||||
|
||||
extern func void blorg(Test t);
|
||||
|
||||
func Test creator()
|
||||
{
|
||||
blorg(Test {} );
|
||||
return Test {};
|
||||
blorg(Test({}));
|
||||
return Test({});
|
||||
}
|
||||
|
||||
// #expect: literal_load.ll
|
||||
|
||||
25
test/test_suite/arrays/array_casts.c3t
Normal file
25
test/test_suite/arrays/array_casts.c3t
Normal file
@@ -0,0 +1,25 @@
|
||||
module test;
|
||||
|
||||
|
||||
func void test()
|
||||
{
|
||||
int[3] x;
|
||||
int *y = &x;
|
||||
int[] z = &x;
|
||||
}
|
||||
|
||||
// #expect: array_casts.ll
|
||||
|
||||
%"int[]" = type { i32*, i64 }
|
||||
|
||||
%x = alloca [3 x i32], align 4
|
||||
%y = alloca i32*, align 8
|
||||
%z = alloca %"int[]", align 8
|
||||
%0 = bitcast [3 x i32]* %x to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 12, i1 false)
|
||||
%ptrptr = bitcast [3 x i32]* %x to i32*
|
||||
store i32* %ptrptr, i32** %y, align 8
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%2 = insertvalue %"int[]" undef, i32* %1, 0
|
||||
%3 = insertvalue %"int[]" %2, i64 3, 1
|
||||
store %"int[]" %3, %"int[]"* %z, align 8
|
||||
12
test/test_suite/arrays/array_invalid_casts.c3
Normal file
12
test/test_suite/arrays/array_invalid_casts.c3
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
func void test()
|
||||
{
|
||||
int[3] x;
|
||||
double *y = &x; // #error: Cannot implicitly cast 'int[3]*' to 'double*
|
||||
}
|
||||
|
||||
func void test2()
|
||||
{
|
||||
int[3] x;
|
||||
double[] z = &x; // #error: Cannot cast 'int[3]*' to 'double[]'
|
||||
}
|
||||
@@ -29,11 +29,12 @@ struct ExtraSimple
|
||||
|
||||
func void testSimple()
|
||||
{
|
||||
ExtraSimple a = { c.j = 3.3 };
|
||||
ExtraSimple a = { .c.j = 3.3 };
|
||||
a.c.j = 3.4;
|
||||
printf("a = %d, c.e = %f, c.f = %f, c.j = %f, g = %d, o0 = %f, r = %d, s = %d\n", a.a, a.c.e, a.c.f, a.c.j, a.g, a.o0, a.r, a.s);
|
||||
}
|
||||
|
||||
// TODO these may be wrong.
|
||||
// #expect: pointer_access.ll
|
||||
|
||||
%pointer_access.ExtraSimple = type { i32, i32, %pointer_access.c, %pointer_access.anon, %pointer_access.anon.0, i32 }
|
||||
@@ -45,39 +46,32 @@ func void testSimple()
|
||||
|
||||
entry:
|
||||
%a = alloca %pointer_access.ExtraSimple, align 8
|
||||
%literal = alloca %pointer_access.ExtraSimple, align 8
|
||||
%0 = bitcast %pointer_access.ExtraSimple* %literal to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 72, i1 false)
|
||||
%c = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %literal, i32 0, i32 2
|
||||
%double = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c, i32 0, i32 4
|
||||
store double 3.300000e+00, double* %double
|
||||
%1 = bitcast %pointer_access.ExtraSimple* %a to i8*
|
||||
%2 = bitcast %pointer_access.ExtraSimple* %literal to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %1, i8* align 8 %2, i32 72, i1 false)
|
||||
%c1 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%j = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c1, i32 0, i32 4
|
||||
%0 = bitcast %pointer_access.ExtraSimple* %a to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %0, i8* align 8 bitcast (%pointer_access.ExtraSimple* @0 to i8*), i32 72, i1 false)
|
||||
%c = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%j = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c, i32 0, i32 4
|
||||
store double 3.400000e+00, double* %j, align 8
|
||||
%a2 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 0
|
||||
%3 = load i32, i32* %a2, align 4
|
||||
%a1 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 0
|
||||
%1 = load i32, i32* %a1, align 4
|
||||
%c2 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%e = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c2, i32 0, i32 0
|
||||
%2 = load double, double* %e, align 8
|
||||
%c3 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%e = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c3, i32 0, i32 0
|
||||
%4 = load double, double* %e, align 8
|
||||
%f = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c3, i32 0, i32 3
|
||||
%3 = load double, double* %f, align 8
|
||||
%c4 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%f = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c4, i32 0, i32 3
|
||||
%5 = load double, double* %f, align 8
|
||||
%c5 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 2
|
||||
%j6 = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c5, i32 0, i32 4
|
||||
%6 = load double, double* %j6, align 8
|
||||
%j5 = getelementptr inbounds %pointer_access.c, %pointer_access.c* %c4, i32 0, i32 4
|
||||
%4 = load double, double* %j5, align 8
|
||||
%g = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 5
|
||||
%7 = load i32, i32* %g, align 4
|
||||
%5 = load i32, i32* %g, align 4
|
||||
%anon = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 4
|
||||
%o0 = bitcast %pointer_access.anon.0* %anon to double*
|
||||
%8 = load double, double* %o0, align 8
|
||||
%6 = load double, double* %o0, align 8
|
||||
%anon6 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 3
|
||||
%r = getelementptr inbounds %pointer_access.anon, %pointer_access.anon* %anon6, i32 0, i32 0
|
||||
%7 = load i32, i32* %r, align 4
|
||||
%anon7 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 3
|
||||
%r = getelementptr inbounds %pointer_access.anon, %pointer_access.anon* %anon7, i32 0, i32 0
|
||||
%9 = load i32, i32* %r, align 4
|
||||
%anon8 = getelementptr inbounds %pointer_access.ExtraSimple, %pointer_access.ExtraSimple* %a, i32 0, i32 3
|
||||
%s = getelementptr inbounds %pointer_access.anon, %pointer_access.anon* %anon8, i32 0, i32 1
|
||||
%10 = load i32, i32* %s, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([71 x i8], [71 x i8]* @0, i32 0, i32 0), i32 %3, double %4, double %5, double %6, i32 %7, double %8, i32 %9, i32 %10)
|
||||
%s = getelementptr inbounds %pointer_access.anon, %pointer_access.anon* %anon7, i32 0, i32 1
|
||||
%8 = load i32, i32* %s, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([71 x i8], [71 x i8]* @1, i32 0, i32 0), i32 %1, double %2, double %3, double %4, i32 %5, double %6, i32 %7, i32 %8)
|
||||
ret void
|
||||
38
test/test_suite/functions/varargs.c3t
Normal file
38
test/test_suite/functions/varargs.c3t
Normal file
@@ -0,0 +1,38 @@
|
||||
module test;
|
||||
|
||||
extern func void printf(char* c, ...);
|
||||
|
||||
func void test()
|
||||
{
|
||||
printf("%d\n", true);
|
||||
printf("%d\n", 123);
|
||||
printf("%f\n", 12.3);
|
||||
char x1 = -123;
|
||||
bool b = false;
|
||||
float z1 = 12.3;
|
||||
printf("%d\n", b);
|
||||
printf("%d\n", x1);
|
||||
printf("%f\n", z1);
|
||||
}
|
||||
|
||||
// #expect: varargs.ll
|
||||
|
||||
%x1 = alloca i8, align 1
|
||||
%b = alloca i8, align 1
|
||||
%z1 = alloca float, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), i32 1)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @1, i32 0, i32 0), i32 123)
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @2, i32 0, i32 0), double 1.230000e+01)
|
||||
store i8 -123, i8* %x1, align 1
|
||||
store i8 0, i8* %b, align 1
|
||||
store float 0x40289999A0000000, float* %z1, align 4
|
||||
%0 = load i8, i8* %b, align 1
|
||||
%1 = trunc i8 %0 to i1
|
||||
%boolsi = zext i1 %1 to i32
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @3, i32 0, i32 0), i32 %boolsi)
|
||||
%2 = load i8, i8* %x1, align 1
|
||||
%sisiext = sext i8 %2 to i32
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @4, i32 0, i32 0), i32 %sisiext)
|
||||
%3 = load float, float* %z1, align 4
|
||||
%fpfpext = fpext float %3 to double
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @5, i32 0, i32 0), double %fpfpext)
|
||||
@@ -50,7 +50,7 @@ func void tester()
|
||||
p.uu.e = 8;
|
||||
Point *p2 = &p;
|
||||
p2.bb.b = 3;
|
||||
p = { a = 1, bb.b = 3, e = 2 };
|
||||
p = { .a = 1, .bb.b = 3, .e = 2 };
|
||||
|
||||
Point* pp = &p;
|
||||
pp.a = 20;
|
||||
@@ -82,6 +82,6 @@ struct Struct
|
||||
func void myfunc()
|
||||
{
|
||||
Struct s;
|
||||
s.b = 10; // #error: There is no element or method 'Struct.b'
|
||||
s.b = 10; // #error: There is no field or method 'Struct.b'
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,5 @@ func void test1()
|
||||
entry:
|
||||
%p = alloca %test.Point, align 4
|
||||
%0 = bitcast %test.Point* %p to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast (%test.Point* @0 to i8*), i32 8, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 8 bitcast (%test.Point* @0 to i8*), i32 8, i1 false)
|
||||
|
||||
|
||||
39
test/test_suite/struct/struct_codegen_empty.c3t
Normal file
39
test/test_suite/struct/struct_codegen_empty.c3t
Normal file
@@ -0,0 +1,39 @@
|
||||
struct StructA
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
struct StructB
|
||||
{
|
||||
struct b
|
||||
{
|
||||
int a;
|
||||
}
|
||||
}
|
||||
|
||||
func void test()
|
||||
{
|
||||
StructA a = {};
|
||||
StructA a2;
|
||||
StructB b = {};
|
||||
StructB b2;
|
||||
StructB b3 = { .b = { } };
|
||||
}
|
||||
|
||||
// #expect: struct_codegen_empty.ll
|
||||
|
||||
%a = alloca %struct_codegen_empty.StructA, align 4
|
||||
%a2 = alloca %struct_codegen_empty.StructA, align 4
|
||||
%b = alloca %struct_codegen_empty.StructB, align 4
|
||||
%b2 = alloca %struct_codegen_empty.StructB, align 4
|
||||
%b3 = alloca %struct_codegen_empty.StructB, align 4
|
||||
%0 = bitcast %struct_codegen_empty.StructA* %a to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 4, i1 false)
|
||||
%1 = bitcast %struct_codegen_empty.StructA* %a2 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 4, i1 false)
|
||||
%2 = bitcast %struct_codegen_empty.StructB* %b to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %2, i8 0, i64 4, i1 false)
|
||||
%3 = bitcast %struct_codegen_empty.StructB* %b2 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %3, i8 0, i64 4, i1 false)
|
||||
%4 = bitcast %struct_codegen_empty.StructB* %b3 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %4, i8 0, i64 4, i1 false)
|
||||
@@ -22,7 +22,7 @@ func void test3()
|
||||
func void test4()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^0];
|
||||
int[] z = x[..^1];
|
||||
z = x[..^-1]; // #error: Negative numbers are not allowed when indexing from the end.
|
||||
}
|
||||
|
||||
@@ -63,4 +63,10 @@ func void test10()
|
||||
int[] w = x[0..]; // #error: Omitting end index is not allowed for pointers.
|
||||
int[] z = x[^2..]; // #error: Indexing from the end is not allowed for pointers.
|
||||
int[] y = x[..^2]; // #error: Indexing from the end is not allowed for pointers.
|
||||
}
|
||||
}
|
||||
|
||||
func void test11()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] z = x[..^0]; // #error: Array end index out of bounds, was 3, exceeding array length 3
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ func void test()
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
%3 = insertvalue %"int[]" %2, i64 1, 1
|
||||
%3 = insertvalue %"int[]" %2, i64 2, 1
|
||||
store %"int[]" %3, %"int[]"* %y, align 8
|
||||
|
||||
@@ -14,6 +14,6 @@ func void test()
|
||||
%1 = bitcast [3 x i32]* %x to i32*
|
||||
%offset = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%2 = insertvalue %"int[]" undef, i32* %offset, 0
|
||||
%3 = insertvalue %"int[]" %2, i64 1, 1
|
||||
%3 = insertvalue %"int[]" %2, i64 2, 1
|
||||
store %"int[]" %3, %"int[]"* %y, align 8
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
func void test()
|
||||
{
|
||||
int[3] x = { 1, 2, 3 };
|
||||
int[] y = x[^2..2];
|
||||
int[] y = x[^2..1];
|
||||
}
|
||||
|
||||
// #expect: slice_offset_neg_start.ll
|
||||
|
||||
@@ -2,9 +2,9 @@ func void test()
|
||||
{
|
||||
int[6] feok2 = { 1, 8, 100, 293, 23982, 34};
|
||||
int[] feok = &feok2;
|
||||
int[] flok = feok2[3..6];
|
||||
int[] flok = feok2[3..5];
|
||||
int[] flak = flok[1..2];
|
||||
flok = feok2[..6];
|
||||
flok = feok2[..5];
|
||||
flok = feok2[..^2];
|
||||
flok = feok2[..];
|
||||
flok = feok2[^3..];
|
||||
|
||||
20
test/test_suite/union/union_codegen_const.c3t
Normal file
20
test/test_suite/union/union_codegen_const.c3t
Normal file
@@ -0,0 +1,20 @@
|
||||
module test;
|
||||
|
||||
union Foo
|
||||
{
|
||||
int a;
|
||||
double b;
|
||||
}
|
||||
|
||||
Foo f = { .a = 23 };
|
||||
Foo g = { .b = 2.3 };
|
||||
Foo h = { .a = 23, .b = 2.3 };
|
||||
Foo i = { .b = 2.3, .a = 23 };
|
||||
|
||||
// #expect: union_codegen_const.ll
|
||||
|
||||
@f = protected global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8
|
||||
@g = protected global %test.Foo { double 2.300000e+00 }, align 8
|
||||
@h = protected global %test.Foo { double 2.300000e+00 }, align 8
|
||||
@i = protected global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8
|
||||
|
||||
45
test/test_suite/union/union_codegen_empty.c3t
Normal file
45
test/test_suite/union/union_codegen_empty.c3t
Normal file
@@ -0,0 +1,45 @@
|
||||
union UnionA
|
||||
{
|
||||
int a;
|
||||
}
|
||||
|
||||
union UnionB
|
||||
{
|
||||
struct b
|
||||
{
|
||||
int a;
|
||||
}
|
||||
int c;
|
||||
double d;
|
||||
}
|
||||
|
||||
func void test()
|
||||
{
|
||||
UnionA a = {};
|
||||
UnionA a2;
|
||||
UnionB b = {};
|
||||
UnionB b2;
|
||||
UnionB b3 = { .b = {} };
|
||||
UnionB b4 = { .b.a = 23, .c = 4, .d = 0.4, .b = {} };
|
||||
}
|
||||
|
||||
// #expect: union_codegen_empty.ll
|
||||
|
||||
%a = alloca %union_codegen_empty.UnionA, align 4
|
||||
%a2 = alloca %union_codegen_empty.UnionA, align 4
|
||||
%b = alloca %union_codegen_empty.UnionB, align 8
|
||||
%b2 = alloca %union_codegen_empty.UnionB, align 8
|
||||
%b3 = alloca %union_codegen_empty.UnionB, align 8
|
||||
%b4 = alloca %union_codegen_empty.UnionB, align 8
|
||||
%0 = bitcast %union_codegen_empty.UnionA* %a to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 4, i1 false)
|
||||
%1 = bitcast %union_codegen_empty.UnionA* %a2 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 4, i1 false)
|
||||
%2 = bitcast %union_codegen_empty.UnionB* %b to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %2, i8 0, i64 8, i1 false)
|
||||
%3 = bitcast %union_codegen_empty.UnionB* %b2 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false)
|
||||
%4 = bitcast %union_codegen_empty.UnionB* %b3 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %4, i8 0, i64 8, i1 false)
|
||||
%5 = bitcast %union_codegen_empty.UnionB* %b4 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %5, i8 0, i64 8, i1 false)
|
||||
30
test/test_suite/union/union_codegen_overwrite_call.c3t
Normal file
30
test/test_suite/union/union_codegen_overwrite_call.c3t
Normal file
@@ -0,0 +1,30 @@
|
||||
module test;
|
||||
|
||||
union UnionB
|
||||
{
|
||||
struct b
|
||||
{
|
||||
int a;
|
||||
}
|
||||
int c;
|
||||
double d;
|
||||
}
|
||||
|
||||
extern func int bar();
|
||||
|
||||
func void test()
|
||||
{
|
||||
UnionB b = { .c = bar(), .b = {} };
|
||||
}
|
||||
|
||||
// #expect: union_codegen_overwrite_call.ll
|
||||
|
||||
entry:
|
||||
%b = alloca %test.UnionB, align 8
|
||||
%1 = bitcast %test.UnionB* %b to i32*
|
||||
%2 = call i32 @bar()
|
||||
store i32 %2, i32* %1, align 4
|
||||
%3 = bitcast %test.UnionB* %b to %test.b*
|
||||
%4 = bitcast %test.b* %3 to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* %4, i8 0, i64 4, i1 false)
|
||||
ret void
|
||||
Reference in New Issue
Block a user