0

I am working on a project for which I need to "combine" code distributed over multiple C++ files into one file. Due to the nature of the project, I only need one entry function (the function that will be defined as the top function in the Xilinx High-Level-Synthesis software -> see context below). The signature of this function needs to be preserved in the transformation. Whether other functions from other files simply get copied into the file and get called as a subroutine or are inlined does not matter. I think due to variable and function scopes simply concatenating the files will not work.

Since I did not write the C++ code myself and it is quite comprehensive, I am looking for a way to do the transformation automatically. The possibilities I am aware of to do this are the following:

  1. Compile the code to LLVM IR with inlining flags and use a C++/C backend to turn the LLVM code into the source language again. This will result in bad source code and require either an old release of Clang and LLVM or another backend like JuliaComputing. 1
  2. The other option would be developing a tool that relies on using the AST and a library like LibTooling to restructure the code. This option would probably result in better code and put everything into one file without the unnecessary inlining. 2 However, this options seems too complicated to put the all the code into one file.

Hence my question: Are you aware of a better or simply alternative approach to solve this problem?

Context: The project aims to run some of the code on a Xilinx FPGA and the Vitis High-Level-Synthesis tool requires all code that is to be made into a single IP block to be contained in a single file. That is why I need to realise this transformation.

Sam
  • 207
  • 1
  • 4
  • 12
  • 3
    What exactly do you mean by "combine code"? To me that sounds like you just want to concatenate the files together (which can easily be done with a bash/batch/whatever language you want to use script) – UnholySheep Jan 15 '22 at 12:09
  • Alternatively you may be looking for something like Unity builds? https://en.wikipedia.org/wiki/Unity_build – UnholySheep Jan 15 '22 at 12:15
  • @UnholySheep I am not sure whether concatenation would work as variable and function scopes, macros, etc. might cause problems. I tried to expand on this in the question a bit. – Sam Jan 15 '22 at 14:26
  • @Sam: interesting question. Can you please briefly add why would you need to do that for HLS? I'm interested in HLS part. AFAIK, for HLS tool you would in any case need to restructure and transform the code in order to make it synthesizable on FPGA. And that transformation requires manual effort. It's not a push-button approach for Vitis HLS. – BZKN Jan 15 '22 at 14:36
  • 1
    Simple concatenation probably won't work, but a custom-written concatenator will probably work and will have two big advantages: ① it's simpler and ② the resulting code is more likely to be programmer-friendly. I have written such a thing, I used one C file that included the files I wanted, and I added #define directives before/between the #include directives to work around the conflicts. The debugger worked well with the result (it found the original/right source). I suggest a time-boxed attempt to do it this way. If you find yourself needing >100 #defines it's time to abort the attempt. – arnt Jan 15 '22 at 14:51
  • In general: There's much to be said for solutions that require neither if/then nor loops, even if they are a little hacky. – arnt Jan 15 '22 at 14:54
  • 3
    This is a hard problem. While one can easily gather classes from the original source files that you are interested in, the source code is preprocessor code. You will then need a separate phase to chase down referenced preprocessed code in a special-purpose preprocessor, not easy because parsing of preprocessed code contains minimal structure: preprocessor directive sections, and source code complete flat--a list of tokens. Doable, with difficulty. – kaby76 Jan 15 '22 at 15:47
  • The problems mentioned here are not critical. AFAIK, no buildsystems that support jumbo builds actually fixed them. The most common (if not the only one) workaround is to let users split files themself. – Osyotr Jan 15 '22 at 17:52
  • 1
    You can check these two links http://www.martinecker.com/rudebuild/about/ https://devblogs.microsoft.com/cppblog/support-for-unity-jumbo-files-in-visual-studio-2017-15-8-experimental/ – Sebastian Jan 15 '22 at 20:18
  • @BKN The code I am trying to synthesize into IP Cores is a library that contains much code I do not need. If I could write a script that does the inlining and at the same only includes the functions, classes, etc. in the call stack of the functions I need, I would save some time and only need to define pragmas, etc. for the resulting code. In my mind, that seemed to be the fastest way; I am not experienced with Vitis HLS though. – Sam Jan 18 '22 at 09:10
  • @kaby76 Thank you, that gives me some perspective on how hard it will be. – Sam Jan 18 '22 at 09:11
  • @Sebastian Thank you; I will check out the links you suggested – Sam Jan 18 '22 at 09:12
  • @arnt Thank you for the suggestion - it sounds promising. I don't have much experience with writing code like that – can you think of any git-repo or article explaining this in more detail? – Sam Jan 18 '22 at 09:15
  • 1
    Write two files, a.c and b.c, each of which contains the single line `static int foo = 42;`. Now write a third file, c.c, containing the two lines `#include "a.c"` and `#include "b.c"`. Compiling c.c will fail. By inspecting the error message you can guess that inserting `#define foo bar` as a new middle line in c.c will resolve the error. Doing this for real code is very tiresome because there may be many conflicts, but not complicated. Sometimes changing the order of the includes helps. – arnt Jan 18 '22 at 09:23
  • 1
    Perhaps you can somehow automatically list all identifiers the compiler generated for each .cpp file and autogenerate defines to be used after it and before the next .cpp file. Or it will be enough to do it only for those identifiers the linker throws errors. The tools I linked should do that (all the steps) automatically. – Sebastian Jan 18 '22 at 10:50
  • @Sebastian Thank you, that sounds great - I'll give it a try unless my current, not so elegant, approach works soon. – Sam Jan 18 '22 at 11:18
  • Does anybody know, if re#defining standard library symbols and including them a second time could lead to problems? Or are all those in namespaces? – Sebastian Jan 18 '22 at 11:43

0 Answers0