Playing around with modifying list arguments passed to C. This uses the low level c_put from src/runtime/fstruct.r, along with loadfunc. I'd appreciate having any mistakes pointed out, before getting too much farther in and leading people down the wrong path.
prompt$ $ valgrind unicon -s unilist.icn -x
==25555== Memcheck, a memory error detector
==25555== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25555== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==25555== Command: /home/btiffin/unicon/bin/unicon -s unilist.icn -x
==25555==
==25556== Warning: invalid file descriptor -1 in syscall close()
==25557==
==25557== HEAP SUMMARY:
==25557== in use at exit: 11,362 bytes in 96 blocks
==25557== total heap usage: 103 allocs, 7 frees, 12,074 bytes allocated
==25557==
==25557== LEAK SUMMARY:
==25557== definitely lost: 0 bytes in 0 blocks
==25557== indirectly lost: 0 bytes in 0 blocks
==25557== possibly lost: 0 bytes in 0 blocks
==25557== still reachable: 11,362 bytes in 96 blocks
==25557== suppressed: 0 bytes in 0 blocks
==25557== Rerun with --leak-check=full to see details of leaked memory
==25557==
==25557== For counts of detected and suppressed errors, rerun with: -v
==25557== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==25556==
==25556== HEAP SUMMARY:
==25556== in use at exit: 3,197 bytes in 96 blocks
==25556== total heap usage: 101 allocs, 5 frees, 3,381 bytes allocated
==25556==
==25556== LEAK SUMMARY:
==25556== definitely lost: 0 bytes in 0 blocks
==25556== indirectly lost: 0 bytes in 0 blocks
==25556== possibly lost: 0 bytes in 0 blocks
==25556== still reachable: 3,197 bytes in 96 blocks
==25556== suppressed: 0 bytes in 0 blocks
==25556== Rerun with --leak-check=full to see details of leaked memory
==25556==
==25556== For counts of detected and suppressed errors, rerun with: -v
==25556== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
&allocated
----------
Heap : 34528
Static : 0
String : 0
Block : 34528
100000 list_2(300000)
26 :qoAJhUvjcZrecFWyLrBQwFlpPA: 13.25298485031956
19 :AflKLEGxLZtzQZmwaEP: 13.67044743647354
2 :lT: 0.5765757200199066
7 :OhkDWKm: 5.096226113893197
16 :gjqnotdNfzYEtHdC: 15.73470170783564
19 :blwwmvlWwSFAtVPKQVr: 16.38335897232562
27 :kqEyWpWgbglFyKHGKPAIUZbGGuD: 21.23552009939939
26 :bNjxhLyHVveJMxFeaYTQdZpZfV: 12.53927280499566
31 :OknmfCKiiqnQXWpjLmvBTIfkjjqNabE:3.146761554361676
6 :wgZozD: 2.082273955495224
&allocated
----------
Heap : 8084874
Static : 0
String : 1658010
Block : 6426864
tcc compiled DSO kicked from Unicon.
The .so generated from gcc from was
-rwxrwxr-x 1 btiffin btiffin 12808 Jan 8 11:50 unilist.so
From tcc that weighs in at
-rwxrwxr-x 1 btiffin btiffin 5720 Jan 8 12:31 unilist.so
Pretty neat, and tidy.
Next step is embedding Tiny C in Unicon:
/*- Author: Brian Tiffin Dedicated to the public domain Date started: January 2017 Modified: 2017-01-08/12:23-0500 Tectonics: tcc -o unitcc.so -shared unitcc.c -ltcc -L/usr/local/lib+*//* unitcc.c, embed Tiny C in Unicon */#include<stdlib.h>#include<stdio.h>#include<string.h>#include"libtcc.h"#include"icall.h"intunitcc(intargc,descriptorargv[]){/* Crank up tcc */TCCState*s;int(*func)(int);intresult;/* First arg is the C code */ArgString(1);/* Second arg is the integer parameter */ArgInteger(2);s=tcc_new();if(!s){fprintf(stderr,"Could not create tcc state\n");exit(1);}/* if tcclib.h and libtcc1.a are not installed, where can we find them *//* if (argc == 2 && !memcmp(argv[1], "lib_path=",9)) tcc_set_lib_path(s, argv[1]+9); *//* MUST BE CALLED before any compilation */tcc_set_output_type(s,TCC_OUTPUT_MEMORY);if(tcc_compile_string(s,StringVal(argv[1]))==-1)return1;/* as a test, we add a symbol that the compiled program can use. You may also open a dll with tcc_add_dll() and use symbols from that *//* tcc_add_symbol(s, "add", add); *//* relocate the code */if(tcc_relocate(s,TCC_RELOCATE_AUTO)<0)return1;/* get entry symbol */func=tcc_get_symbol(s,"unitcc");if(!func)return1;/* run the code */result=func(IntegerVal(argv[2]));/* delete the state */tcc_delete(s);RetInteger(result);}
unitcc.c
And a caller:
##-
# Author: Brian Tiffin
# Dedicated to the public domain
#
# Date started: January 2017
# Modified: 2017-01-08/12:27-0500
##+
#
# unitcc.icn, demonstrate an embedded Tiny C compiler
#
# tectonics:
# tcc -o unitcc.so unitcc.c -ltcc -L\usr\local\lib
#
procedure main()
tcc := loadfunc("./unitcc.so", "unitcc")
result := tcc(
"int unitcc(int i) {\n_
printf(\"Hello, world\n\");\n_
return i*42;\n_
}", 42)
write("result from tcc: ", result)
end
And the drum roll...
prompt$ tcc -shared unitcc.c -o unitcc.so -ltcc -L/usr/local/lib
prompt$ unicon -s unitcc.icn -x
Hello, world
result from tcc: 1764
Proof of a basic install, returning 42 * 42. Woohoo. C compiled on the fly, to memory, then invoked, with the C program passed from Unicon as a string along with a sample argument, and result returned to Unicon.
Tiny C is quite the animal. The only complaint from the sample was the lib_path search setting in the tcc example wanted to use argv, and I didn't bother moving that to an ArgString(3) as a descriptor argv from Unicon. It just worked without setting the path, so that code remained commented out.
Now, can the original unilist.c loadable be compiled on the fly, invoked by the Tiny C engine and then loadfunc-ed into Unicon space via unitcc? An experiment for next time.
If t works, it'll mean being able to ship loadfunc applications as recursively self hosted source. :-)
Tiny C was orignally written by Fabrice Bellard, who went on to build QEMU. Brilliant. LGPL
tcc 0.9.26 (the version put through its paces here, also comes with an inline assembler, inlined inside the tcc to memory compile and link, no externals required.
And the cooler part is, it compiles loadfunc Dynamic Shared Objects for use by Unicon and valgrind is still happy . after building some 10,000 random strings and appending them to Unicon structures. A fine way to waste an hour of Sunday morning exploring Unicon potentials.
Full disclosure: valgrind is mostly happy; when run with --trace-children=yes there is some 8K of space that is complained about. This is due to icon_init rundown not being performed before image exit, which is pretty standard behaviour for language runtimes. Grab a little space, and then keep it forever, or until returning to the operating system. The complaint had nothing to do with tcc or Unicon in general. So, still the woo and the hoo. :-)
Cheers,
Brian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Playing around with modifying list arguments passed to C. This uses the low level
c_put
fromsrc/runtime/fstruct.r
, along withloadfunc
. I'd appreciate having any mistakes pointed out, before getting too much farther in and leading people down the wrong path.http://btiffin.users.sourceforge.net/up/programs.html#unilist
Have good, make well,
Brian
Kept playing.
The loadable, generated from Tiny C
Build a tcc version of the shared library
Test run:
tcc compiled DSO kicked from Unicon.
The .so generated from gcc from was
From tcc that weighs in at
Pretty neat, and tidy.
Next step is embedding Tiny C in Unicon:
unitcc.c
And a caller:
And the drum roll...
Proof of a basic install, returning 42 * 42. Woohoo. C compiled on the fly, to memory, then invoked, with the C program passed from Unicon as a string along with a sample argument, and result returned to Unicon.
Tiny C is quite the animal. The only complaint from the sample was the
lib_path
search setting in the tcc example wanted to use argv, and I didn't bother moving that to an ArgString(3) as adescriptor
argv from Unicon. It just worked without setting the path, so that code remained commented out.Now, can the original
unilist.c
loadable be compiled on the fly, invoked by the Tiny C engine and then loadfunc-ed into Unicon space viaunitcc
? An experiment for next time.If t works, it'll mean being able to ship loadfunc applications as recursively self hosted source. :-)
Tiny C was orignally written by Fabrice Bellard, who went on to build QEMU. Brilliant. LGPL
http://bellard.org/tcc/
tcc 0.9.26 (the version put through its paces here, also comes with an inline assembler, inlined inside the tcc to memory compile and link, no externals required.
And the cooler part is, it compiles
loadfunc
Dynamic Shared Objects for use by Unicon and valgrind is still happy . after building some 10,000 random strings and appending them to Unicon structures. A fine way to waste an hour of Sunday morning exploring Unicon potentials.Full disclosure:
valgrind
is mostly happy; when run with --trace-children=yes there is some 8K of space that is complained about. This is due toicon_init
rundown not being performed before image exit, which is pretty standard behaviour for language runtimes. Grab a little space, and then keep it forever, or until returning to the operating system. The complaint had nothing to do withtcc
or Unicon in general. So, still the woo and the hoo. :-)Cheers,
Brian