Two compilers at once

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Two compilers at once

Karl Yerkes
I would like to have two compilers active at the same time so i can recompile and hot-swap a function. ;On my journey, I noticed that making a new, second compiler before the first one compiles leads to strange behaviour. I am running macOS 10.14.5 with tcc 0.9.27.

// compile and run like this:
//
//   c++ -std=c++11 -ltcc tinycc-devel-example.cpp ; and ./a.out
//
// the `tcc_compile_string` step will fail with this error:
//
//   <string>: error: missing #endif
//
#include <cassert>
#include <cstdio>
#include "libtcc.h"

int main() {
  TCCState* a = nullptr;
  char (*A)(int) = nullptr;
  assert((a = tcc_new()) != nullptr);
  TCCState* b = tcc_new();  // remove this line to make the program work
  assert(tcc_set_output_type(a, TCC_OUTPUT_MEMORY) == 0);
  assert(tcc_compile_string(a, "char foo(int t) { return (char)t; }") != -1);
  assert(tcc_relocate(a, TCC_RELOCATE_AUTO) >= 0);
  assert((A = (char (*)(int))tcc_get_symbol(a, "foo")) != nullptr);
  printf("%d = A(0)\n", A(0));
}


As long as I make the second compiler after the first one compiles something, things work. is this a bug? Is using two compilers unsupported or prohibited?

-- karl



_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Michael Matz-4
Hello,

On Fri, 24 May 2019, Karl Yerkes wrote:

> As long as I make the second compiler after the first one compiles
> something, things work. is this a bug? Is using two compilers
> unsupported or prohibited?

libtcc contains some global state, i.e. shared between TCCState objects
you create.  Some of this sharing is harmless, some of it isn't; the
latter is the reason why two compile objects generally don't work except
by accident.  Fixing this implies adding one indirection, and some of that
state is used in extremely performance critical code, so it has never been
a priority.

So, yeah, it's a current limitation of libtcc.


Ciao,
Michael.

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Christian Jullien-3

Hi,

 

Because Karl uses C++11, it may be theoretically possible for him to load two different tcc instances having different C++ namespaces and compiled in two distinct translation units.

 

tcc1.cpp:

namespace tcc1 {

#include "libtcc.h"

};

 

Tcc2.cpp:

namespace tcc2 {

#include "libtcc.h"

};

 

int main() {

  tcc1::TCCState* a = nullptr;

  char (*A)(int) = nullptr;

  assert((a = tcc1::tcc_new()) != nullptr);

  tcc2::TCCState* b = tcc2::tcc_new();  // remove this line to make the program work

//

}

 

But it may not be so simple. For some projects it worked flawlessly and failed for some others.

 

C.

 

-----Original Message-----
From: Tinycc-devel [mailto:tinycc-devel-bounces+eligis=[hidden email]] On Behalf Of Michael Matz
Sent: Friday, May 24, 2019 21:51
To: [hidden email]
Subject: Re: [Tinycc-devel] Two compilers at once

 

Hello,

 

On Fri, 24 May 2019, Karl Yerkes wrote:

 

> As long as I make the second compiler after the first one compiles

> something, things work. is this a bug? Is using two compilers

> unsupported or prohibited?

 

libtcc contains some global state, i.e. shared between TCCState objects

you create.  Some of this sharing is harmless, some of it isn't; the

latter is the reason why two compile objects generally don't work except

by accident.  Fixing this implies adding one indirection, and some of that

state is used in extremely performance critical code, so it has never been

a priority.

 

So, yeah, it's a current limitation of libtcc.

 

 

Ciao,

Michael.

 

_______________________________________________

Tinycc-devel mailing list

[hidden email]

https://lists.nongnu.org/mailman/listinfo/tinycc-devel


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Giovanni Mascellani
Hi,

Il 25/05/19 06:24, Christian Jullien ha scritto:
> Because Karl uses C++11, it may be /theoretically/ possible for him to
> load two different tcc instances having different C++ namespaces and
> compiled in two distinct translation units.

If you don't mind some quite dirty hacking (and if you mind it you
shouldn't probably use tcc), I also believe that you can have two
instances in the same address space by using the first one to compile
another one (or many others) and relocating them to different addresses.
Then each of them is a completely independent compiler with independent
state. Of course this means that you need tcc's source code at runtime.
Otherwise there is the old trick of just opening a pipe, forking and
then sending back the result.

Have fun, Giovanni.
--
Giovanni Mascellani <[hidden email]>
Postdoc researcher - Université Libre de Bruxelles


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

signature.asc (235 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Karl Yerkes
thank you for your replies. your help and insights are much appreciated. 

I'm loving TCC!

however, i've reached the limit of my current hot-swap function hack that uses two state-commingling TCC instances. after a while, the instances stop working properly and I get strange compile errors.

so, i am interested in executing some hack to allow multiple independent TCC instances in the same application. i am certain that "the old trick of just opening a pipe, forking and
then sending back the result" will not work for my purposes. if i can't get one of these hacks working, i have to go look at LLVM and cling again :/

as i understand it, option 2 (from Giovanni Mascellani) is using libtcc to compile libtcc from source into memory. that sounds awesome. i spent most of today trying this on windows.. and also learning to compile TCC on windows. here's my attempt:

// boot.cpp
//
// tcc version 0.9.27 (x86_64 Windows)
// install: c:/tcc
// include:
//   c:/tcc/include
//   c:/tcc/include/winapi
// libraries:
//   c:/tcc/lib
//   C:/Windows/system32
// libtcc1:
//   c:/tcc/lib/libtcc1-64.a
//
// build and run with:
//   cd tinycc
//   cl /MD boot.cpp c:\tcc\libtcc64.lib
//   boot.exe
//
//  fails like this:
//  need 457827 bytes
//  relocating to 21f0a402fd0
//  tcc: error: library 'libtcc1-64.a' not found
//  Assertion failed: dec != nullptr, file boot.cpp, line 69
//
#include "libtcc.h"

#include <cassert>
#include <iostream>

int main() {
  TCCState* instance = tcc_new();

  // i'm on Windows 10 x64. what else do i need here?
  tcc_set_options(instance, "-shared");
  tcc_define_symbol(instance, "TCC_TARGET_X86_64", "");
  tcc_define_symbol(instance, "TCC_TARGET_PE", "");
  tcc_define_symbol(instance, "LIBTCC_AS_DLL", "");

  // i needed this define on Windows to get tcc_relocate in the DLL
  tcc_define_symbol(instance, "TCC_IS_NATIVE", "");

  tcc_set_output_type(instance, TCC_OUTPUT_MEMORY);

  // maybe add more source files?
  tcc_add_file(instance, "libtcc.c");

  int size = tcc_relocate(instance, (void*)0);
  void* memory = malloc(size);

  printf("need %d bytes\n", size);
  printf("relocating to %llx\n", (unsigned long long int)memory);
  tcc_relocate(instance, memory);

  // TCCState *tcc_new(void);
  using New = TCCState* (*)(void);
  New _new = (New)tcc_get_symbol(instance, "tcc_new");
  assert(_new != nullptr);

  // int tcc_set_output_type(TCCState *s, int output_type);
  using SetOutputType = int (*)(TCCState*, int);
  SetOutputType _set_output_type =
      (SetOutputType)tcc_get_symbol(instance, "tcc_set_output_type");
  assert(_set_output_type != nullptr);

  // int tcc_compile_string(TCCState *s, const char *buf);
  using CompileString = int (*)(TCCState*, const char*);
  CompileString _compile_string =
      (CompileString)tcc_get_symbol(instance, "tcc_compile_string");
  assert(_compile_string != nullptr);

  // int tcc_relocate(TCCState *s1, void *ptr);
  using Relocate = int (*)(TCCState*, void*);
  Relocate _relocate = (Relocate)tcc_get_symbol(instance, "tcc_relocate");
  assert(_relocate != nullptr);

  // void *tcc_get_symbol(TCCState *s, const char *name);
  using GetSymbol = void* (*)(TCCState*, const char*);
  GetSymbol _get_symbol = (GetSymbol)tcc_get_symbol(instance, "tcc_get_symbol");
  assert(_get_symbol != nullptr);

  // can i delete the instance now??
  // my experiments suggest no.
  // tcc_delete(instance);

  // use the new, relocated instance to compile something
  TCCState* born_in_memory = _new();
  assert(born_in_memory != nullptr);
  _set_output_type(born_in_memory, TCC_OUTPUT_MEMORY);
  _compile_string(born_in_memory, "int dec(int t) { return t - 1; }");
  _relocate(born_in_memory, TCC_RELOCATE_AUTO);
  using Foo = int (*)(int);
  Foo dec = (Foo)_get_symbol(born_in_memory, "dec");
  assert(dec != nullptr);
  printf("dec(2) == %d\b", dec(2));
}

am i on the right track here? any suggestions would help a lot. i think i could add the path to libtcc1-64.a, but i would rather compile all the .c files i need so there's no need to find libtcc1-64.a at runtime. 

-

option 1 (from Christian Jullien) is something that i don't quite understand. i am just failing to connect the dots given i the pseudocode:

// tcc1.cpp:
namespace tcc1 {
#include "libtcc.h"
  // does this mean i should compile libtcc as c++ (not c) under the tcc1 namespace?
};

// tcc2.cpp:
namespace tcc2 {
#include "libtcc.h"
   // does this mean i should compile libtcc as c++ (not c) AGAIN under the tcc2 namespace?
 // OR does this mean i should write a wrapper interface for libtcc here?
};

// main.cpp:
int main() {
  tcc1::TCCState* a = nullptr;
  char (*A)(int) = nullptr;
  assert((a = tcc1::tcc_new()) != nullptr);
  tcc2::TCCState* b =
      tcc2::tcc_new();  // remove this line to make the program work
}

also "But it may not be so simple. For some projects it worked flawlessly and failed for some others" is mysterious to me. my apologies for being too ignorant to put it together! a little more help on this option might help me a lot.

sorry for the long email.

-- karl





  



On Sat, May 25, 2019 at 12:30 AM Giovanni Mascellani <[hidden email]> wrote:
Hi,

Il 25/05/19 06:24, Christian Jullien ha scritto:
> Because Karl uses C++11, it may be /theoretically/ possible for him to
> load two different tcc instances having different C++ namespaces and
> compiled in two distinct translation units.

If you don't mind some quite dirty hacking (and if you mind it you
shouldn't probably use tcc), I also believe that you can have two
instances in the same address space by using the first one to compile
another one (or many others) and relocating them to different addresses.
Then each of them is a completely independent compiler with independent
state. Of course this means that you need tcc's source code at runtime.
Otherwise there is the old trick of just opening a pipe, forking and
then sending back the result.

Have fun, Giovanni.
--
Giovanni Mascellani <[hidden email]>
Postdoc researcher - Université Libre de Bruxelles

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Steve Fan

I’m sorry to intervene in the matter, but as you look at the design of TCC, you will see that it is not designed for re-entrancy.

 

Foolish younger me, I used to have a hardworking re-entrant fork of TCC working but the one of the project owner denounced my idea, calling me to adapt TLS for each and every global variables instead of rewriting most of the TCC functions to add TCCState for them.

 

TCC is just a hobbyist bone picked from OTCC by the legend Fabrice Bellard himself, but he has abandoned his child, TCC, ever since.

 

I used to be like you, I want to research on TCC, but now I do warn you to not touch this egregious code again.

 

Go figure out your own parser. Maybe learn Bison or ANTLR for a basic parser, then read some paper about register allocation (which is a very bitchy problem for it was actually NP-Complete), read the specs for ELF, and read the respective assembly handbook for each and every codegen backend. You can reuse the ELF/PE code from TCC I reckon, but just don’t try to make anything happen to TCC, a dying project.

 

From: [hidden email]
Sent: Friday, 21 June 2019 9:24 AM
To: [hidden email]
Subject: Re: [Tinycc-devel] Two compilers at once

 

thank you for your replies. your help and insights are much appreciated. 

 

I'm loving TCC!

 

however, i've reached the limit of my current hot-swap function hack that uses two state-commingling TCC instances. after a while, the instances stop working properly and I get strange compile errors.

 

so, i am interested in executing some hack to allow multiple independent TCC instances in the same application. i am certain that "the old trick of just opening a pipe, forking and

then sending back the result" will not work for my purposes. if i can't get one of these hacks working, i have to go look at LLVM and cling again :/

 

as i understand it, option 2 (from Giovanni Mascellani) is using libtcc to compile libtcc from source into memory. that sounds awesome. i spent most of today trying this on windows.. and also learning to compile TCC on windows. here's my attempt:

 

// boot.cpp
//
// tcc version 0.9.27 (x86_64 Windows)
// install: c:/tcc
// include:
//   c:/tcc/include
//   c:/tcc/include/winapi
// libraries:
//   c:/tcc/lib
//   C:/Windows/system32
// libtcc1:
//   c:/tcc/lib/libtcc1-64.a
//
// build and run with:
//   cd tinycc
//   cl /MD boot.cpp c:\tcc\libtcc64.lib
//   boot.exe
//
//  fails like this:
//  need 457827 bytes
//  relocating to 21f0a402fd0
//  tcc: error: library 'libtcc1-64.a' not found
//  Assertion failed: dec != nullptr, file boot.cpp, line 69
//
#include "libtcc.h"

#include <cassert>
#include <iostream>

int main() {
  TCCState* instance = tcc_new();

  // i'm on Windows 10 x64. what else do i need here?
  tcc_set_options(instance, "-shared");
  tcc_define_symbol(instance, "TCC_TARGET_X86_64", "");
  tcc_define_symbol(instance, "TCC_TARGET_PE", "");
  tcc_define_symbol(instance, "LIBTCC_AS_DLL", "");

  // i needed this define on Windows to get tcc_relocate in the DLL
  tcc_define_symbol(instance, "TCC_IS_NATIVE", "");

  tcc_set_output_type(instance, TCC_OUTPUT_MEMORY);

  // maybe add more source files?
  tcc_add_file(instance, "libtcc.c");

  int size = tcc_relocate(instance, (void*)0);
  void* memory = malloc(size);

  printf("need %d bytes\n", size);
  printf("relocating to %llx\n", (unsigned long long int)memory);
  tcc_relocate(instance, memory);

  // TCCState *tcc_new(void);
  using New = TCCState* (*)(void);
  New _new = (New)tcc_get_symbol(instance, "tcc_new");
  assert(_new != nullptr);

  // int tcc_set_output_type(TCCState *s, int output_type);
  using SetOutputType = int (*)(TCCState*, int);
  SetOutputType _set_output_type =
      (SetOutputType)tcc_get_symbol(instance, "tcc_set_output_type");
  assert(_set_output_type != nullptr);

  // int tcc_compile_string(TCCState *s, const char *buf);
  using CompileString = int (*)(TCCState*, const char*);
  CompileString _compile_string =
      (CompileString)tcc_get_symbol(instance, "tcc_compile_string");
  assert(_compile_string != nullptr);

  // int tcc_relocate(TCCState *s1, void *ptr);
  using Relocate = int (*)(TCCState*, void*);
  Relocate _relocate = (Relocate)tcc_get_symbol(instance, "tcc_relocate");
  assert(_relocate != nullptr);

  // void *tcc_get_symbol(TCCState *s, const char *name);
  using GetSymbol = void* (*)(TCCState*, const char*);
  GetSymbol _get_symbol = (GetSymbol)tcc_get_symbol(instance, "tcc_get_symbol");
  assert(_get_symbol != nullptr);

  // can i delete the instance now??
  // my experiments suggest no.
  // tcc_delete(instance);

  // use the new, relocated instance to compile something
  TCCState* born_in_memory = _new();
  assert(born_in_memory != nullptr);
  _set_output_type(born_in_memory, TCC_OUTPUT_MEMORY);
  _compile_string(born_in_memory, "int dec(int t) { return t - 1; }");
  _relocate(born_in_memory, TCC_RELOCATE_AUTO);
  using Foo = int (*)(int);
  Foo dec = (Foo)_get_symbol(born_in_memory, "dec");
  assert(dec != nullptr);
  printf("dec(2) == %d\b", dec(2));
}

 

am i on the right track here? any suggestions would help a lot. i think i could add the path to libtcc1-64.a, but i would rather compile all the .c files i need so there's no need to find libtcc1-64.a at runtime. 

 

-

 

option 1 (from Christian Jullien) is something that i don't quite understand. i am just failing to connect the dots given i the pseudocode:

 

// tcc1.cpp:
namespace tcc1 {
#include "libtcc.h"

  // does this mean i should compile libtcc as c++ (not c) under the tcc1 namespace?
};

// tcc2.cpp:
namespace tcc2 {
#include "libtcc.h"

   // does this mean i should compile libtcc as c++ (not c) AGAIN under the tcc2 namespace?

 // OR does this mean i should write a wrapper interface for libtcc here?
};

// main.cpp:
int main() {
  tcc1::TCCState* a = nullptr;
  char (*A)(int) = nullptr;
  assert((a = tcc1::tcc_new()) != nullptr);
  tcc2::TCCState* b =
      tcc2::tcc_new();  // remove this line to make the program work
}

also "But it may not be so simple. For some projects it worked flawlessly and failed for some others" is mysterious to me. my apologies for being too ignorant to put it together! a little more help on this option might help me a lot.

 

sorry for the long email.

 

-- karl

 

 

 

 

 

  

 

 

 

On Sat, May 25, 2019 at 12:30 AM Giovanni Mascellani <[hidden email]> wrote:

Hi,

Il 25/05/19 06:24, Christian Jullien ha scritto:
> Because Karl uses C++11, it may be /theoretically/ possible for him to
> load two different tcc instances having different C++ namespaces and
> compiled in two distinct translation units.

If you don't mind some quite dirty hacking (and if you mind it you
shouldn't probably use tcc), I also believe that you can have two
instances in the same address space by using the first one to compile
another one (or many others) and relocating them to different addresses.
Then each of them is a completely independent compiler with independent
state. Of course this means that you need tcc's source code at runtime.
Otherwise there is the old trick of just opening a pipe, forking and
then sending back the result.

Have fun, Giovanni.
--
Giovanni Mascellani <[hidden email]>
Postdoc researcher - Université Libre de Bruxelles

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

 


_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Karl Yerkes

Steve Fan --

On Thu, Jun 20, 2019 at 7:14 PM Steve Fan <[hidden email]> wrote:

I’m sorry to intervene in the matter, but as you look at the design of TCC, you will see that it is not designed for re-entrancy.


yes. i understand. i am not trying to make it reentrant. i want to hot-recompile-swap a function with very low latency and i am willing to settle for a hack.


Foolish younger me, I used to have a hardworking re-entrant fork of TCC working but the one of the project owner denounced my idea, calling me to adapt TLS for each and every global variables instead of rewriting most of the TCC functions to add TCCState for them.


good for you.. and that sucks.


TCC is just a hobbyist bone picked from OTCC by the legend Fabrice Bellard himself, but he has abandoned his child, TCC, ever since.


yes. i get that.
 

I used to be like you, I want to research on TCC, but now I do warn you to not touch this egregious code again.


i am not aiming to change the TCC source code. i actually only want to hack around what currently exists. that said, i might end up helping out somehow.


Go figure out your own parser. Maybe learn Bison or ANTLR for a basic parser, then read some paper about register allocation (which is a very bitchy problem for it was actually NP-Complete), read the specs for ELF, and read the respective assembly handbook for each and every codegen backend. You can reuse the ELF/PE code from TCC I reckon, but


thank you. this is good advice and good info. i know parsing and grammars. i write my grammars/parsers in perl6 :) 

maybe generating x86, ARM, or LLVM-IR is not that hard and i should go do that. (right now it is black magic to me.)

but my aim is actually to hack something together to further my aims in a different domain: sound.

i am quite close with TCC.

 

just don’t try to make anything happen to TCC, a dying project.


i hear your warning. you may very well be right, but to me TCC seems... mature, not dying. maybe it's not going to be much more than what it is, but i bet it'll hold its value for a while.

-- karl
 

 

From: [hidden email]
Sent: Friday, 21 June 2019 9:24 AM
To: [hidden email]
Subject: Re: [Tinycc-devel] Two compilers at once

 

thank you for your replies. your help and insights are much appreciated. 

 

I'm loving TCC!

 

however, i've reached the limit of my current hot-swap function hack that uses two state-commingling TCC instances. after a while, the instances stop working properly and I get strange compile errors.

 

so, i am interested in executing some hack to allow multiple independent TCC instances in the same application. i am certain that "the old trick of just opening a pipe, forking and

then sending back the result" will not work for my purposes. if i can't get one of these hacks working, i have to go look at LLVM and cling again :/

 

as i understand it, option 2 (from Giovanni Mascellani) is using libtcc to compile libtcc from source into memory. that sounds awesome. i spent most of today trying this on windows.. and also learning to compile TCC on windows. here's my attempt:

 

// boot.cpp
//
// tcc version 0.9.27 (x86_64 Windows)
// install: c:/tcc
// include:
//   c:/tcc/include
//   c:/tcc/include/winapi
// libraries:
//   c:/tcc/lib
//   C:/Windows/system32
// libtcc1:
//   c:/tcc/lib/libtcc1-64.a
//
// build and run with:
//   cd tinycc
//   cl /MD boot.cpp c:\tcc\libtcc64.lib
//   boot.exe
//
//  fails like this:
//  need 457827 bytes
//  relocating to 21f0a402fd0
//  tcc: error: library 'libtcc1-64.a' not found
//  Assertion failed: dec != nullptr, file boot.cpp, line 69
//
#include "libtcc.h"

#include <cassert>
#include <iostream>

int main() {
  TCCState* instance = tcc_new();

  // i'm on Windows 10 x64. what else do i need here?
  tcc_set_options(instance, "-shared");
  tcc_define_symbol(instance, "TCC_TARGET_X86_64", "");
  tcc_define_symbol(instance, "TCC_TARGET_PE", "");
  tcc_define_symbol(instance, "LIBTCC_AS_DLL", "");

  // i needed this define on Windows to get tcc_relocate in the DLL
  tcc_define_symbol(instance, "TCC_IS_NATIVE", "");

  tcc_set_output_type(instance, TCC_OUTPUT_MEMORY);

  // maybe add more source files?
  tcc_add_file(instance, "libtcc.c");

  int size = tcc_relocate(instance, (void*)0);
  void* memory = malloc(size);

  printf("need %d bytes\n", size);
  printf("relocating to %llx\n", (unsigned long long int)memory);
  tcc_relocate(instance, memory);

  // TCCState *tcc_new(void);
  using New = TCCState* (*)(void);
  New _new = (New)tcc_get_symbol(instance, "tcc_new");
  assert(_new != nullptr);

  // int tcc_set_output_type(TCCState *s, int output_type);
  using SetOutputType = int (*)(TCCState*, int);
  SetOutputType _set_output_type =
      (SetOutputType)tcc_get_symbol(instance, "tcc_set_output_type");
  assert(_set_output_type != nullptr);

  // int tcc_compile_string(TCCState *s, const char *buf);
  using CompileString = int (*)(TCCState*, const char*);
  CompileString _compile_string =
      (CompileString)tcc_get_symbol(instance, "tcc_compile_string");
  assert(_compile_string != nullptr);

  // int tcc_relocate(TCCState *s1, void *ptr);
  using Relocate = int (*)(TCCState*, void*);
  Relocate _relocate = (Relocate)tcc_get_symbol(instance, "tcc_relocate");
  assert(_relocate != nullptr);

  // void *tcc_get_symbol(TCCState *s, const char *name);
  using GetSymbol = void* (*)(TCCState*, const char*);
  GetSymbol _get_symbol = (GetSymbol)tcc_get_symbol(instance, "tcc_get_symbol");
  assert(_get_symbol != nullptr);

  // can i delete the instance now??
  // my experiments suggest no.
  // tcc_delete(instance);

  // use the new, relocated instance to compile something
  TCCState* born_in_memory = _new();
  assert(born_in_memory != nullptr);
  _set_output_type(born_in_memory, TCC_OUTPUT_MEMORY);
  _compile_string(born_in_memory, "int dec(int t) { return t - 1; }");
  _relocate(born_in_memory, TCC_RELOCATE_AUTO);
  using Foo = int (*)(int);
  Foo dec = (Foo)_get_symbol(born_in_memory, "dec");
  assert(dec != nullptr);
  printf("dec(2) == %d\b", dec(2));
}

 

am i on the right track here? any suggestions would help a lot. i think i could add the path to libtcc1-64.a, but i would rather compile all the .c files i need so there's no need to find libtcc1-64.a at runtime. 

 

-

 

option 1 (from Christian Jullien) is something that i don't quite understand. i am just failing to connect the dots given i the pseudocode:

 

// tcc1.cpp:
namespace tcc1 {
#include "libtcc.h"

  // does this mean i should compile libtcc as c++ (not c) under the tcc1 namespace?
};

// tcc2.cpp:
namespace tcc2 {
#include "libtcc.h"

   // does this mean i should compile libtcc as c++ (not c) AGAIN under the tcc2 namespace?

 // OR does this mean i should write a wrapper interface for libtcc here?
};

// main.cpp:
int main() {
  tcc1::TCCState* a = nullptr;
  char (*A)(int) = nullptr;
  assert((a = tcc1::tcc_new()) != nullptr);
  tcc2::TCCState* b =
      tcc2::tcc_new();  // remove this line to make the program work
}

also "But it may not be so simple. For some projects it worked flawlessly and failed for some others" is mysterious to me. my apologies for being too ignorant to put it together! a little more help on this option might help me a lot.

 

sorry for the long email.

 

-- karl

 

 

 

 

 

  

 

 

 

On Sat, May 25, 2019 at 12:30 AM Giovanni Mascellani <[hidden email]> wrote:

Hi,

Il 25/05/19 06:24, Christian Jullien ha scritto:
> Because Karl uses C++11, it may be /theoretically/ possible for him to
> load two different tcc instances having different C++ namespaces and
> compiled in two distinct translation units.

If you don't mind some quite dirty hacking (and if you mind it you
shouldn't probably use tcc), I also believe that you can have two
instances in the same address space by using the first one to compile
another one (or many others) and relocating them to different addresses.
Then each of them is a completely independent compiler with independent
state. Of course this means that you need tcc's source code at runtime.
Otherwise there is the old trick of just opening a pipe, forking and
then sending back the result.

Have fun, Giovanni.
--
Giovanni Mascellani <[hidden email]>
Postdoc researcher - Université Libre de Bruxelles

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

 

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

uso ewin
On Fri, Jun 21, 2019 at 4:58 AM Karl Yerkes <[hidden email]> wrote:

>
>
> Steve Fan --
>
> On Thu, Jun 20, 2019 at 7:14 PM Steve Fan <[hidden email]> wrote:
>>
>> I’m sorry to intervene in the matter, but as you look at the design of TCC, you will see that it is not designed for re-entrancy.
>
>
> yes. i understand. i am not trying to make it reentrant. i want to hot-recompile-swap a function with very low latency and i am willing to settle for a hack.
>
>
>> Foolish younger me, I used to have a hardworking re-entrant fork of TCC working but the one of the project owner denounced my idea, calling me to adapt TLS for each and every global variables instead of rewriting most of the TCC functions to add TCCState for them.
>
>
> good for you.. and that sucks.
>
>
>> TCC is just a hobbyist bone picked from OTCC by the legend Fabrice Bellard himself, but he has abandoned his child, TCC, ever since.
>
>
> yes. i get that.
>
>
>> I used to be like you, I want to research on TCC, but now I do warn you to not touch this egregious code again.
>
>
> i am not aiming to change the TCC source code. i actually only want to hack around what currently exists. that said, i might end up helping out somehow.
>
>
>> Go figure out your own parser. Maybe learn Bison or ANTLR for a basic parser, then read some paper about register allocation (which is a very bitchy problem for it was actually NP-Complete), read the specs for ELF, and read the respective assembly handbook for each and every codegen backend. You can reuse the ELF/PE code from TCC I reckon, but
>
>
> thank you. this is good advice and good info. i know parsing and grammars. i write my grammars/parsers in perl6 :)
>
> maybe generating x86, ARM, or LLVM-IR is not that hard and i should go do that. (right now it is black magic to me.)
>
> but my aim is actually to hack something together to further my aims in a different domain: sound.
>
> i am quite close with TCC.
>
>
>>
>> just don’t try to make anything happen to TCC, a dying project.
>
>
> i hear your warning. you may very well be right, but to me TCC seems... mature, not dying. maybe it's not going to be much more than what it is, but i bet it'll hold its value for a while.
>
> -- karl
>
>>
>>
>>
>> From: Karl Yerkes
>> Sent: Friday, 21 June 2019 9:24 AM
>> To: [hidden email]
>> Subject: Re: [Tinycc-devel] Two compilers at once
>>
>>
>>
>> thank you for your replies. your help and insights are much appreciated.
>>
>>
>>
>> I'm loving TCC!
>>
>>
>>
>> however, i've reached the limit of my current hot-swap function hack that uses two state-commingling TCC instances. after a while, the instances stop working properly and I get strange compile errors.
>>
>>
>>
>> so, i am interested in executing some hack to allow multiple independent TCC instances in the same application. i am certain that "the old trick of just opening a pipe, forking and
>>
>> then sending back the result" will not work for my purposes. if i can't get one of these hacks working, i have to go look at LLVM and cling again :/
>>
>>
>>
>> as i understand it, option 2 (from Giovanni Mascellani) is using libtcc to compile libtcc from source into memory. that sounds awesome. i spent most of today trying this on windows.. and also learning to compile TCC on windows. here's my attempt:
>>
>>
>>
>> // boot.cpp
>> //
>> // tcc version 0.9.27 (x86_64 Windows)
>> // install: c:/tcc
>> // include:
>> //   c:/tcc/include
>> //   c:/tcc/include/winapi
>> // libraries:
>> //   c:/tcc/lib
>> //   C:/Windows/system32
>> // libtcc1:
>> //   c:/tcc/lib/libtcc1-64.a
>> //
>> // build and run with:
>> //   cd tinycc
>> //   cl /MD boot.cpp c:\tcc\libtcc64.lib
>> //   boot.exe
>> //
>> //  fails like this:
>> //  need 457827 bytes
>> //  relocating to 21f0a402fd0
>> //  tcc: error: library 'libtcc1-64.a' not found
>> //  Assertion failed: dec != nullptr, file boot.cpp, line 69
>> //
>> #include "libtcc.h"
>>
>> #include <cassert>
>> #include <iostream>
>>
>> int main() {
>>   TCCState* instance = tcc_new();
>>
>>   // i'm on Windows 10 x64. what else do i need here?
>>   tcc_set_options(instance, "-shared");
>>   tcc_define_symbol(instance, "TCC_TARGET_X86_64", "");
>>   tcc_define_symbol(instance, "TCC_TARGET_PE", "");
>>   tcc_define_symbol(instance, "LIBTCC_AS_DLL", "");
>>
>>   // i needed this define on Windows to get tcc_relocate in the DLL
>>   tcc_define_symbol(instance, "TCC_IS_NATIVE", "");
>>
>>   tcc_set_output_type(instance, TCC_OUTPUT_MEMORY);
>>
>>   // maybe add more source files?
>>   tcc_add_file(instance, "libtcc.c");
>>
>>   int size = tcc_relocate(instance, (void*)0);
>>   void* memory = malloc(size);
>>
>>   printf("need %d bytes\n", size);
>>   printf("relocating to %llx\n", (unsigned long long int)memory);
>>   tcc_relocate(instance, memory);
>>
>>   // TCCState *tcc_new(void);
>>   using New = TCCState* (*)(void);
>>   New _new = (New)tcc_get_symbol(instance, "tcc_new");
>>   assert(_new != nullptr);
>>
>>   // int tcc_set_output_type(TCCState *s, int output_type);
>>   using SetOutputType = int (*)(TCCState*, int);
>>   SetOutputType _set_output_type =
>>       (SetOutputType)tcc_get_symbol(instance, "tcc_set_output_type");
>>   assert(_set_output_type != nullptr);
>>
>>   // int tcc_compile_string(TCCState *s, const char *buf);
>>   using CompileString = int (*)(TCCState*, const char*);
>>   CompileString _compile_string =
>>       (CompileString)tcc_get_symbol(instance, "tcc_compile_string");
>>   assert(_compile_string != nullptr);
>>
>>   // int tcc_relocate(TCCState *s1, void *ptr);
>>   using Relocate = int (*)(TCCState*, void*);
>>   Relocate _relocate = (Relocate)tcc_get_symbol(instance, "tcc_relocate");
>>   assert(_relocate != nullptr);
>>
>>   // void *tcc_get_symbol(TCCState *s, const char *name);
>>   using GetSymbol = void* (*)(TCCState*, const char*);
>>   GetSymbol _get_symbol = (GetSymbol)tcc_get_symbol(instance, "tcc_get_symbol");
>>   assert(_get_symbol != nullptr);
>>
>>   // can i delete the instance now??
>>   // my experiments suggest no.
>>   // tcc_delete(instance);
>>
>>   // use the new, relocated instance to compile something
>>   TCCState* born_in_memory = _new();
>>   assert(born_in_memory != nullptr);
>>   _set_output_type(born_in_memory, TCC_OUTPUT_MEMORY);
>>   _compile_string(born_in_memory, "int dec(int t) { return t - 1; }");
>>   _relocate(born_in_memory, TCC_RELOCATE_AUTO);
>>   using Foo = int (*)(int);
>>   Foo dec = (Foo)_get_symbol(born_in_memory, "dec");
>>   assert(dec != nullptr);
>>   printf("dec(2) == %d\b", dec(2));
>> }
>>
>>
>>
>> am i on the right track here? any suggestions would help a lot. i think i could add the path to libtcc1-64.a, but i would rather compile all the .c files i need so there's no need to find libtcc1-64.a at runtime.
>>
>>
>>
>> -
>>
>>
>>
>> option 1 (from Christian Jullien) is something that i don't quite understand. i am just failing to connect the dots given i the pseudocode:
>>
>>
>>
>> // tcc1.cpp:
>> namespace tcc1 {
>> #include "libtcc.h"
>>
>>   // does this mean i should compile libtcc as c++ (not c) under the tcc1 namespace?
>> };
>>
>> // tcc2.cpp:
>> namespace tcc2 {
>> #include "libtcc.h"
>>
>>    // does this mean i should compile libtcc as c++ (not c) AGAIN under the tcc2 namespace?
>>
>>  // OR does this mean i should write a wrapper interface for libtcc here?
>> };
>>
>> // main.cpp:
>> int main() {
>>   tcc1::TCCState* a = nullptr;
>>   char (*A)(int) = nullptr;
>>   assert((a = tcc1::tcc_new()) != nullptr);
>>   tcc2::TCCState* b =
>>       tcc2::tcc_new();  // remove this line to make the program work
>> }
>>
>> also "But it may not be so simple. For some projects it worked flawlessly and failed for some others" is mysterious to me. my apologies for being too ignorant to put it together! a little more help on this option might help me a lot.
>>
>>
>>
>> sorry for the long email.
>>
>>
>>
>> -- karl
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Sat, May 25, 2019 at 12:30 AM Giovanni Mascellani <[hidden email]> wrote:
>>
>> Hi,
>>
>> Il 25/05/19 06:24, Christian Jullien ha scritto:
>> > Because Karl uses C++11, it may be /theoretically/ possible for him to
>> > load two different tcc instances having different C++ namespaces and
>> > compiled in two distinct translation units.
>>
>> If you don't mind some quite dirty hacking (and if you mind it you
>> shouldn't probably use tcc), I also believe that you can have two
>> instances in the same address space by using the first one to compile
>> another one (or many others) and relocating them to different addresses.
>> Then each of them is a completely independent compiler with independent
>> state. Of course this means that you need tcc's source code at runtime.
>> Otherwise there is the old trick of just opening a pipe, forking and
>> then sending back the result.
>>
>> Have fun, Giovanni.
>> --
>> Giovanni Mascellani <[hidden email]>
>> Postdoc researcher - Université Libre de Bruxelles
>>
>> _______________________________________________
>> Tinycc-devel mailing list
>> [hidden email]
>> https://lists.nongnu.org/mailman/listinfo/tinycc-devel
>>
>>
>>
>> _______________________________________________
>> Tinycc-devel mailing list
>> [hidden email]
>> https://lists.nongnu.org/mailman/listinfo/tinycc-devel
>
> _______________________________________________
> Tinycc-devel mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Stupide question, but can't you just use 2 instances of tcc in 2
diferent process ?
Maybe a simpler hack, instead of making it reentrent would be to add
optionaly _Thread_local
attribute to tcc globals and execute the 2 instances in 2 diferent threads.

Matthias,

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Steven G. Messervey
In reply to this post by Karl Yerkes


On Friday, May 24, 2019, 1:48:24 PM EDT, Karl Yerkes <[hidden email]> wrote:


I would like to have two compilers active at the same time so i can recompile and hot-swap a function. ;On my journey, I noticed that making a new, second compiler before the first one compiles leads to strange behaviour. I am running macOS 10.14.5 with tcc 0.9.27.

// compile and run like this:
//
//   c++ -std=c++11 -ltcc tinycc-devel-example.cpp ; and ./a.out
//
// the `tcc_compile_string` step will fail with this error:
//
//   <string>: error: missing #endif
//
#include <cassert>
#include <cstdio>
#include "libtcc.h"

int main() {
  TCCState* a = nullptr;
  char (*A)(int) = nullptr;
  assert((a = tcc_new()) != nullptr);
  TCCState* b = tcc_new();  // remove this line to make the program work
  assert(tcc_set_output_type(a, TCC_OUTPUT_MEMORY) == 0);
  assert(tcc_compile_string(a, "char foo(int t) { return (char)t; }") != -1);
  assert(tcc_relocate(a, TCC_RELOCATE_AUTO) >= 0);
  assert((A = (char (*)(int))tcc_get_symbol(a, "foo")) != nullptr);
  printf("%d = A(0)\n", A(0));
}


As long as I make the second compiler after the first one compiles something, things work. is this a bug? Is using two compilers unsupported or prohibited?

-- karl


_______________________________________________
Tinycc-devel mailing list
[hidden email]





Perhaps we've been coming at this from the wrong direction;
I'm not quite sure one would need two compiler instances to recompile a single function.

TCC allows you to allocate memory for an object/function/program yourself- you call tcc_relocate with NULL for the 'ptr' parameter, and it returns
the number of bytes needed to hold the object.
This means that that memory is no longer bound to or managed by TCC.

I know when I've adapted TCC to cache function handlers, I just update the pointer to the handler function and then
free() the old pointer; but this was single-threaded use, and I was disposing of TCC in between (re)compilations.

For multi-threaded use, I believe you would just need a mutex to synchronize access the pointer.

Have you tried this? Or is there some other stuff your code is doing that needs two compiler instances?

-Steve

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Karl Yerkes
In reply to this post by uso ewin

On Fri, Jun 21, 2019 at 2:12 AM uso ewin <[hidden email]> wrote:
On Fri, Jun 21, 2019 at 4:58 AM Karl Yerkes <[hidden email]> wrote:
>
>
> Steve Fan --
>
> On Thu, Jun 20, 2019 at 7:14 PM Steve Fan <[hidden email]> wrote:
>>
>> I’m sorry to intervene in the matter, but as you look at the design of TCC, you will see that it is not designed for re-entrancy.
>
>
> yes. i understand. i am not trying to make it reentrant. i want to hot-recompile-swap a function with very low latency and i am willing to settle for a hack.
>
>
>> Foolish younger me, I used to have a hardworking re-entrant fork of TCC working but the one of the project owner denounced my idea, calling me to adapt TLS for each and every global variables instead of rewriting most of the TCC functions to add TCCState for them.
>
>
> good for you.. and that sucks.
>
>
>> TCC is just a hobbyist bone picked from OTCC by the legend Fabrice Bellard himself, but he has abandoned his child, TCC, ever since.
>
>
> yes. i get that.
>
>
>> I used to be like you, I want to research on TCC, but now I do warn you to not touch this egregious code again.
>
>
> i am not aiming to change the TCC source code. i actually only want to hack around what currently exists. that said, i might end up helping out somehow.
>
>
>> Go figure out your own parser. Maybe learn Bison or ANTLR for a basic parser, then read some paper about register allocation (which is a very bitchy problem for it was actually NP-Complete), read the specs for ELF, and read the respective assembly handbook for each and every codegen backend. You can reuse the ELF/PE code from TCC I reckon, but
>
>
> thank you. this is good advice and good info. i know parsing and grammars. i write my grammars/parsers in perl6 :)
>
> maybe generating x86, ARM, or LLVM-IR is not that hard and i should go do that. (right now it is black magic to me.)
>
> but my aim is actually to hack something together to further my aims in a different domain: sound.
>
> i am quite close with TCC.
>
>
>>
>> just don’t try to make anything happen to TCC, a dying project.
>
>
> i hear your warning. you may very well be right, but to me TCC seems... mature, not dying. maybe it's not going to be much more than what it is, but i bet it'll hold its value for a while.
>
> -- karl
>
>>
>>
>>
>> From: Karl Yerkes
>> Sent: Friday, 21 June 2019 9:24 AM
>> To: [hidden email]
>> Subject: Re: [Tinycc-devel] Two compilers at once
>>
>>
>>
>> thank you for your replies. your help and insights are much appreciated.
>>
>>
>>
>> I'm loving TCC!
>>
>>
>>
>> however, i've reached the limit of my current hot-swap function hack that uses two state-commingling TCC instances. after a while, the instances stop working properly and I get strange compile errors.
>>
>>
>>
>> so, i am interested in executing some hack to allow multiple independent TCC instances in the same application. i am certain that "the old trick of just opening a pipe, forking and
>>
>> then sending back the result" will not work for my purposes. if i can't get one of these hacks working, i have to go look at LLVM and cling again :/
>>
>>
>>
>> as i understand it, option 2 (from Giovanni Mascellani) is using libtcc to compile libtcc from source into memory. that sounds awesome. i spent most of today trying this on windows.. and also learning to compile TCC on windows. here's my attempt:
>>
>>
>>
>> // boot.cpp
>> //
>> // tcc version 0.9.27 (x86_64 Windows)
>> // install: c:/tcc
>> // include:
>> //   c:/tcc/include
>> //   c:/tcc/include/winapi
>> // libraries:
>> //   c:/tcc/lib
>> //   C:/Windows/system32
>> // libtcc1:
>> //   c:/tcc/lib/libtcc1-64.a
>> //
>> // build and run with:
>> //   cd tinycc
>> //   cl /MD boot.cpp c:\tcc\libtcc64.lib
>> //   boot.exe
>> //
>> //  fails like this:
>> //  need 457827 bytes
>> //  relocating to 21f0a402fd0
>> //  tcc: error: library 'libtcc1-64.a' not found
>> //  Assertion failed: dec != nullptr, file boot.cpp, line 69
>> //
>> #include "libtcc.h"
>>
>> #include <cassert>
>> #include <iostream>
>>
>> int main() {
>>   TCCState* instance = tcc_new();
>>
>>   // i'm on Windows 10 x64. what else do i need here?
>>   tcc_set_options(instance, "-shared");
>>   tcc_define_symbol(instance, "TCC_TARGET_X86_64", "");
>>   tcc_define_symbol(instance, "TCC_TARGET_PE", "");
>>   tcc_define_symbol(instance, "LIBTCC_AS_DLL", "");
>>
>>   // i needed this define on Windows to get tcc_relocate in the DLL
>>   tcc_define_symbol(instance, "TCC_IS_NATIVE", "");
>>
>>   tcc_set_output_type(instance, TCC_OUTPUT_MEMORY);
>>
>>   // maybe add more source files?
>>   tcc_add_file(instance, "libtcc.c");
>>
>>   int size = tcc_relocate(instance, (void*)0);
>>   void* memory = malloc(size);
>>
>>   printf("need %d bytes\n", size);
>>   printf("relocating to %llx\n", (unsigned long long int)memory);
>>   tcc_relocate(instance, memory);
>>
>>   // TCCState *tcc_new(void);
>>   using New = TCCState* (*)(void);
>>   New _new = (New)tcc_get_symbol(instance, "tcc_new");
>>   assert(_new != nullptr);
>>
>>   // int tcc_set_output_type(TCCState *s, int output_type);
>>   using SetOutputType = int (*)(TCCState*, int);
>>   SetOutputType _set_output_type =
>>       (SetOutputType)tcc_get_symbol(instance, "tcc_set_output_type");
>>   assert(_set_output_type != nullptr);
>>
>>   // int tcc_compile_string(TCCState *s, const char *buf);
>>   using CompileString = int (*)(TCCState*, const char*);
>>   CompileString _compile_string =
>>       (CompileString)tcc_get_symbol(instance, "tcc_compile_string");
>>   assert(_compile_string != nullptr);
>>
>>   // int tcc_relocate(TCCState *s1, void *ptr);
>>   using Relocate = int (*)(TCCState*, void*);
>>   Relocate _relocate = (Relocate)tcc_get_symbol(instance, "tcc_relocate");
>>   assert(_relocate != nullptr);
>>
>>   // void *tcc_get_symbol(TCCState *s, const char *name);
>>   using GetSymbol = void* (*)(TCCState*, const char*);
>>   GetSymbol _get_symbol = (GetSymbol)tcc_get_symbol(instance, "tcc_get_symbol");
>>   assert(_get_symbol != nullptr);
>>
>>   // can i delete the instance now??
>>   // my experiments suggest no.
>>   // tcc_delete(instance);
>>
>>   // use the new, relocated instance to compile something
>>   TCCState* born_in_memory = _new();
>>   assert(born_in_memory != nullptr);
>>   _set_output_type(born_in_memory, TCC_OUTPUT_MEMORY);
>>   _compile_string(born_in_memory, "int dec(int t) { return t - 1; }");
>>   _relocate(born_in_memory, TCC_RELOCATE_AUTO);
>>   using Foo = int (*)(int);
>>   Foo dec = (Foo)_get_symbol(born_in_memory, "dec");
>>   assert(dec != nullptr);
>>   printf("dec(2) == %d\b", dec(2));
>> }
>>
>>
>>
>> am i on the right track here? any suggestions would help a lot. i think i could add the path to libtcc1-64.a, but i would rather compile all the .c files i need so there's no need to find libtcc1-64.a at runtime.
>>
>>
>>
>> -
>>
>>
>>
>> option 1 (from Christian Jullien) is something that i don't quite understand. i am just failing to connect the dots given i the pseudocode:
>>
>>
>>
>> // tcc1.cpp:
>> namespace tcc1 {
>> #include "libtcc.h"
>>
>>   // does this mean i should compile libtcc as c++ (not c) under the tcc1 namespace?
>> };
>>
>> // tcc2.cpp:
>> namespace tcc2 {
>> #include "libtcc.h"
>>
>>    // does this mean i should compile libtcc as c++ (not c) AGAIN under the tcc2 namespace?
>>
>>  // OR does this mean i should write a wrapper interface for libtcc here?
>> };
>>
>> // main.cpp:
>> int main() {
>>   tcc1::TCCState* a = nullptr;
>>   char (*A)(int) = nullptr;
>>   assert((a = tcc1::tcc_new()) != nullptr);
>>   tcc2::TCCState* b =
>>       tcc2::tcc_new();  // remove this line to make the program work
>> }
>>
>> also "But it may not be so simple. For some projects it worked flawlessly and failed for some others" is mysterious to me. my apologies for being too ignorant to put it together! a little more help on this option might help me a lot.
>>
>>
>>
>> sorry for the long email.
>>
>>
>>
>> -- karl
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Sat, May 25, 2019 at 12:30 AM Giovanni Mascellani <[hidden email]> wrote:
>>
>> Hi,
>>
>> Il 25/05/19 06:24, Christian Jullien ha scritto:
>> > Because Karl uses C++11, it may be /theoretically/ possible for him to
>> > load two different tcc instances having different C++ namespaces and
>> > compiled in two distinct translation units.
>>
>> If you don't mind some quite dirty hacking (and if you mind it you
>> shouldn't probably use tcc), I also believe that you can have two
>> instances in the same address space by using the first one to compile
>> another one (or many others) and relocating them to different addresses.
>> Then each of them is a completely independent compiler with independent
>> state. Of course this means that you need tcc's source code at runtime.
>> Otherwise there is the old trick of just opening a pipe, forking and
>> then sending back the result.
>>
>> Have fun, Giovanni.
>> --
>> Giovanni Mascellani <[hidden email]>
>> Postdoc researcher - Université Libre de Bruxelles
>>
>> _______________________________________________
>> Tinycc-devel mailing list
>> [hidden email]
>> https://lists.nongnu.org/mailman/listinfo/tinycc-devel
>>
>>
>>
>> _______________________________________________
>> Tinycc-devel mailing list
>> [hidden email]
>> https://lists.nongnu.org/mailman/listinfo/tinycc-devel
>
> _______________________________________________
> Tinycc-devel mailing list
> [hidden email]
> https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Stupide question, but can't you just use 2 instances of tcc in 2
diferent process ?
Maybe a simpler hack, instead of making it reentrent would be to add
optionaly _Thread_local
attribute to tcc globals and execute the 2 instances in 2 diferent threads.

Matthias,

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Karl Yerkes
In reply to this post by Steven G. Messervey

Perhaps we've been coming at this from the wrong direction;
I'm not quite sure one would need two compiler instances to recompile a single function.

as far as i can tell "recompiling a function" is not a feature of libtcc. you get "error: 'foo' defined twice" as you would with other compilers. there's no way to  delete a compiled function.
 

TCC allows you to allocate memory for an object/function/program yourself- you call tcc_relocate with NULL for the 'ptr' parameter, and it returns
the number of bytes needed to hold the object.

you can relocate, but you cannot allocate ahead of time. also, in my experience, the compiled function is still dependent on the tcc instance that compiled it even after a relocation. delete the instance that compiled foo and foo will sometimes crash.
 
This means that that memory is no longer bound to or managed by TCC.

not in my experience. look here:



I know when I've adapted TCC to cache function handlers, I just update the pointer to the handler function and then
free() the old pointer; but this was single-threaded use, and I was disposing of TCC in between (re)compilations.

For multi-threaded use, I believe you would just need a mutex to synchronize access the pointer.

Have you tried this? Or is there some other stuff your code is doing that needs two compiler instances?

i have no need of two compilers other than as a hack to recompile a function.


-Steve
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Two compilers at once

Steven G. Messervey
Of course it doesn't,  silly of me.
Is there any reason why you can't destroy 
& recreate TCC instances on demand?
(This was the bit I was forgetting in my
handlers)

On Tue, Jun 25, 2019 at 7:43 PM, Karl Yerkes
_______________________________________________
Tinycc-devel mailing list
[hidden email]

https://lists.nongnu.org/mailman/listinfo/tinycc-devel



_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel