Emmanuel Deloget | 28 Apr 02:21 2015
Picon

cross-compilation of tcc fails

Hello, 

I'm cross-compiling tcc to create a native ARM compiler for an ARM platform 
and noticed that this is just not possible with the current build scripts. 

$ ./configure --cpu=armv7a --cross-prefix=arm-openwrt-linux-muslgnueabi-

The problem happens when the system tries to compile a native library:

  make -C lib native
  make[1]: Entering directory '/home/me/tcc-2015-04-28/lib'
  mkdir -p arm
  ../tcc -B.. -c libtcc1.c -o arm/libtcc1.o -I..  -fPIC -DTCC_TARGET_ARM
  ../tcc: 1: ../tcc: Syntax error: word unexpected (expecting ")")

(I spare you tons of lines ; I'm integrating tcc as an openwrt package as I 
don't want to build my own toolchain).

Now, the error is perfectly logical, as tcc is: 

  $ file tcc
  tcc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, 
  interpreter /lib/ld-musl-arm.so.1, not stripped

it's not going to run. 

I'm more or less stick here: either I create cross-compilers and the library is built using the cross compilers (but that don't help much, as the cross-compiler will not run on my target host) or I build a cross-compiled native tcc but then I cannot compile the library. 

Unfortunately, I cannot build tcc for arm and rebuild it (with its native library) on the target host.

So, question: what would be a good way to remove that deadly lock ? 

A) when cross-compiling, build the corresponding cross-compiler to build the library? That ould require to either have more configure switch or to detect the target arch from the cross-prefix (this is not always possible). 

B) use the cross-compiler to built the target library? it should not be difficult but I'm not sure that a good thing. 

C) something I haven't said yet?

Best regards, 

-- Emmanuel Deloget

<div><div dir="ltr">
<div class="gmail_default">Hello,&nbsp;</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">I'm cross-compiling tcc to create a native ARM compiler for an ARM platform&nbsp;</div>
<div class="gmail_default">and noticed that this is just not possible with the current build scripts.&nbsp;</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">$ ./configure --cpu=armv7a --cross-prefix=arm-openwrt-linux-muslgnueabi-≤br>
</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">The problem happens when the system tries to compile a native library:</div>
<div class="gmail_default"><br></div>
<div class="gmail_default">
<div class="gmail_default">&nbsp; make -C lib native</div>
<div class="gmail_default">&nbsp; make[1]: Entering directory '/home/me/tcc-2015-04-28/lib'</div>
<div class="gmail_default">&nbsp; mkdir -p arm</div>
<div class="gmail_default">&nbsp; ../tcc -B.. -c libtcc1.c -o arm/libtcc1.o -I.. &nbsp;-fPIC -DTCC_TARGET_ARM</div>
<div class="gmail_default">&nbsp; ../tcc: 1: ../tcc: Syntax error: word unexpected (expecting ")")</div>
<div><br></div>
<div>(I spare you tons of lines ; I'm integrating tcc as an openwrt package as I&nbsp;</div>
<div>don't want to build my own toolchain).</div>
<div><br></div>
<div>Now, the error is perfectly logical, as tcc is:&nbsp;</div>
<div><br></div>
<div>&nbsp; $ file tcc</div>
<div>&nbsp; tcc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked,&nbsp;</div>
<div>&nbsp; interpreter /lib/ld-musl-arm.so.1, not stripped<br>
</div>
<div><br></div>
<div>it's not going to run.&nbsp;</div>
<div><br></div>
<div>I'm more or less stick here: either I create cross-compilers and the library is built using the cross compilers (but that don't help much, as the cross-compiler will not run on my target host) or I build a cross-compiled native tcc but then I cannot compile the library.&nbsp;</div>
<div><br></div>
<div>Unfortunately, I cannot build tcc for arm and rebuild it (with its native library) on the target host.</div>
<div><br></div>
<div>So, question: what would be a good way to remove that deadly lock ?&nbsp;</div>
<div><br></div>
<div>A) when cross-compiling, build the corresponding cross-compiler to build the library? That ould require to either have more configure switch or to detect the target arch from the cross-prefix (this is not always possible).&nbsp;</div>
<div><br></div>
<div>B) use the cross-compiler to built the target library? it should not be difficult but I'm not sure that a good thing.&nbsp;</div>
<div><br></div>
<div>C) something I haven't said yet?</div>
<div><br></div>
<div>Best regards,&nbsp;</div>
<div><br></div>
<div>-- Emmanuel Deloget</div>
<div><br></div>
</div>
</div></div>
Sergey Korshunoff | 26 Apr 04:48 2015
Picon

tcc-kernel-2.4.26.tar.bz2

An archive contains scripts to build a linux kernel  2.4.26 with the
current tcc.
Attachment (tcc-kernel-2.4.26.tar.bz2): application/x-bzip2, 67 KiB
An archive contains scripts to build a linux kernel  2.4.26 with the
current tcc.
Pip Cet | 25 Apr 21:09 2015
Picon

x86_64 ABI: mixed structs

I've just committed two tests for the x86_64 ELF ABI which currently
fail, because we don't deal properly with mixed structures along the
lines of

struct {
    double x;
    long y;
};

Such structs should be split and passed in an SSE register plus an
integer register, which the current approach, assigning VT_QFLOAT or
VT_QLONG as structure type, fails to deal with.

I think I've got most of what's needed for a fix here, but the change
involves rewriting a little of the x86_64 code; a less intrusive fix
would be preferred, I think.

I'll try isolating this from my other changes and coming up with a patch.

Pip Cet | 24 Apr 11:07 2015
Picon

VLAs broken on mob branch

Hi,
as far as I can tell, VLAs are currently broken. If you apply this
patch to the source code (adding a useless VLA to the TCC code
itself), make test dies with a segmentation fault (on x86-64, Linux):

diff --git a/x86_64-gen.c b/x86_64-gen.c
index d837a1d..593dd91 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
 <at>  <at>  -1186,6 +1186,7  <at>  <at>  void gfunc_call(int nb_args)
     int size, align, r, args_size, stack_adjust, run_start, run_end,
i, reg_count;
     int nb_reg_args = 0;
     int nb_sse_args = 0;
+    int offsets[nb_args*nb_args+1];
     int sse_reg, gen_reg;

     /* calculate the number of integer/float register arguments */

I've tried fixing it. So far all I have is a patch that appears to
make the problem go away, but that I don't fully understand. If anyone
who actually understands the VLA code could have a look, that would be
very much appreciated. I include the patch mostly for reasons of
completeness, since it's probably very different from any actual fix:

diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags,
*orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int
*case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ?
&vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags
& VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type,
Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();

Attachment tcc-break-vlas.diff is the change that causes the segfault;
attachment tcc-notafix.diff is the half-understood patch that "fixes"
things.
diff --git a/x86_64-gen.c b/x86_64-gen.c
index d837a1d..593dd91 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
 <at>  <at>  -1186,6 +1186,7  <at>  <at>  void gfunc_call(int nb_args)
     int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count;
     int nb_reg_args = 0;
     int nb_sse_args = 0;
+    int offsets[nb_args*nb_args+1];
     int sse_reg, gen_reg;

     /* calculate the number of integer/float register arguments */
diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ? &vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type, Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();
diff --git a/tccgen.c b/tccgen.c
index 103c955..afd610e 100644
--- a/tccgen.c
+++ b/tccgen.c
 <at>  <at>  -3479,7 +3479,7  <at>  <at>  static void post_type(CType *type, AttributeDef *ad)

             vla_runtime_type_size(type, &align);
             gen_op('*');
-            vset(&int_type, VT_LOCAL|VT_LVAL, loc);
+            vset(&int_type, VT_LOCAL|VT_LVAL, n);
             vswap();
             vstore();
         }
 <at>  <at>  -4804,7 +4804,7  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         gsym_addr(b, d);
     } else if (tok == '{') {
         Sym *llabel;
-        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
+        int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags, *orig_vla_sp_loc;

         next();
         /* record local declaration stack position */
 <at>  <at>  -4817,7 +4817,8  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* save VLA state */
         block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
         if (saved_vla_sp_loc != &vla_sp_root_loc)
-          vla_sp_loc = &block_vla_sp_loc;
+            vla_sp_loc = &block_vla_sp_loc;
+        orig_vla_sp_loc = vla_sp_loc;

         saved_vla_flags = vla_flags;
         vla_flags |= VLA_NEED_NEW_FRAME;
 <at>  <at>  -4873,10 +4874,10  <at>  <at>  static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
         /* Pop VLA frames and restore stack pointer if required */
         if (saved_vla_sp_loc != &vla_sp_root_loc)
             *saved_vla_sp_loc = block_vla_sp_loc;
-        if (vla_sp_loc != (saved_vla_sp_loc == &vla_sp_root_loc ? &vla_sp_root_loc : &block_vla_sp_loc)) {
-            vla_sp_loc = saved_vla_sp_loc;
-            gen_vla_sp_restore(*vla_sp_loc);
+        if (vla_sp_loc != orig_vla_sp_loc) {
+            gen_vla_sp_restore(*saved_vla_sp_loc);
         }
+        vla_sp_loc = saved_vla_sp_loc;
         vla_flags = (vla_flags & ~VLA_SCOPE_FLAGS) | (saved_vla_flags & VLA_SCOPE_FLAGS);

         next();
 <at>  <at>  -5458,6 +5459,7  <at>  <at>  static void decl_initializer(CType *type, Section *sec, unsigned long c,

         vla_runtime_type_size(type, &a);
         gen_vla_alloc(type, a);
+        vla_sp_save();
         vset(type, VT_LOCAL|VT_LVAL, c);
         vswap();
         vstore();
Ramsay Jones | 20 Apr 13:19 2015
Picon
Picon

Missing test for -fdollar-in-identifiers commit

Hi Sergey, Daniel,

I just pushed a quick fix for the missing test files to the mob branch.

Also, I noticed a slight difference between Daniel's patch and commit
5ce2154, which amounts to:

  diff --git a/tccasm.c b/tccasm.c
  index 3fa6f07..8f71846 100644
  --- a/tccasm.c
  +++ b/tccasm.c
   <at>  <at>  -853,6 +853,7  <at>  <at>  static void tcc_assemble_inline(TCCState *s1, char *str, int len)
       memcpy(file->buffer, str, len);

       macro_ptr = NULL;
  +    parse_flags |= PARSE_FLAG_ASM_FILE;
       tcc_assemble_internal(s1, 0);
       tcc_close();

  $ 

I don't have time to investigate further, so I will leave the issue
of the above difference for you to investigate.

Thanks!

ATB,
Ramsay Jones

Christian Jullien | 18 Apr 10:07 2015
Picon

can't relocate value at 2058898, 1 on RPi with last commit!

My TinyCC cron complains :

 

------------ hello-run ------------

./tcc -B.. -I.. -I.. -I../include -run ../examples/ex1.c Hello World

gcc -o libtcc_test libtcc_test.c ../libtcc.a -I..   -DCONFIG_MULTIARCHDIR="\"arm-linux-gnueabihf\"" -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT -DTCC_ARM_VFP -lm -ldl   -I..

------------ libtest ------------

./libtcc_test lib_path=..

tcc: error: can't relocate value at 2058898,1

Makefile:99: recipe for target 'libtest' failed

make[1]: *** [libtest] Error 1

 

<div><div class="WordSection1">
<p class="MsoNormal"><span lang="FR">My TinyCC cron complains&nbsp;:<p></p></span></p>
<p class="MsoNormal"><span lang="FR"><p>&nbsp;</p></span></p>
<p class="MsoPlainText">------------ hello-run ------------<p></p></p>
<p class="MsoPlainText">./tcc -B.. -I.. -I.. -I../include -run ../examples/ex1.c Hello World<p></p></p>
<p class="MsoPlainText">gcc -o libtcc_test libtcc_test.c ../libtcc.a -I..&nbsp;&nbsp; -DCONFIG_MULTIARCHDIR="\"arm-linux-gnueabihf\"" -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT -DTCC_ARM_VFP -lm -ldl&nbsp;&nbsp; -I..<p></p></p>
<p class="MsoPlainText">------------ libtest ------------<p></p></p>
<p class="MsoPlainText">./libtcc_test lib_path=..<p></p></p>
<p class="MsoPlainText">tcc: error: can't relocate value at 2058898,1<p></p></p>
<p class="MsoPlainText">Makefile:99: recipe for target 'libtest' failed<p></p></p>
<p class="MsoPlainText">make[1]: *** [libtest] Error 1<p></p></p>
<p class="MsoNormal"><span lang="FR"><p>&nbsp;</p></span></p>
</div></div>
Steven G. Messervey | 16 Apr 05:06 2015
Picon

#pragma comment(lib,...)

Hello,

  Re-pushed a series of changes that add #pragma comment(lib,””) functionality.

These changes keep the prior default behavior of silently ignoring unknown #pragma directives.

 

Tested on:

MINGW32_NT-6.1 PROBOOK-6545-1 1.0.17(0.48/3/2) 2011-04-24 23:39 i686 Msys  (X86-64)

Linux sgmtech 3.2.0-4-686-pae #1 SMP Debian 3.2.65-1+deb7u2 i686 GNU/Linux   (X86-32)

 

Thanks,

  Steven G.

<div><div class="WordSection1">
<p class="MsoNormal">Hello,<p></p></p>
<p class="MsoNormal">&nbsp; Re-pushed a series of changes that add #pragma comment(lib,&rdquo;&rdquo;) functionality.<p></p></p>
<p class="MsoNormal">These changes keep the prior default behavior of silently ignoring unknown #pragma directives.<p></p></p>
<p class="MsoNormal"><p>&nbsp;</p></p>
<p class="MsoNormal">Tested on:<p></p></p>
<p class="MsoNormal">MINGW32_NT-6.1 PROBOOK-6545-1 1.0.17(0.48/3/2) 2011-04-24 23:39 i686 Msys&nbsp; (X86-64)<p></p></p>
<p class="MsoNormal">Linux sgmtech 3.2.0-4-686-pae #1 SMP Debian 3.2.65-1+deb7u2 i686 GNU/Linux&nbsp;&nbsp; (X86-32)<p></p></p>
<p class="MsoNormal"><p>&nbsp;</p></p>
<p class="MsoNormal">Thanks,<p></p></p>
<p class="MsoNormal">&nbsp; Steven G.<p></p></p>
</div></div>
Roy Tam | 16 Apr 02:06 2015
Picon

rev 8615bb4 makes build become nosier

Hello list,

rev 8615bb4 makes tcc complaining #pragma push_macro and #pragma
pop_macro, please fix or silencing it.

Thanks.

Regards,
Roy

Christian JULLIEN | 15 Apr 14:02 2015
Picon

RE : #pragma push_macro(abort) && #pragma pop_macro(abort)

IMHO if not implemented it should not warn.

6.10.6 Pragma directive
Semantics

A preprocessing directive of the form
# pragma pp-tokensopt new-line
where the preprocessing token STDC does not immediately follow pragma in the
directive (prior to any macro replacement)174) causes the implementation to behave in an
implementation-defined manner. The behavior might cause translation to fail or cause the
translator or the resulting program to behave in a non-conforming manner. Any such
pragma that is not recognized by the implementation is ignored.



----- message d'origine -----
De : "Sergey Korshunoff" <seyko2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
date mer. 15/04/2015 12:07 (GMT +02:00)
À : "tinycc-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org" <tinycc-devel <at> nongnu.org>
Objet : [Tinycc-devel] #pragma push_macro(abort) && #pragma pop_macro(abort)

Hi! While making a cross compilers (./congigure --enable-cross) there
is a bunch of warnings abount undefined "#pragma push_macro(abort)"
and "#pragma pop_macro(abort)" with PE target. It looks like this
pragmas must be implemneted too. But how it must be done?

_______________________________________________
Tinycc-devel mailing list
Tinycc-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
<div>
<p>IMHO if not implemented it should not warn.<br><br>6.10.6 Pragma directive<br>Semantics<br><br>A preprocessing directive of the form<br># pragma pp-tokensopt new-line<br>where the preprocessing token STDC does not immediately follow pragma in the<br>directive (prior to any macro replacement)174) causes the implementation to behave in an<br>implementation-defined manner. The behavior might cause translation to fail or cause the<br>translator or the resulting program to behave in a non-conforming manner. Any such<br>pragma that is not recognized by the implementation is ignored.<br><br><br><br></p>
<blockquote>----- message d'origine -----<br>De : <span dir="ltr">"Sergey Korshunoff"</span> <span dir="lrt">&lt;seyko2@...&gt;</span><br>date mer. 15/04/2015 12:07 (GMT +02:00)<br>&Agrave; : <span dir="ltr">"tinycc-devel@..."</span> <span dir="lrt">&lt;tinycc-devel <at> nongnu.org&gt;</span><br>Objet : [Tinycc-devel] #pragma push_macro(abort) &amp;&amp; #pragma pop_macro(abort)<br><br>Hi! While making a cross compilers (./congigure --enable-cross) there<br>is a bunch of warnings abount undefined "#pragma push_macro(abort)"<br>and "#pragma pop_macro(abort)" with PE target. It looks like this<br>pragmas must be implemneted too. But how it must be done?<br><br>_______________________________________________<br>Tinycc-devel mailing list<br>Tinycc-devel@...<br>https://lists.nongnu.org/mailman/listinfo/tinycc-devel<br>
</blockquote>
</div>
Sergey Korshunoff | 15 Apr 12:02 2015
Picon

#pragma push_macro(abort) && #pragma pop_macro(abort)

Hi! While making a cross compilers (./congigure --enable-cross) there
is a bunch of warnings abount undefined "#pragma push_macro(abort)"
and "#pragma pop_macro(abort)" with PE target. It looks like this
pragmas must be implemneted too. But how it must be done?

Christian JULLIEN | 13 Apr 13:30 2015
Picon

RE :Re: Dollar Sign in Identifiers Extension

Arg! You're right Vincent, I was trying to exhibit a sample requiring a lexical closure.
Your sample is better.
This case we have to promote functions as first order object which contains code AND lexical closure at the time function is returned.
It's a brand new language design.

C++, allowing local class definition, can implement a feature similar to nested functions.


----- message d'origine -----
De : "Vincent Lefevre" <vincent-buymaDBGzMOsTnJN9+BGXg@public.gmane.org>
date lun. 13/04/2015 11:19 (GMT +02:00)
À : "tinycc-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org" <tinycc-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org>
Objet : Re: [Tinycc-devel] Dollar Sign in Identifiers Extension

On 2015-04-13 06:57:00 +0200, Christian Jullien wrote:
> Good luck for nested function implementers that (as is Lisp :o) will
> want to make this code working!

Despite some users want C to be like LISP here, it must not be like in
LISP. In C, a function is not an object, thus in particular, you have
no closures in C. And introducing nested functions (as in GCC) won't
change that. And one doesn't want closures anyway as they would yield
an incompatibility with ISO C when writing (using global variables
and functions):

int i = 17;
int foo (void) { return i; }

Here one mustn't assume that 17 will be returned. The value of an
external variable inside a function body is the value at the function
call (or the modified value by the function itself if the variable is
modified by the function), not the value when the function was
defined like in LISP.

> typedef int (*fp) (uint32_t i);
>
> int
> callback(fp fn, uint32_t i)
> fn(i);{
> }
>
> uint32_t
> isEven(uint32_t i) {
> uint32_t odd(uint32_t i) {
> if (i == 0) return 0;
> if (i == 1) return 1;
> retrun even(i - 1);
> }
> uint32_t even(uint32_t i) {
> if (i == 0) return 1;
> if (i == 1) return 0;
> retrun odd(i - 1);
> }
> callback(even, i);
> }

There are several typos. There's also the fact that even() is not
declared. You need to add:

auto uint32_t even(uint32_t i);

before the definition of odd(). After this being fixed, I don't see
any problem. This is not like if you were using lexical scoping to
access variables defined in isEven (in your example, the variable i
is passed as an argument to odd() and even(), so this doesn't
introduce a problem). But using lexical scoping after the function
exits would be a programming error (like with GCC's specification
of nested functions), just like:

int *foo (void)
{
int i;
return &i;
}

> C is not prepared to support nested function unless you rewrite whole
> calling convention mechanism that will break all known libraries.

I think that the main problem is that there are several ways to
specify nested functions. GCC has its own specification. Perhaps
other compilers that also support them as an extension have a
different one. In any case, the use of nested functions is rather
limited as non standard.

FYI, GNU MPFR uses nested functions when some specific feature
(logging) is enabled, but only because of other C extensions
implemented by GCC and compatible compilers, like destructors.

I would say that nested functions *alone* are not very useful, and
to make them useful in practice would be to implement other GCC
extensions, but this is much more work.

--
Vincent Lefèvre <vincent-buymaDBGzMOsTnJN9+BGXg@public.gmane.org> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

_______________________________________________
Tinycc-devel mailing list
Tinycc-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
<div>
<p>Arg! You're right Vincent, I was trying to exhibit a sample requiring a lexical closure.<br>Your sample is better.<br>This case we have to promote functions as first order object which contains code AND lexical closure at the time function is returned.<br>It's a brand new language design.<br><br>C++, allowing local class definition, can implement a feature similar to nested functions.<br><br><br></p>
<blockquote>----- message d'origine -----<br>De : <span dir="ltr">"Vincent Lefevre"</span> <span dir="lrt">&lt;vincent@...&gt;</span><br>date lun. 13/04/2015 11:19 (GMT +02:00)<br>&Agrave; : <span dir="ltr">"tinycc-devel@..."</span> <span dir="lrt">&lt;tinycc-devel@...&gt;</span><br>Objet : Re: [Tinycc-devel] Dollar Sign in Identifiers Extension<br><br>On 2015-04-13 06:57:00 +0200, Christian Jullien wrote:<br>&gt; Good luck for nested function implementers that (as is Lisp :o) will<br>&gt; want to make this code working!<br><br>Despite some users want C to be like LISP here, it must not be like in<br>LISP. In C, a function is not an object, thus in particular, you have<br>no closures in C. And introducing nested functions (as in GCC) won't<br>change that. And one doesn't want closures anyway as they would yield<br>an incompatibility with ISO C when writing (using global variables<br>and functions):<br><br>int i = 17;<br>int foo (void) { return i; }<br><br>Here one mustn't assume that 17 will be returned. The value of an<br>external variable inside a function body is the value at the function<br>call (or the modified value by the function itself if the variable is<br>modified by the function), not the value when the function was<br>defined like in LISP.<br><br>&gt; typedef int (*fp) (uint32_t i);<br>&gt; <br>&gt; int<br>&gt; callback(fp fn, uint32_t i)<br>&gt; fn(i);{<br>&gt; }<br>&gt; <br>&gt; uint32_t<br>&gt; isEven(uint32_t i) {<br>&gt; uint32_t odd(uint32_t i) {<br>&gt; if (i == 0) return 0;<br>&gt; if (i == 1) return 1;<br>&gt; retrun even(i - 1);<br>&gt; }<br>&gt; uint32_t even(uint32_t i) {<br>&gt; if (i == 0) return 1;<br>&gt; if (i == 1) return 0;<br>&gt; retrun odd(i - 1);<br>&gt; }<br>&gt; callback(even, i);<br>&gt; }<br><br>There are several typos. There's also the fact that even() is not<br>declared. You need to add:<br><br>  auto uint32_t even(uint32_t i);<br><br>before the definition of odd(). After this being fixed, I don't see<br>any problem. This is not like if you were using lexical scoping to<br>access variables defined in isEven (in your example, the variable i<br>is passed as an argument to odd() and even(), so this doesn't<br>introduce a problem). But using lexical scoping after the function<br>exits would be a programming error (like with GCC's specification<br>of nested functions), just like:<br><br>int *foo (void)<br>{<br>  int i;<br>  return &amp;i;<br>}<br><br>&gt; C is not prepared to support nested function unless you rewrite whole<br>&gt; calling convention mechanism that will break all known libraries.<br><br>I think that the main problem is that there are several ways to<br>specify nested functions. GCC has its own specification. Perhaps<br>other compilers that also support them as an extension have a<br>different one. In any case, the use of nested functions is rather<br>limited as non standard.<br><br>FYI, GNU MPFR uses nested functions when some specific feature<br>(logging) is enabled, but only because of other C extensions<br>implemented by GCC and compatible compilers, like destructors.<br><br>I would say that nested functions *alone* are not very useful, and<br>to make them useful in practice would be to implement other GCC<br>extensions, but this is much more work.<br><br>-- <br>Vincent Lef&egrave;vre &lt;vincent@...&gt; - Web: &lt;https://www.vinc17.net/&gt;<br>100% accessible validated (X)HTML - Blog: &lt;https://www.vinc17.net/blog/&gt;<br>Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)<br><br>_______________________________________________<br>Tinycc-devel mailing list<br>Tinycc-devel@...<br>https://lists.nongnu.org/mailman/listinfo/tinycc-devel<br>
</blockquote>
</div>

Gmane