Skip to content

Commit 180516f

Browse files
authored
Merge pull request #302 from jayrm/gcc-warnings
Fix gcc warnings in C backend - Fixes github # 298 -Wc has a limit of 128 characters - Fixes github # 217 warning: array subscript -1 is outside array bounds - Fixes inline asm warning - allows options longer than 128 chars to be passed to gcc, as, ld
2 parents 3516f8d + 2240120 commit 180516f

File tree

5 files changed

+208
-143
lines changed

5 files changed

+208
-143
lines changed

changelog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Version 1.08.0
4545
- github #203: allow casts of addresses on static initializers
4646
- only write debug line information for statements and don't write comments / empty lines / directives for top level source code in assembly debug ouput
4747
- optimize byref 'm += s' string concatenations to fb_StrConcatByref() which will check for same string descriptor at run-time which can't be determined at compile time for byref parameters.
48+
- github #298: allow command line options passed to as, gcc, ld to be longer than 128 characters by using string types internally
4849

4950
[added]
5051
- extern "rtlib": respects the parent namespace, uses default fb calling convention and C style name mangling
@@ -132,6 +133,8 @@ Version 1.08.0
132133
- fix __FB_EVAL__() incorrectly reading past the end of the expression, and report errors in expressions
133134
- C backend: switch to .text section after writing the exports to the C file in the explicit asm block. gcc can move sections around with optimizations and there is a change between 7.x and 8.x that causes issue with where the directive section is located
134135
- sf.net #917: optimize 'm += s' string concatenations to fix the long compile times in the gcc backend (which makes heavy use of string building).
136+
- github #217: C backend, fix gcc array out of bounds warning when compiled with -O2 or higher optimizations and accessing non-zero lower bound fixed length string arrays
137+
- C backend: inline asm - don't add rsp/esp to the clobber list, it's deprecated in newer gcc versions and silently ignored in older versions
135138

136139

137140
Version 1.07.0

src/compiler/fbc.bas

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ enum
2525
end enum
2626

2727
type FBC_EXTOPT
28-
gas as zstring * 128
29-
ld as zstring * 128
30-
gcc as zstring * 128
28+
gas as string
29+
ld as string
30+
gcc as string
3131
end type
3232

3333
type FBCIOFILE

src/compiler/ir-hlc.bas

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,8 +2678,23 @@ private function exprNewVREG _
26782678
l = exprNewUOP( AST_OP_ADDROF, l )
26792679
end if
26802680
if( have_offset ) then
2681-
'' Cast to ubyte ptr to work around C's pointer arithmetic
2682-
l = exprNewCAST( typeAddrOf( FB_DATATYPE_UBYTE ), NULL, l )
2681+
if( is_c_array ) then
2682+
'' Cast to intptr_t to work around gcc out side of array bounds
2683+
'' warnings if we are casting from FBSTRING array to pointer
2684+
'' fbc uses a kind of virtual pointer for the an array's (0,..)
2685+
'' index; technically this is undefinded behaviour in C and is
2686+
'' impossible to cast away even when using pointer only casts
2687+
'' in the same expression. Some gcc optimizations cause a
2688+
'' a warning when setting a pointer for the array's virtual
2689+
'' index location. To fix this for compliant C code, would
2690+
'' need to rewrite the array descriptor to contain only the
2691+
'' offset value from actual memory pointer and compute the
2692+
'' array access fully on each array element access.
2693+
l = exprNewCAST( FB_DATATYPE_INTEGER, NULL, l )
2694+
else
2695+
'' Cast to ubyte ptr to work around C's pointer arithmetic
2696+
l = exprNewCAST( typeAddrOf( FB_DATATYPE_UBYTE ), NULL, l )
2697+
end if
26832698
if( vreg->vidx <> NULL ) then
26842699
l = exprNewBOP( AST_OP_ADD, l, exprNewVREG( vreg->vidx ) )
26852700
end if
@@ -3557,15 +3572,20 @@ private sub _emitAsmLine( byval asmtokenhead as ASTASMTOK ptr )
35573572
ln += " : " + inputconstraints
35583573

35593574
'' We don't know what registers etc. will be trashed,
3560-
'' so assume everything...
3575+
'' so assume everything... except for rsp/esp - gcc requires a valid
3576+
'' stack to preserve registers and if the asm code clobbers esp/rsp
3577+
'' then there is no way to get it back after esp/rsp changes to
3578+
'' something else. User is always responsible for handling the stack
3579+
'' registers.
3580+
''
35613581
ln += " : ""cc"", ""memory"""
35623582

35633583
select case( fbGetCpuFamily( ) )
35643584
case FB_CPUFAMILY_X86, FB_CPUFAMILY_X86_64
35653585
if( fbGetCpuFamily( ) = FB_CPUFAMILY_X86 ) then
3566-
ln += ", ""eax"", ""ebx"", ""ecx"", ""edx"", ""esp"", ""edi"", ""esi"""
3586+
ln += ", ""eax"", ""ebx"", ""ecx"", ""edx"", ""edi"", ""esi"""
35673587
else
3568-
ln += ", ""rax"", ""rbx"", ""rcx"", ""rdx"", ""rsp"", ""rdi"", ""rsi"""
3588+
ln += ", ""rax"", ""rbx"", ""rcx"", ""rdx"", ""rdi"", ""rsi"""
35693589
ln += ", ""r8"", ""r9"", ""r10"", ""r11"", ""r12"", ""r13"", ""r14"", ""r15"""
35703590
end if
35713591

tests/compound/select_const.bas

Lines changed: 0 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -564,139 +564,4 @@ SUITE( fbc_tests.compound.select_const )
564564

565565
END_TEST
566566

567-
TEST( RangeEdges )
568-
569-
dim as integer ok, nok
570-
571-
#macro TEST_RANGE( T, a, b, c_, d_, p, f )
572-
scope
573-
ok = 0
574-
nok = 0
575-
dim v as T
576-
#if LITERAL
577-
#define c c_
578-
#define d d_
579-
#else
580-
const c as T = c_
581-
const d as T = d_
582-
#endif
583-
v = a
584-
do
585-
select case as const v
586-
case (c) to (d)
587-
CU_ASSERT( (v>=(c)) and (v<=(d)) )
588-
ok += 1
589-
case else
590-
CU_ASSERT( not ((v>=(c)) and (v<=(d))) )
591-
nok += 1
592-
end select
593-
if( v = b ) then
594-
exit do
595-
end if
596-
v += 1
597-
loop
598-
CU_ASSERT_EQUAL( p, ok )
599-
CU_ASSERT_EQUAL( f, nok )
600-
end scope
601-
#endmacro
602-
603-
#macro TEST_RANGE_EDGES( T, a, b )
604-
TEST_RANGE( T, a+0, a+10, a+0, a+0, 1, 10 )
605-
TEST_RANGE( T, a+0, a+10, a+0, a+1, 2, 9 )
606-
TEST_RANGE( T, a+0, a+10, a+1, a+1, 1, 10 )
607-
TEST_RANGE( T, a+0, a+10, a+1, a+2, 2, 9 )
608-
TEST_RANGE( T, a+0, a+10, a+2, a+2, 1, 10 )
609-
610-
TEST_RANGE( T, a+0, a+10, a+0, a+3, 4, 7 )
611-
TEST_RANGE( T, a+0, a+10, a+1, a+4, 4, 7 )
612-
TEST_RANGE( T, a+0, a+10, a+2, a+5, 4, 7 )
613-
614-
TEST_RANGE( T, a+1, a+10, a+0, a+0, 0, 10 )
615-
TEST_RANGE( T, a+1, a+10, a+0, a+1, 1, 9 )
616-
TEST_RANGE( T, a+1, a+10, a+1, a+1, 1, 9 )
617-
TEST_RANGE( T, a+1, a+10, a+1, a+2, 2, 8 )
618-
TEST_RANGE( T, a+1, a+10, a+2, a+2, 1, 9 )
619-
620-
TEST_RANGE( T, b-10, b-0, b-0, b-0, 1, 10 )
621-
TEST_RANGE( T, b-10, b-0, b-1, b-0, 2, 9 )
622-
TEST_RANGE( T, b-10, b-0, b-1, b-1, 1, 10 )
623-
TEST_RANGE( T, b-10, b-0, b-2, b-1, 2, 9 )
624-
TEST_RANGE( T, b-10, b-0, b-2, b-2, 1, 10 )
625-
626-
TEST_RANGE( T, b-10, b-0, b-3, b-0, 4, 7 )
627-
TEST_RANGE( T, b-10, b-0, b-4, b-1, 4, 7 )
628-
TEST_RANGE( T, b-10, b-0, b-5, b-2, 4, 7 )
629-
630-
TEST_RANGE( T, b-10, b-1, b-0, b-0, 0, 10 )
631-
TEST_RANGE( T, b-10, b-1, b-1, b-0, 1, 9 )
632-
TEST_RANGE( T, b-10, b-1, b-1, b-1, 1, 9 )
633-
TEST_RANGE( T, b-10, b-1, b-2, b-1, 2, 8 )
634-
TEST_RANGE( T, b-10, b-1, b-2, b-2, 1, 9 )
635-
#endmacro
636-
637-
#macro TEST_RANGES()
638-
'' byte range edges and near zero
639-
TEST_RANGE_EDGES( byte, -128, 127 )
640-
TEST_RANGE_EDGES( byte, -2, 2 )
641-
TEST_RANGE_EDGES( ubyte, 0, 255 )
642-
643-
TEST_RANGE_EDGES( short, -129, 128 )
644-
TEST_RANGE_EDGES( short, -1, 256 )
645-
TEST_RANGE_EDGES( long, -129, 128 )
646-
TEST_RANGE_EDGES( long, -1, 256 )
647-
TEST_RANGE_EDGES( integer, -129, 128 )
648-
TEST_RANGE_EDGES( integer, -1, 256 )
649-
TEST_RANGE_EDGES( longint, -129, 128 )
650-
TEST_RANGE_EDGES( longint, -1, 256 )
651-
652-
'' short range edges and near zero
653-
TEST_RANGE_EDGES( short, -32768, 32767 )
654-
TEST_RANGE_EDGES( short, -2, 2 )
655-
TEST_RANGE_EDGES( ushort, 0, 65535 )
656-
657-
TEST_RANGE_EDGES( long, -32769, 32768 )
658-
TEST_RANGE_EDGES( long, 0, 65536 )
659-
TEST_RANGE_EDGES( integer, -32769, 32768 )
660-
TEST_RANGE_EDGES( integer, 0, 65536 )
661-
TEST_RANGE_EDGES( longint, -32769, 32768 )
662-
TEST_RANGE_EDGES( longint, 0, 65536 )
663-
664-
'' long range edges and near zero
665-
TEST_RANGE_EDGES( long, -2147483648, 2147483647 )
666-
TEST_RANGE_EDGES( long, -2, 2 )
667-
TEST_RANGE_EDGES( ulong, 0, 4294967295 )
668-
669-
TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll )
670-
TEST_RANGE_EDGES( longint, 0, 4294967296ll )
671-
672-
#ifdef __FB_64BIT__
673-
TEST_RANGE_EDGES( integer, -9223372036854775807ll-1ll, 9223372036854775807ll )
674-
TEST_RANGE_EDGES( integer, -2ll, 2ll )
675-
TEST_RANGE_EDGES( uinteger, 0, 18446744073709551615ull )
676-
#else
677-
TEST_RANGE_EDGES( integer, -2147483648, 2147483647 )
678-
TEST_RANGE_EDGES( integer, -2, 2 )
679-
TEST_RANGE_EDGES( uinteger, 0, 4294967295 )
680-
681-
TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll )
682-
TEST_RANGE_EDGES( longint, 0, 4294967296ll )
683-
#endif
684-
685-
'' longint range edges and near zero
686-
TEST_RANGE_EDGES( longint, -9223372036854775807ll-1ll, 9223372036854775807ll )
687-
TEST_RANGE_EDGES( longint, -2ll, 2ll )
688-
TEST_RANGE_EDGES( ulongint, 0, 18446744073709551615ull )
689-
#endmacro
690-
691-
'' Test Ranges using literal values
692-
#define LITERAL TRUE
693-
TEST_RANGES()
694-
695-
'' Test Ranges using a CONST symbol
696-
#undef LITERAL
697-
#define LITERAL FALSE
698-
TEST_RANGES()
699-
700-
END_TEST
701-
702567
END_SUITE

tests/compound/select_const2.bas

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# include "fbcunit.bi"
2+
3+
'' originally these tests were included in select_const.bas
4+
'' but due the nested macro expansion, the test as written
5+
'' in the gcc backend would generate a C listing 250K+ in length
6+
'' and is very taxing on gcc especially when optimizations and
7+
'' debug information is enabled. In some cases:
8+
'' - gcc (cc1) can run out of memory allocting debug symbols
9+
'' - gcc -O2 is really (really!) slow due that most of the
10+
'' test uses constant symbols and gcc chews away on optimizing
11+
'' for quite some time
12+
13+
'' split the test so we can modify test generation here separately
14+
15+
SUITE( fbc_tests.compound.select_const2 )
16+
17+
const FALSE = 0
18+
const TRUE = not FALSE
19+
20+
#macro TEST_RANGE( T, a, b, c_, d_, p, f )
21+
#if DEFINITION = TRUE
22+
__fb_uniqueid_push__( callstack )
23+
sub __fb_uniqueid__( callstack )
24+
dim as integer ok, nok
25+
ok = 0
26+
nok = 0
27+
dim v as T
28+
#if LITERAL
29+
#define c c_
30+
#define d d_
31+
#else
32+
const c as T = c_
33+
const d as T = d_
34+
#endif
35+
v = a
36+
do
37+
select case as const v
38+
case (c) to (d)
39+
CU_ASSERT( (v>=(c)) and (v<=(d)) )
40+
ok += 1
41+
case else
42+
CU_ASSERT( not ((v>=(c)) and (v<=(d))) )
43+
nok += 1
44+
end select
45+
if( v = b ) then
46+
exit do
47+
end if
48+
v += 1
49+
loop
50+
CU_ASSERT_EQUAL( p, ok )
51+
CU_ASSERT_EQUAL( f, nok )
52+
end sub
53+
#else
54+
'' call the test - the order doesn't matter
55+
__fb_uniqueid__( callstack )()
56+
__fb_uniqueid_pop__( callstack )
57+
#endif
58+
#endmacro
59+
60+
#macro TEST_RANGE_EDGES( T, a, b )
61+
TEST_RANGE( T, a+0, a+10, a+0, a+0, 1, 10 )
62+
TEST_RANGE( T, a+0, a+10, a+0, a+1, 2, 9 )
63+
TEST_RANGE( T, a+0, a+10, a+1, a+1, 1, 10 )
64+
TEST_RANGE( T, a+0, a+10, a+1, a+2, 2, 9 )
65+
TEST_RANGE( T, a+0, a+10, a+2, a+2, 1, 10 )
66+
67+
TEST_RANGE( T, a+0, a+10, a+0, a+3, 4, 7 )
68+
TEST_RANGE( T, a+0, a+10, a+1, a+4, 4, 7 )
69+
TEST_RANGE( T, a+0, a+10, a+2, a+5, 4, 7 )
70+
71+
TEST_RANGE( T, a+1, a+10, a+0, a+0, 0, 10 )
72+
TEST_RANGE( T, a+1, a+10, a+0, a+1, 1, 9 )
73+
TEST_RANGE( T, a+1, a+10, a+1, a+1, 1, 9 )
74+
TEST_RANGE( T, a+1, a+10, a+1, a+2, 2, 8 )
75+
TEST_RANGE( T, a+1, a+10, a+2, a+2, 1, 9 )
76+
77+
TEST_RANGE( T, b-10, b-0, b-0, b-0, 1, 10 )
78+
TEST_RANGE( T, b-10, b-0, b-1, b-0, 2, 9 )
79+
TEST_RANGE( T, b-10, b-0, b-1, b-1, 1, 10 )
80+
TEST_RANGE( T, b-10, b-0, b-2, b-1, 2, 9 )
81+
TEST_RANGE( T, b-10, b-0, b-2, b-2, 1, 10 )
82+
83+
TEST_RANGE( T, b-10, b-0, b-3, b-0, 4, 7 )
84+
TEST_RANGE( T, b-10, b-0, b-4, b-1, 4, 7 )
85+
TEST_RANGE( T, b-10, b-0, b-5, b-2, 4, 7 )
86+
87+
TEST_RANGE( T, b-10, b-1, b-0, b-0, 0, 10 )
88+
TEST_RANGE( T, b-10, b-1, b-1, b-0, 1, 9 )
89+
TEST_RANGE( T, b-10, b-1, b-1, b-1, 1, 9 )
90+
TEST_RANGE( T, b-10, b-1, b-2, b-1, 2, 8 )
91+
TEST_RANGE( T, b-10, b-1, b-2, b-2, 1, 9 )
92+
#endmacro
93+
94+
#macro TEST_RANGES()
95+
'' byte range edges and near zero
96+
TEST_RANGE_EDGES( byte, -128, 127 )
97+
TEST_RANGE_EDGES( byte, -2, 2 )
98+
TEST_RANGE_EDGES( ubyte, 0, 255 )
99+
100+
TEST_RANGE_EDGES( short, -129, 128 )
101+
TEST_RANGE_EDGES( short, -1, 256 )
102+
TEST_RANGE_EDGES( long, -129, 128 )
103+
TEST_RANGE_EDGES( long, -1, 256 )
104+
TEST_RANGE_EDGES( integer, -129, 128 )
105+
TEST_RANGE_EDGES( integer, -1, 256 )
106+
TEST_RANGE_EDGES( longint, -129, 128 )
107+
TEST_RANGE_EDGES( longint, -1, 256 )
108+
109+
'' short range edges and near zero
110+
TEST_RANGE_EDGES( short, -32768, 32767 )
111+
TEST_RANGE_EDGES( short, -2, 2 )
112+
TEST_RANGE_EDGES( ushort, 0, 65535 )
113+
114+
TEST_RANGE_EDGES( long, -32769, 32768 )
115+
TEST_RANGE_EDGES( long, 0, 65536 )
116+
TEST_RANGE_EDGES( integer, -32769, 32768 )
117+
TEST_RANGE_EDGES( integer, 0, 65536 )
118+
TEST_RANGE_EDGES( longint, -32769, 32768 )
119+
TEST_RANGE_EDGES( longint, 0, 65536 )
120+
121+
'' long range edges and near zero
122+
TEST_RANGE_EDGES( long, -2147483648, 2147483647 )
123+
TEST_RANGE_EDGES( long, -2, 2 )
124+
TEST_RANGE_EDGES( ulong, 0, 4294967295 )
125+
126+
TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll )
127+
TEST_RANGE_EDGES( longint, 0, 4294967296ll )
128+
129+
#ifdef __FB_64BIT__
130+
TEST_RANGE_EDGES( integer, -9223372036854775807ll-1ll, 9223372036854775807ll )
131+
TEST_RANGE_EDGES( integer, -2ll, 2ll )
132+
TEST_RANGE_EDGES( uinteger, 0, 18446744073709551615ull )
133+
#else
134+
TEST_RANGE_EDGES( integer, -2147483648, 2147483647 )
135+
TEST_RANGE_EDGES( integer, -2, 2 )
136+
TEST_RANGE_EDGES( uinteger, 0, 4294967295 )
137+
138+
TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll )
139+
TEST_RANGE_EDGES( longint, 0, 4294967296ll )
140+
#endif
141+
142+
'' longint range edges and near zero
143+
TEST_RANGE_EDGES( longint, -9223372036854775807ll-1ll, 9223372036854775807ll )
144+
TEST_RANGE_EDGES( longint, -2ll, 2ll )
145+
TEST_RANGE_EDGES( ulongint, 0, 18446744073709551615ull )
146+
#endmacro
147+
148+
'' generate tests for Test Ranges using literal values
149+
#define LITERAL TRUE
150+
#undef DEFINITION
151+
#define DEFINITION TRUE
152+
TEST_RANGES()
153+
154+
'' call the tests - the order doesn't matter, only that we use & call
155+
'' the correct number of calls from the callstack
156+
#undef DEFINITION
157+
#define DEFINITION FALSE
158+
TEST( RangeEdges_literal )
159+
TEST_RANGES()
160+
END_TEST
161+
162+
'' generate tests for Test Ranges using a CONST symbol
163+
#undef LITERAL
164+
#define LITERAL FALSE
165+
#undef DEFINITION
166+
#define DEFINITION TRUE
167+
TEST_RANGES()
168+
169+
'' call the tests - the order doesn't matter, only that we use & call
170+
'' the correct number of calls from the callstack
171+
#undef DEFINITION
172+
#define DEFINITION FALSE
173+
TEST( RangeEdges_const )
174+
TEST_RANGES()
175+
END_TEST
176+
177+
END_SUITE

0 commit comments

Comments
 (0)