#line 1111 "lpsrc/flx_rtl.ipk"
#include <cstdlib>
#include <stdio.h>
#include <vector>
#include <list>
#include <map>
#include <cstring>
#include <cassert>
#include <string>
//#include <unistd.h>
#include "flx_rtl.hpp"
#include "flx_collector.hpp"
#include "flx_dynlink.hpp"
using namespace std;
using namespace flx::rtl;
#ifdef HAVE_GXX_X86
register void *sp __asm__("esp");
#else
static void *sp = 0;
#endif
void print_loc(FILE *ef,flx_range_srcref_t x,char *cf, int cl)
{
fprintf(ef,"Felix location: %s %d[%d]-%d[%d]\n",
x.filename,
x.startline,
x.startcol,
x.endline,
x.endcol
);
fprintf(ef,"C++ location : %s %d\n", cf, cl);
}
int main(int argc, char** argv)
{
#ifndef FLX_STATIC_LINK
bool static_link = false;
if (argc<2)
{
printf("usage: flx_run [--debug] dll_filename options ..\n");
return 1;
}
char *filename = argv[1];
char **flx_argv = argv+1;
int flx_argc = argc-1;
bool debug = (argc > 1) && (strcmp(argv[1],"--debug")==0);
if(debug)
{
if(argc<3)
{
printf("usage: flx_run [--debug] dll_filename options ..\n");
return 1;
}
filename = argv[2];
--flx_argc;
++flx_argv;
}
#else
bool static_link = true;
char *filename = argv[0];
char **flx_argv = argv;
int flx_argc = argc;
bool debug = false;
// printf("Statically linked Felix program running\n");
#endif
char *debug_env = std::getenv("FLX_DEBUG");
debug = debug || debug_env != 0;
if(debug)
{
fprintf(stderr,"Debug enabled for %s link program\n",static_link?"static":"dynamic");
}
char *finalise_env= std::getenv("FLX_FINALISE");
bool finalise = finalise_env != 0;
if(debug)
fprintf(stderr,"Finalisation %s\n",finalise? "Enabled" : "Disabled");
#ifdef HAVE_GXX
if(debug) fprintf(stderr, "Compiled by g++\n");
static void *init_sp = sp;
static void *init_fframe FLX_UNUSED = __builtin_frame_address(0);
static void *init_ret = __builtin_return_address(0);
#endif
if(debug)
for(int i=0; i<flx_argc; ++i)
fprintf(stderr,"flx_argv[%d]->%s\n",i,flx_argv[i]);
try
{
if(debug)
fprintf(stderr,"flx_run driver begins %s\n",flx_argv[0]);
flx_dynlink_t library;
flx_libinit_t instance;
library.link(filename);
flx::gc::collector::malloc_free allocator;
allocator.set_debug(debug);
flx::gc::collector::flx_collector_t collector(&allocator);
collector.set_debug(debug);
instance.create(&library, &collector,flx_argc,flx_argv,stdin,stdout,stderr);
if(debug) {
fprintf(stderr,"loaded library %s at %p\n",filename,library.library);
fprintf(stderr,"thread frame at %p\n",instance.thread_frame);
fprintf(stderr,"initial continuation at %p\n",instance.start_proc);
}
int gc_counter = 0;
unsigned long collections = 0;
con_t *top = instance.start_proc;
fthread_t *ft = new (collector,_fthread_ptr_map) fthread_t(top);
collector.add_root(ft);
_uctor_ *request = ft->run();
while( request && request->variant == svc_yield)
{
gc_counter++;
if(gc_counter == 1000)
{
gc_counter = 0;
++collections;
unsigned long n = collector.collect();
if(debug)fprintf(stderr,"collected %ld objects\n",n);
}
request = ft->run();
}
if(debug){
unsigned long uncollected = collector.get_allocation_count();
unsigned long roots = collector.get_root_count();
fprintf(stderr,"program finished, %ld collections, %ld uncollected objects, roots %ld\n",collections,uncollected,roots);
}
if(finalise)
{
if(debug) fprintf(stderr,"Finalising\n");
if(debug)fprintf(stderr,"removing thread %p\n",ft);
collector.remove_root(ft);
{
if(debug)
fprintf(stderr,"Data collection starts ..\n");
unsigned long n = collector.collect();
unsigned long a = collector.get_allocation_count();
if(debug)
fprintf(stderr,"flx_run collected %ld objects, %ld left\n",n,a);
}
if(debug)
fprintf(stderr,"Destroying program instance\n");
instance.destroy();
if(debug)
fprintf(stderr,"Final collection starts ..\n");
unsigned long n = collector.collect();
unsigned long a = collector.get_allocation_count();
if(debug)
fprintf(stderr,"Collected %ld objects, %ld left (should be 0)\n",n,a);
if(a!=0){
fprintf(stderr,"flx_run %ld uncollected objects, should be zero!!\n",a);
return 5;
}
if(debug)
fprintf(stderr,"Libref cnt = %ld\n",library.refcnt);
if(library.refcnt >0)
{
if(debug)
fprintf(stderr,"flx_run %p library still referenced %ld times (expected 1)\n",library.library,library.refcnt);
}
if(debug)
fprintf(stderr,"Unlinking library ..\n");
library.unlink();
if(library.refcnt >0)
{
fprintf(stderr,"flx_run %p library still referenced %ld times?!\n",library.library,library.refcnt);
return 6;
}
if(debug)
fprintf(stderr,"flx_run driver ends with finalisation complete, collected %ld,left=%ld\n",n,a);
}
else {
if(debug) {
unsigned long a = collector.get_allocation_count();
fprintf(stderr,"flx_run driver ends with finalisation skipped, %ld uncollected objects\n",a);
}
}
}
catch (flx_link_failure_t x)
{
fprintf(stderr,"Dynamic linkage error\n");
fprintf(stderr,"filename: %s\n",x.filename.data());
fprintf(stderr,"operation: %s\n",x.operation.data());
fprintf(stderr,"what: %s\n",x.what.data());
return 2;
}
catch (flx_exec_failure_t x)
{
fprintf(stderr,"Execution error\n");
fprintf(stderr,"filename: %s\n",x.filename.data());
fprintf(stderr,"operation: %s\n",x.operation.data());
fprintf(stderr,"what: %s\n",x.what.data());
return 3;
}
catch (flx_assert_failure_t x)
{
fprintf(stderr,"Assertion Failure\n");
print_loc(stderr,x.flx_loc,x.cxx_srcfile, x.cxx_srcline);
return 3;
}
catch (flx_match_failure_t x)
{
fprintf(stderr,"Match Failure\n");
print_loc(stderr,x.flx_loc,x.cxx_srcfile, x.cxx_srcline);
return 3;
}
catch (...)
{
fprintf(stderr,"flx_run driver ends with unknown EXCEPTION\n");
return 4;
}
#ifdef HAVE_GXX
// check the frame pointer isn't corrupted
static void *fin_sp = sp;
static void *fin_fframe FLX_UNUSED = __builtin_frame_address(0);
static void *fin_ret = __builtin_return_address(0);
if (init_sp != fin_sp ) {
fprintf(stderr,"g++: STACK POINTER ERROR %p != %p\n",init_sp,fin_sp);
}
// I have to comment this out, because it only applies if the
// gcc compiler is using the frame pointer.. it doesn't if you
// say -fomit-frame-pointer, for example .. I don't know if there
// is a way to tell inside the code ..
#if 0
if (init_fframe != fin_fframe) {
fprintf(stderr,"g++: FRAME POINTER ERROR %p != %p\n",init_fframe,fin_fframe);
}
#endif
else if (init_ret != fin_ret) {
fprintf(stderr,"g++: RETURN ADDRESS ERROR %p != %p\n",init_ret,fin_ret);
}
#endif
if(debug)fprintf(stderr,"flx_run driver ends OK\n");
return 0;
}