tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Two compilers at once


From: Karl Yerkes
Subject: Re: [Tinycc-devel] Two compilers at once
Date: Thu, 20 Jun 2019 18:23:24 -0700

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 <address@hidden> 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 <address@hidden>
Postdoc researcher - Université Libre de Bruxelles

_______________________________________________
Tinycc-devel mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

reply via email to

[Prev in Thread] Current Thread [Next in Thread]