From 4d19e26c0c36b7ef090a308a068f17e74fea1298 Mon Sep 17 00:00:00 2001 From: coderJeff Date: Mon, 26 Apr 2021 18:35:27 -0400 Subject: [PATCH 1/5] fbc-tests: split tests/compound/select_const.bas in to 2 test files - prepare for changes to the select const tests causing problems compiling with the gcc backend - the test will generate a very large C listing (250K+ LOC with debugging enabled) with most of the asserts in a single procedure - with debug symbols enabled, gcc can run out of memory overflowing the symbol hash tables - and the test is very taxing on the gcc optimizer (-O1 or higher) resulting in a very slow compile time --- tests/compound/select_const.bas | 135 --------------------------- tests/compound/select_const2.bas | 155 +++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 135 deletions(-) create mode 100644 tests/compound/select_const2.bas diff --git a/tests/compound/select_const.bas b/tests/compound/select_const.bas index f079530894..1fdc4f0c14 100644 --- a/tests/compound/select_const.bas +++ b/tests/compound/select_const.bas @@ -564,139 +564,4 @@ SUITE( fbc_tests.compound.select_const ) END_TEST - TEST( RangeEdges ) - - dim as integer ok, nok - - #macro TEST_RANGE( T, a, b, c_, d_, p, f ) - scope - ok = 0 - nok = 0 - dim v as T - #if LITERAL - #define c c_ - #define d d_ - #else - const c as T = c_ - const d as T = d_ - #endif - v = a - do - select case as const v - case (c) to (d) - CU_ASSERT( (v>=(c)) and (v<=(d)) ) - ok += 1 - case else - CU_ASSERT( not ((v>=(c)) and (v<=(d))) ) - nok += 1 - end select - if( v = b ) then - exit do - end if - v += 1 - loop - CU_ASSERT_EQUAL( p, ok ) - CU_ASSERT_EQUAL( f, nok ) - end scope - #endmacro - - #macro TEST_RANGE_EDGES( T, a, b ) - TEST_RANGE( T, a+0, a+10, a+0, a+0, 1, 10 ) - TEST_RANGE( T, a+0, a+10, a+0, a+1, 2, 9 ) - TEST_RANGE( T, a+0, a+10, a+1, a+1, 1, 10 ) - TEST_RANGE( T, a+0, a+10, a+1, a+2, 2, 9 ) - TEST_RANGE( T, a+0, a+10, a+2, a+2, 1, 10 ) - - TEST_RANGE( T, a+0, a+10, a+0, a+3, 4, 7 ) - TEST_RANGE( T, a+0, a+10, a+1, a+4, 4, 7 ) - TEST_RANGE( T, a+0, a+10, a+2, a+5, 4, 7 ) - - TEST_RANGE( T, a+1, a+10, a+0, a+0, 0, 10 ) - TEST_RANGE( T, a+1, a+10, a+0, a+1, 1, 9 ) - TEST_RANGE( T, a+1, a+10, a+1, a+1, 1, 9 ) - TEST_RANGE( T, a+1, a+10, a+1, a+2, 2, 8 ) - TEST_RANGE( T, a+1, a+10, a+2, a+2, 1, 9 ) - - TEST_RANGE( T, b-10, b-0, b-0, b-0, 1, 10 ) - TEST_RANGE( T, b-10, b-0, b-1, b-0, 2, 9 ) - TEST_RANGE( T, b-10, b-0, b-1, b-1, 1, 10 ) - TEST_RANGE( T, b-10, b-0, b-2, b-1, 2, 9 ) - TEST_RANGE( T, b-10, b-0, b-2, b-2, 1, 10 ) - - TEST_RANGE( T, b-10, b-0, b-3, b-0, 4, 7 ) - TEST_RANGE( T, b-10, b-0, b-4, b-1, 4, 7 ) - TEST_RANGE( T, b-10, b-0, b-5, b-2, 4, 7 ) - - TEST_RANGE( T, b-10, b-1, b-0, b-0, 0, 10 ) - TEST_RANGE( T, b-10, b-1, b-1, b-0, 1, 9 ) - TEST_RANGE( T, b-10, b-1, b-1, b-1, 1, 9 ) - TEST_RANGE( T, b-10, b-1, b-2, b-1, 2, 8 ) - TEST_RANGE( T, b-10, b-1, b-2, b-2, 1, 9 ) - #endmacro - - #macro TEST_RANGES() - '' byte range edges and near zero - TEST_RANGE_EDGES( byte, -128, 127 ) - TEST_RANGE_EDGES( byte, -2, 2 ) - TEST_RANGE_EDGES( ubyte, 0, 255 ) - - TEST_RANGE_EDGES( short, -129, 128 ) - TEST_RANGE_EDGES( short, -1, 256 ) - TEST_RANGE_EDGES( long, -129, 128 ) - TEST_RANGE_EDGES( long, -1, 256 ) - TEST_RANGE_EDGES( integer, -129, 128 ) - TEST_RANGE_EDGES( integer, -1, 256 ) - TEST_RANGE_EDGES( longint, -129, 128 ) - TEST_RANGE_EDGES( longint, -1, 256 ) - - '' short range edges and near zero - TEST_RANGE_EDGES( short, -32768, 32767 ) - TEST_RANGE_EDGES( short, -2, 2 ) - TEST_RANGE_EDGES( ushort, 0, 65535 ) - - TEST_RANGE_EDGES( long, -32769, 32768 ) - TEST_RANGE_EDGES( long, 0, 65536 ) - TEST_RANGE_EDGES( integer, -32769, 32768 ) - TEST_RANGE_EDGES( integer, 0, 65536 ) - TEST_RANGE_EDGES( longint, -32769, 32768 ) - TEST_RANGE_EDGES( longint, 0, 65536 ) - - '' long range edges and near zero - TEST_RANGE_EDGES( long, -2147483648, 2147483647 ) - TEST_RANGE_EDGES( long, -2, 2 ) - TEST_RANGE_EDGES( ulong, 0, 4294967295 ) - - TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll ) - TEST_RANGE_EDGES( longint, 0, 4294967296ll ) - - #ifdef __FB_64BIT__ - TEST_RANGE_EDGES( integer, -9223372036854775807ll-1ll, 9223372036854775807ll ) - TEST_RANGE_EDGES( integer, -2ll, 2ll ) - TEST_RANGE_EDGES( uinteger, 0, 18446744073709551615ull ) - #else - TEST_RANGE_EDGES( integer, -2147483648, 2147483647 ) - TEST_RANGE_EDGES( integer, -2, 2 ) - TEST_RANGE_EDGES( uinteger, 0, 4294967295 ) - - TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll ) - TEST_RANGE_EDGES( longint, 0, 4294967296ll ) - #endif - - '' longint range edges and near zero - TEST_RANGE_EDGES( longint, -9223372036854775807ll-1ll, 9223372036854775807ll ) - TEST_RANGE_EDGES( longint, -2ll, 2ll ) - TEST_RANGE_EDGES( ulongint, 0, 18446744073709551615ull ) - #endmacro - - '' Test Ranges using literal values - #define LITERAL TRUE - TEST_RANGES() - - '' Test Ranges using a CONST symbol - #undef LITERAL - #define LITERAL FALSE - TEST_RANGES() - - END_TEST - END_SUITE diff --git a/tests/compound/select_const2.bas b/tests/compound/select_const2.bas new file mode 100644 index 0000000000..eacbb71619 --- /dev/null +++ b/tests/compound/select_const2.bas @@ -0,0 +1,155 @@ +# include "fbcunit.bi" + +'' originally these tests were included in select_const.bas +'' but due the nested macro expansion, the test as written +'' in the gcc backend would generate a C listing 250K+ in length +'' and is very taxing on gcc especially when optimizations and +'' debug information is enabled. In some cases: +'' - gcc (cc1) can run out of memory allocting debug symbols +'' - gcc -O2 is really (really!) slow due that most of the +'' test uses constant symbols and gcc chews away on optimizing +'' for quite some time + +'' split the test so we can modify test generation here separately + +SUITE( fbc_tests.compound.select_const ) + + const FALSE = 0 + const TRUE = not FALSE + + TEST( RangeEdges ) + + dim as integer ok, nok + + #macro TEST_RANGE( T, a, b, c_, d_, p, f ) + scope + ok = 0 + nok = 0 + dim v as T + #if LITERAL + #define c c_ + #define d d_ + #else + const c as T = c_ + const d as T = d_ + #endif + v = a + do + select case as const v + case (c) to (d) + CU_ASSERT( (v>=(c)) and (v<=(d)) ) + ok += 1 + case else + CU_ASSERT( not ((v>=(c)) and (v<=(d))) ) + nok += 1 + end select + if( v = b ) then + exit do + end if + v += 1 + loop + CU_ASSERT_EQUAL( p, ok ) + CU_ASSERT_EQUAL( f, nok ) + end scope + #endmacro + + #macro TEST_RANGE_EDGES( T, a, b ) + TEST_RANGE( T, a+0, a+10, a+0, a+0, 1, 10 ) + TEST_RANGE( T, a+0, a+10, a+0, a+1, 2, 9 ) + TEST_RANGE( T, a+0, a+10, a+1, a+1, 1, 10 ) + TEST_RANGE( T, a+0, a+10, a+1, a+2, 2, 9 ) + TEST_RANGE( T, a+0, a+10, a+2, a+2, 1, 10 ) + + TEST_RANGE( T, a+0, a+10, a+0, a+3, 4, 7 ) + TEST_RANGE( T, a+0, a+10, a+1, a+4, 4, 7 ) + TEST_RANGE( T, a+0, a+10, a+2, a+5, 4, 7 ) + + TEST_RANGE( T, a+1, a+10, a+0, a+0, 0, 10 ) + TEST_RANGE( T, a+1, a+10, a+0, a+1, 1, 9 ) + TEST_RANGE( T, a+1, a+10, a+1, a+1, 1, 9 ) + TEST_RANGE( T, a+1, a+10, a+1, a+2, 2, 8 ) + TEST_RANGE( T, a+1, a+10, a+2, a+2, 1, 9 ) + + TEST_RANGE( T, b-10, b-0, b-0, b-0, 1, 10 ) + TEST_RANGE( T, b-10, b-0, b-1, b-0, 2, 9 ) + TEST_RANGE( T, b-10, b-0, b-1, b-1, 1, 10 ) + TEST_RANGE( T, b-10, b-0, b-2, b-1, 2, 9 ) + TEST_RANGE( T, b-10, b-0, b-2, b-2, 1, 10 ) + + TEST_RANGE( T, b-10, b-0, b-3, b-0, 4, 7 ) + TEST_RANGE( T, b-10, b-0, b-4, b-1, 4, 7 ) + TEST_RANGE( T, b-10, b-0, b-5, b-2, 4, 7 ) + + TEST_RANGE( T, b-10, b-1, b-0, b-0, 0, 10 ) + TEST_RANGE( T, b-10, b-1, b-1, b-0, 1, 9 ) + TEST_RANGE( T, b-10, b-1, b-1, b-1, 1, 9 ) + TEST_RANGE( T, b-10, b-1, b-2, b-1, 2, 8 ) + TEST_RANGE( T, b-10, b-1, b-2, b-2, 1, 9 ) + #endmacro + + #macro TEST_RANGES() + '' byte range edges and near zero + TEST_RANGE_EDGES( byte, -128, 127 ) + TEST_RANGE_EDGES( byte, -2, 2 ) + TEST_RANGE_EDGES( ubyte, 0, 255 ) + + TEST_RANGE_EDGES( short, -129, 128 ) + TEST_RANGE_EDGES( short, -1, 256 ) + TEST_RANGE_EDGES( long, -129, 128 ) + TEST_RANGE_EDGES( long, -1, 256 ) + TEST_RANGE_EDGES( integer, -129, 128 ) + TEST_RANGE_EDGES( integer, -1, 256 ) + TEST_RANGE_EDGES( longint, -129, 128 ) + TEST_RANGE_EDGES( longint, -1, 256 ) + + '' short range edges and near zero + TEST_RANGE_EDGES( short, -32768, 32767 ) + TEST_RANGE_EDGES( short, -2, 2 ) + TEST_RANGE_EDGES( ushort, 0, 65535 ) + + TEST_RANGE_EDGES( long, -32769, 32768 ) + TEST_RANGE_EDGES( long, 0, 65536 ) + TEST_RANGE_EDGES( integer, -32769, 32768 ) + TEST_RANGE_EDGES( integer, 0, 65536 ) + TEST_RANGE_EDGES( longint, -32769, 32768 ) + TEST_RANGE_EDGES( longint, 0, 65536 ) + + '' long range edges and near zero + TEST_RANGE_EDGES( long, -2147483648, 2147483647 ) + TEST_RANGE_EDGES( long, -2, 2 ) + TEST_RANGE_EDGES( ulong, 0, 4294967295 ) + + TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll ) + TEST_RANGE_EDGES( longint, 0, 4294967296ll ) + + #ifdef __FB_64BIT__ + TEST_RANGE_EDGES( integer, -9223372036854775807ll-1ll, 9223372036854775807ll ) + TEST_RANGE_EDGES( integer, -2ll, 2ll ) + TEST_RANGE_EDGES( uinteger, 0, 18446744073709551615ull ) + #else + TEST_RANGE_EDGES( integer, -2147483648, 2147483647 ) + TEST_RANGE_EDGES( integer, -2, 2 ) + TEST_RANGE_EDGES( uinteger, 0, 4294967295 ) + + TEST_RANGE_EDGES( longint, -2147483649ll, 2147483648ll ) + TEST_RANGE_EDGES( longint, 0, 4294967296ll ) + #endif + + '' longint range edges and near zero + TEST_RANGE_EDGES( longint, -9223372036854775807ll-1ll, 9223372036854775807ll ) + TEST_RANGE_EDGES( longint, -2ll, 2ll ) + TEST_RANGE_EDGES( ulongint, 0, 18446744073709551615ull ) + #endmacro + + '' Test Ranges using literal values + #define LITERAL TRUE + TEST_RANGES() + + '' Test Ranges using a CONST symbol + #undef LITERAL + #define LITERAL FALSE + TEST_RANGES() + + END_TEST + +END_SUITE From 2343df4dc70f83ec461bab8e7167c2706be1f8d9 Mon Sep 17 00:00:00 2001 From: coderJeff Date: Mon, 26 Apr 2021 18:39:21 -0400 Subject: [PATCH 2/5] fbc-tests: split tests/compound/select_const.bas in to 2 test files - prepare for changes to the select const tests causing problems compiling with the gcc backend - the test will generate a very large C listing (250K+ LOC with debugging enabled) with most of the asserts in a single procedure - with debug symbols enabled, gcc can run out of memory overflowing the symbol hash tables - and the test is very taxing on the gcc optimizer (-O1 or higher) resulting in a very slow compile time --- tests/compound/select_const2.bas | 64 +++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/tests/compound/select_const2.bas b/tests/compound/select_const2.bas index eacbb71619..1b27ea8879 100644 --- a/tests/compound/select_const2.bas +++ b/tests/compound/select_const2.bas @@ -12,17 +12,16 @@ '' split the test so we can modify test generation here separately -SUITE( fbc_tests.compound.select_const ) +SUITE( fbc_tests.compound.select_const2 ) const FALSE = 0 const TRUE = not FALSE - TEST( RangeEdges ) - - dim as integer ok, nok - - #macro TEST_RANGE( T, a, b, c_, d_, p, f ) - scope + #macro TEST_RANGE( T, a, b, c_, d_, p, f ) + #if DEFINITION = TRUE + __fb_uniqueid_push__( callstack ) + sub __fb_uniqueid__( callstack ) + dim as integer ok, nok ok = 0 nok = 0 dim v as T @@ -50,10 +49,15 @@ SUITE( fbc_tests.compound.select_const ) loop CU_ASSERT_EQUAL( p, ok ) CU_ASSERT_EQUAL( f, nok ) - end scope - #endmacro - - #macro TEST_RANGE_EDGES( T, a, b ) + end sub + #else + '' call the test - the order doesn't matter + __fb_uniqueid__( callstack )() + __fb_uniqueid_pop__( callstack ) + #endif + #endmacro + + #macro TEST_RANGE_EDGES( T, a, b ) TEST_RANGE( T, a+0, a+10, a+0, a+0, 1, 10 ) TEST_RANGE( T, a+0, a+10, a+0, a+1, 2, 9 ) TEST_RANGE( T, a+0, a+10, a+1, a+1, 1, 10 ) @@ -85,9 +89,9 @@ SUITE( fbc_tests.compound.select_const ) TEST_RANGE( T, b-10, b-1, b-1, b-1, 1, 9 ) TEST_RANGE( T, b-10, b-1, b-2, b-1, 2, 8 ) TEST_RANGE( T, b-10, b-1, b-2, b-2, 1, 9 ) - #endmacro + #endmacro - #macro TEST_RANGES() + #macro TEST_RANGES() '' byte range edges and near zero TEST_RANGE_EDGES( byte, -128, 127 ) TEST_RANGE_EDGES( byte, -2, 2 ) @@ -139,17 +143,35 @@ SUITE( fbc_tests.compound.select_const ) TEST_RANGE_EDGES( longint, -9223372036854775807ll-1ll, 9223372036854775807ll ) TEST_RANGE_EDGES( longint, -2ll, 2ll ) TEST_RANGE_EDGES( ulongint, 0, 18446744073709551615ull ) - #endmacro - - '' Test Ranges using literal values - #define LITERAL TRUE + #endmacro + + '' generate tests for Test Ranges using literal values + #define LITERAL TRUE + #undef DEFINITION + #define DEFINITION TRUE + TEST_RANGES() + + '' call the tests - the order doesn't matter, only that we use & call + '' the correct number of calls from the callstack + #undef DEFINITION + #define DEFINITION FALSE + TEST( RangeEdges_literal ) TEST_RANGES() + END_TEST - '' Test Ranges using a CONST symbol - #undef LITERAL - #define LITERAL FALSE + '' generate tests for Test Ranges using a CONST symbol + #undef LITERAL + #define LITERAL FALSE + #undef DEFINITION + #define DEFINITION TRUE + TEST_RANGES() + + '' call the tests - the order doesn't matter, only that we use & call + '' the correct number of calls from the callstack + #undef DEFINITION + #define DEFINITION FALSE + TEST( RangeEdges_const ) TEST_RANGES() - END_TEST END_SUITE From d15165a3a5d3b95c56ad1fa905f65c71f556bdc4 Mon Sep 17 00:00:00 2001 From: coderJeff Date: Mon, 26 Apr 2021 18:15:12 -0400 Subject: [PATCH 3/5] fbc: allow command line options passed to as, gcc, ld to be longer than 128 characters - fixes github # 298: -Wc has a limit of 128 characters - previously fbc used fixed length strings of 128 bytes to hold the options to as, gcc, and ld - now uses variable length string instead --- changelog.txt | 1 + src/compiler/fbc.bas | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index ea4f1e00ee..8d6f3b2a1c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -45,6 +45,7 @@ Version 1.08.0 - github #203: allow casts of addresses on static initializers - only write debug line information for statements and don't write comments / empty lines / directives for top level source code in assembly debug ouput - 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. +- github #298: allow command line options passed to as, gcc, ld to be longer than 128 characters by using string types internally [added] - extern "rtlib": respects the parent namespace, uses default fb calling convention and C style name mangling diff --git a/src/compiler/fbc.bas b/src/compiler/fbc.bas index d69f7e27ae..2754503c25 100644 --- a/src/compiler/fbc.bas +++ b/src/compiler/fbc.bas @@ -25,9 +25,9 @@ enum end enum type FBC_EXTOPT - gas as zstring * 128 - ld as zstring * 128 - gcc as zstring * 128 + gas as string + ld as string + gcc as string end type type FBCIOFILE From 44adf4f2794b790d308a022e6880038155964a61 Mon Sep 17 00:00:00 2001 From: coderJeff Date: Mon, 26 Apr 2021 18:29:33 -0400 Subject: [PATCH 4/5] C backend: fix array out of bounds warning when compiled with -O2 or higher optimizations - see github # 217 - warning: array subscript -1 is outside array bounds - caused by fbc's optimization of non-zero lower bound arrays - fbc calculates a kind of virtual pointer of where the array(0,..) element would be and then computes element addresses from that - this optimization in fbc saves some computations when accessing array elements but the translation to C is technically undefined behaviour - fixed (for now) by casting the address to the equivalent of intptr_t in C. (FB_DATATYPE_INTEGER). --- changelog.txt | 1 + src/compiler/ir-hlc.bas | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8d6f3b2a1c..4651d9bef2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -133,6 +133,7 @@ Version 1.08.0 - fix __FB_EVAL__() incorrectly reading past the end of the expression, and report errors in expressions - 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 - 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). +- 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 Version 1.07.0 diff --git a/src/compiler/ir-hlc.bas b/src/compiler/ir-hlc.bas index f0a8eff312..8508831874 100644 --- a/src/compiler/ir-hlc.bas +++ b/src/compiler/ir-hlc.bas @@ -2678,8 +2678,23 @@ private function exprNewVREG _ l = exprNewUOP( AST_OP_ADDROF, l ) end if if( have_offset ) then - '' Cast to ubyte ptr to work around C's pointer arithmetic - l = exprNewCAST( typeAddrOf( FB_DATATYPE_UBYTE ), NULL, l ) + if( is_c_array ) then + '' Cast to intptr_t to work around gcc out side of array bounds + '' warnings if we are casting from FBSTRING array to pointer + '' fbc uses a kind of virtual pointer for the an array's (0,..) + '' index; technically this is undefinded behaviour in C and is + '' impossible to cast away even when using pointer only casts + '' in the same expression. Some gcc optimizations cause a + '' a warning when setting a pointer for the array's virtual + '' index location. To fix this for compliant C code, would + '' need to rewrite the array descriptor to contain only the + '' offset value from actual memory pointer and compute the + '' array access fully on each array element access. + l = exprNewCAST( FB_DATATYPE_INTEGER, NULL, l ) + else + '' Cast to ubyte ptr to work around C's pointer arithmetic + l = exprNewCAST( typeAddrOf( FB_DATATYPE_UBYTE ), NULL, l ) + end if if( vreg->vidx <> NULL ) then l = exprNewBOP( AST_OP_ADD, l, exprNewVREG( vreg->vidx ) ) end if From 224012014c52a79903f0a333d5af500f1b51076d Mon Sep 17 00:00:00 2001 From: coderJeff Date: Mon, 26 Apr 2021 19:11:51 -0400 Subject: [PATCH 5/5] 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 - gcc requires a valid stack to preserve registers and if the asm code clobbers esp/rsp then there is no way to get it back after esp/rsp changes to something else. - User is always responsoble for handling the stack registers. --- changelog.txt | 1 + src/compiler/ir-hlc.bas | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4651d9bef2..8c11fa09e7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -134,6 +134,7 @@ Version 1.08.0 - 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 - 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). - 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 +- 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 Version 1.07.0 diff --git a/src/compiler/ir-hlc.bas b/src/compiler/ir-hlc.bas index 8508831874..cb1ba54ff7 100644 --- a/src/compiler/ir-hlc.bas +++ b/src/compiler/ir-hlc.bas @@ -3572,15 +3572,20 @@ private sub _emitAsmLine( byval asmtokenhead as ASTASMTOK ptr ) ln += " : " + inputconstraints '' We don't know what registers etc. will be trashed, - '' so assume everything... + '' so assume everything... except for rsp/esp - gcc requires a valid + '' stack to preserve registers and if the asm code clobbers esp/rsp + '' then there is no way to get it back after esp/rsp changes to + '' something else. User is always responsible for handling the stack + '' registers. + '' ln += " : ""cc"", ""memory""" select case( fbGetCpuFamily( ) ) case FB_CPUFAMILY_X86, FB_CPUFAMILY_X86_64 if( fbGetCpuFamily( ) = FB_CPUFAMILY_X86 ) then - ln += ", ""eax"", ""ebx"", ""ecx"", ""edx"", ""esp"", ""edi"", ""esi""" + ln += ", ""eax"", ""ebx"", ""ecx"", ""edx"", ""edi"", ""esi""" else - ln += ", ""rax"", ""rbx"", ""rcx"", ""rdx"", ""rsp"", ""rdi"", ""rsi""" + ln += ", ""rax"", ""rbx"", ""rcx"", ""rdx"", ""rdi"", ""rsi""" ln += ", ""r8"", ""r9"", ""r10"", ""r11"", ""r12"", ""r13"", ""r14"", ""r15""" end if