Is there a way to delay the choice of calling convention without leaving too much work to the linker?

56 Views Asked by At

TL;DR:

  • Is there a way to specify a calling convention/a way a function will retrieve its argument/the return value(s) of another function after compilation?
  • Is it possible to generate assembly/machine code that can later be further optimized according to context?
  • If these are possible, how hard would it be to do relying on widely used/standard tools (like gcc or clang for C/C++), and supporting all compiled languages?

I'm currently working on a sort of code engine (open-source) that I want to make as polyvalent as possible, the goal being having a bunch of totally independent mods that can be linked together with an intricate "piping" system that manages control flow and data exchange between mods, with one notable feature being the ability to create those linkings at runtime. Polyvalence, to me, means that high performance should also be reachable using the engine, albeit probably with a little more work then "normal" use of the engine.

For various reasons, I came to the conclusion that mods should probably come in some form of assembler code (most likely generated by compiling some source in an unspecified language, the original idea was having dynamic libraries loaded using dlopen). I'm currently exploring the limits of the idea (in thought experiments), and among all my considerations, one problem is coming back more often then the others : I need mods to be able to handle any kind of calling conventions, and this mainly because of 2 reasons;

  • I don't want to assume I have enough knowledge to know the best calling convention/way to pass data between mods on every possible architecture, so I want mods to be unaware of the way they are going to retrieve their data.
  • In the current specification, mods can delegate some task to another in the middle of their control flow, and should be able to retrieve an arbitrary amount of data once they are returned to. This can't be done with current calling conventions, unless passing a dynamically allocated array, which creates performance concerns.

A few other considerations are closely linked to this :

  • I want mods to be able to make arbitrary optimizations (for example by generating a new mods by inlining one mod into another)
  • Since all of this should be possible at runtime, I'd really like it to be fast, so link-time code generation is probably unadvised.
  • Mods could be able to be linked to an "implementation library" before the program is launched (in which case fast compilation isn't needed), which simplifies the task of the main program by allowing it to simply call dlopen like devised originally, or the linking be generated at runtime by a mod (in which case fast compilation is needed).

It should also be keept in mind that all of these features should be compatible with most/all current compiled languages. I'm aware that what I'm asking for may be impossible, but I want to have a clear idea of what is and what isn't possible, and why, before choosing what features to keep.


I already started thinking of a way to implement this, but it's incomplete and has a bunch of problems:

Instead of arguments being passed through the argument lists, function would keep their arguments as stack variable, and initialize them by calling a function-like symbole (something like initialize_input_data_pipe(&variable, "pipe name")) which will be provided by the implementation.

A few problems that I've identified with this method :

  • Ignoring the standard way of passing argument can lead to bloated source code, bugs, etc.
  • For performance reasons, when this function is linked, it should be inlined, but, to my knowledge, this isn't possible with dynamic libraries, and by using static libraries and link-time optimization/link-time code generation, would be quite slow.
0

There are 0 best solutions below