Re: [Tinycc-devel] Fwd: TCC VLA bug?
Hello grischka, On Tue, 7 Dec 2021, grischka wrote: Michael Matz wrote: So, the problematic type was: int (*)[a][b] That's pointer to an vla-array of an vla-array of int. All three (inner array, outer array and pointer, but not the int) should be marked VT_VLA. Hm..., IMO one (very) invariant convention is that VT_ARRAY rsp. VT_VLA always also have VT_PTR. Therefor if the outer pointer would have VT_VLA as you say above, then it would be not a pointer to a VLA, but it would be a VLA, as in int arr[z][a][b]; Right, sorry. It really doesn't help to be imprecise here, like I was. In the type 'int (*)[a][b]' the outer pointer doesn't need VT_VLA, but the inner two array types do (and the int itself doesn't). But I was wiggling around because I also wanted to avoid really looking into it :) TCC should generate four CType structs for this type: CType *t; // the full thing, VT_PTR only, 'int (*)[a][b]' CType *o = t->ref; // outer vla, VT_PTR|VT_VLA, 'int [a][b]' CType *i = o->ref; // inner vla, VT_PTR|VT_VLA, 'int [b]' CType *e = i->ref; // element, 'int' And without looking I wasn't sure it really does (I still am not) ;-) Anyway, now that I already did look into it (which initially I was trying to avoid ;) I would maybe just replace all this: if (type1.ref->type.t & VT_VLA) vla_runtime_pointed_size(); else { u = pointed_size(); if (u < 0) tcc_error("unknown array element size"); #if PTR_SIZE == 8 vpushll(u); #else /* XXX: cast to int ? (long long case) */ vpushi(u); #endif by that single line: vla_runtime_type_size(pointed_type([-1].type), ): Yeah, I thought so as well when (very quickly! :) ) looking at this. Also in some other places that currently only conditionally call this. which looks as it would do the right thing automatically also for the normal array (non-vla) case (but except the "unknown array size" check). Of course one could rename "vla_runtime_type_size" to something better, then. Btw, now that I already did look into it (which initially ... ;) I think I found 2 related problems as can be seen with this (added to the original test case): // int (*arr)[h][w]; printf("diff = %d, size = %d/%d\n", arr + 1 - arr, sizeof *arr, sizeof (*arr + 1)); Yeah, during my quick scanning of tccgen.c I also found code that made me think 'huh?', and imagined there could be more errors like this, especially with multi-dimensional VLAs. Alas, I wanted to not get into tcc hacking this week :) Temptations everywhere! Ciao, Michael. -- gr In TCC we collapse the outer array+pointer into one type (a pointer that also has VT_ARRAY/VT_VLA set), so there actually should be two levels: the inner level a VT_VLA pointing to the VT_INT (with its VLA runtime length being evaluated to sizeof(int) * b) and the outer level a VT_VLA pointing to the inner VT_VLA (and its VLA runtime length being evaluated to inner length * a). I'm surprised that your patch didn't cause other problems, it seems either the testsuite isn't testing VLAs very much, or that the VT_VLA flag is set on types where it shouldn't have been (e.g. on the VT_INT type that is in the type->ref of the 'int [n]' array type). Ciao, Michael. ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Re: [Tinycc-devel] Fwd: TCC VLA bug?
Michael Matz wrote: So, the problematic type was: int (*)[a][b] That's pointer to an vla-array of an vla-array of int. All three (inner array, outer array and pointer, but not the int) should be marked VT_VLA. Hm..., IMO one (very) invariant convention is that VT_ARRAY rsp. VT_VLA always also have VT_PTR. Therefor if the outer pointer would have VT_VLA as you say above, then it would be not a pointer to a VLA, but it would be a VLA, as in int arr[z][a][b]; Anyway, now that I already did look into it (which initially I was trying to avoid ;) I would maybe just replace all this: if (type1.ref->type.t & VT_VLA) vla_runtime_pointed_size(); else { u = pointed_size(); if (u < 0) tcc_error("unknown array element size"); #if PTR_SIZE == 8 vpushll(u); #else /* XXX: cast to int ? (long long case) */ vpushi(u); #endif by that single line: vla_runtime_type_size(pointed_type([-1].type), ): which looks as it would do the right thing automatically also for the normal array (non-vla) case (but except the "unknown array size" check). Of course one could rename "vla_runtime_type_size" to something better, then. Btw, now that I already did look into it (which initially ... ;) I think I found 2 related problems as can be seen with this (added to the original test case): // int (*arr)[h][w]; printf("diff = %d, size = %d/%d\n", arr + 1 - arr, sizeof *arr, sizeof (*arr + 1)); -- gr In TCC we collapse the outer array+pointer into one type (a pointer that also has VT_ARRAY/VT_VLA set), so there actually should be two levels: the inner level a VT_VLA pointing to the VT_INT (with its VLA runtime length being evaluated to sizeof(int) * b) and the outer level a VT_VLA pointing to the inner VT_VLA (and its VLA runtime length being evaluated to inner length * a). I'm surprised that your patch didn't cause other problems, it seems either the testsuite isn't testing VLAs very much, or that the VT_VLA flag is set on types where it shouldn't have been (e.g. on the VT_INT type that is in the type->ref of the 'int [n]' array type). Ciao, Michael. ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Re: [Tinycc-devel] Fwd: TCC VLA bug?
Hello Michael Matz, On a side note about tcc and VLA, I have reported a valgrind bug on their mailing list. But there might be a chance that it is actually tcc bug, though I could not find any incorrect behavior in my programs compiled by tcc. I think it's quite normal for valgrind to complain about VLAs generated by tcc on x86_64? Here's the archived emails: https://sourceforge.net/p/valgrind/mailman/message/37382347/ https://sourceforge.net/p/valgrind/mailman/message/37382384/ https://sourceforge.net/p/valgrind/mailman/message/37382663/ https://sourceforge.net/p/valgrind/mailman/message/37382912/ John did not update on the results of further investigation and I suppose he did hit a hard wall. What's your opinion on the matter? I am not awfully familiar with tcc's VLA implementation itself, but it does something that triggers valgrind to think there are uninitialized values when it's not actually possible. Kind Regards, Kyryl. ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Re: [Tinycc-devel] Fwd: TCC VLA bug?
Hey, On Sun, 5 Dec 2021, Herman ten Brugge via Tinycc-devel wrote: On 12/1/21 15:18, grischka wrote: Got this report on private email. Not sure what it means ... -->> Output of the code below if compiled with TCC is pretty messy: array values are "misplaced" and overwrite each other. But everything's ok if compiled with GCC. The patch below seems to fix it. Can I push it? Herman diff --git a/tccgen.c b/tccgen.c index e0b5fd6..67e205b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3494,7 +3494,7 @@ redo: gen_cast_s(VT_INT); #endif type1 = vtop[-1].type; - if (vtop[-1].type.t & VT_VLA) + if (vtop[-1].type.ref->type.t & VT_VLA) vla_runtime_pointed_size([-1].type); Hmm, that would mean the VT_VLA flags are wrongly set. The invariant of vla_runtime_pointed_size(type...) is that type->t has VT_VLA (and that type->ref is meaningful). If your patch helps in this situation that means the flag setting is going wrong somewhere. I see that the testcase has doubly-vla types, maybe only the innermost level is marked, but a variable length type is of course variably length if any of the referred types is, so maybe that's the problem. Just speculation, though. So, the problematic type was: int (*)[a][b] That's pointer to an vla-array of an vla-array of int. All three (inner array, outer array and pointer, but not the int) should be marked VT_VLA. In TCC we collapse the outer array+pointer into one type (a pointer that also has VT_ARRAY/VT_VLA set), so there actually should be two levels: the inner level a VT_VLA pointing to the VT_INT (with its VLA runtime length being evaluated to sizeof(int) * b) and the outer level a VT_VLA pointing to the inner VT_VLA (and its VLA runtime length being evaluated to inner length * a). I'm surprised that your patch didn't cause other problems, it seems either the testsuite isn't testing VLAs very much, or that the VT_VLA flag is set on types where it shouldn't have been (e.g. on the VT_INT type that is in the type->ref of the 'int [n]' array type). Ciao, Michael.___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Re: [Tinycc-devel] Fwd: TCC VLA bug?
On 12/1/21 15:18, grischka wrote: Got this report on private email. Not sure what it means ... -->> Output of the code below if compiled with TCC is pretty messy: array values are "misplaced" and overwrite each other. But everything's ok if compiled with GCC. The patch below seems to fix it. Can I push it? Herman diff --git a/tccgen.c b/tccgen.c index e0b5fd6..67e205b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3494,7 +3494,7 @@redo: gen_cast_s(VT_INT); #endif type1 = vtop[-1].type; - if (vtop[-1].type.t & VT_VLA) + if (vtop[-1].type.ref->type.t & VT_VLA) vla_runtime_pointed_size([-1].type); else { u = pointed_size([-1].type); ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Re: [Tinycc-devel] Fwd: TCC VLA bug?
On Fri, 3 Dec 2021 01:06:35 +0200 Stefanos via Tinycc-devel wrote: > With `gcc -std=c99` and `gcc -std=c11` I get the - identical in both cases - > following output: > >1 2 3 4 5 >6 7 8 9 10 > 11 12 13 14 15 > 16 17 18 19 20 > > 21 22 23 24 25 > 26 27 28 29 30 > 31 32 33 34 35 > 36 37 38 39 40 > > 41 42 43 44 45 > 46 47 48 49 50 > 51 52 53 54 55 > 56 57 58 59 60 > >1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 > 20 > 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 > 40 > 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 > 60 > > With `tcc -std=c99` though and `tcc -std=c11` I get completely different > results: > > C99 output > -- > >1 2 21 22 41 > 42 43 44 45 46 > 47 48 49 50 51 > 52 53 54 55 56 > > 21 22 41 42 43 > 44 45 46 47 48 > 49 50 51 52 53 > 54 55 56 57 58 > > 41 42 43 44 45 > 46 47 48 49 50 > 51 52 53 54 55 > 56 57 58 59 60 > >1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 > 56 > 57 58 59 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 > 0 >0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 > 0 > > > C11 output > -- > >1 2 21 22 41 > 42 43 44 45 46 > 47 48 49 50 51 > 52 53 54 55 56 > > 21 22 41 42 43 > 44 45 46 47 48 > 49 50 51 52 53 > 54 55 56 57 58 > > 41 42 43 44 45 > 46 47 48 49 50 > 51 52 53 54 55 > 56 57 58 59 60 > >1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 > 56 > 57 58 59 60 0 0 16391 0-107212368 22035-107212704 22035-107212592 > 22035 0 0 536872934 0 8 0 >5 0-107212536 22035-107212648 22035-107212536 22035 0 0 536870912 > 0 -1 0 7 0-107212368 22035-107212592 22035 > > > For some reason, it gives me the impression it seems '21' as `2+1` thus '3', > `2+2` thus '4', and so forth; I could be wrong though... > Seems like it's related to `malloc()` somehow; with fix-sized array it behaves as expected. Here's the code, a bit modified for debugging purposes: #include #include int main(void) { const int w = 5; const int h = 4; const int d = 3; int (*arr)[h][w] = malloc(sizeof(int) * d*h*w); int c = 1; int starr[3][4][5]; /* fill with consecutive numbers */ for (int z=0; zhttps://lists.nongnu.org/mailman/listinfo/tinycc-devel
[Tinycc-devel] Fwd: TCC VLA bug?
With `gcc -std=c99` and `gcc -std=c11` I get the - identical in both cases - following output: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 With `tcc -std=c99` though and `tcc -std=c11` I get completely different results: C99 output -- 1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 C11 output -- 1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2 21 22 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 0 0 16391 0-107212368 22035-107212704 22035-107212592 22035 0 0 536872934 0 8 0 5 0-107212536 22035-107212648 22035-107212536 22035 0 0 536870912 0 -1 0 7 0-107212368 22035-107212592 22035 For some reason, it gives me the impression it seems '21' as `2+1` thus '3', `2+2` thus '4', and so forth; I could be wrong though... ___ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel
[Tinycc-devel] Fwd: TCC VLA bug?
Got this report on private email. Not sure what it means ... -->> Output of the code below if compiled with TCC is pretty messy: array values are "misplaced" and overwrite each other. But everything's ok if compiled with GCC. #include #include int main() { const int w = 5; const int h = 4; const int d = 3; int (*arr)[h][w] = malloc(sizeof(int) * d*h*w); int c = 1; /* fill with consecutive numbers */ for (int z=0; zhttps://lists.nongnu.org/mailman/listinfo/tinycc-devel