1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
5     ---------------------------------------------------------------------
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  ************************************************************************
20  ************************************************************************/
21 
22 #ifndef LLVM_DSP_AUX_H
23 #define LLVM_DSP_AUX_H
24 
25 #include <map>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 #include "faust/dsp/dsp.h"
31 #include "faust/gui/CInterface.h"
32 #include "faust/gui/JSONUIDecoder.h"
33 #include "faust/gui/meta.h"
34 
35 #include "dsp_aux.hh"
36 #include "dsp_factory.hh"
37 #include "export.hh"
38 #include "smartpointer.h"
39 #include "timing.hh"
40 
41 #include <llvm/ExecutionEngine/ObjectCache.h>
42 #include <llvm/Support/MemoryBuffer.h>
43 
44 #define LLVM_MAX_OPT_LEVEL 5
45 
46 #define STREAM_ERROR std::error_code
47 #define MEMORY_BUFFER llvm::MemoryBufferRef
48 #define MEMORY_BUFFER_GET(buffer) (buffer.getBuffer())
49 #define MEMORY_BUFFER_GET_REF(buffer) (buffer->get()->getMemBufferRef())
50 #define MEMORY_BUFFER_CREATE(stringref) (llvm::MemoryBufferRef(stringref, ""))
51 #define ModulePTR std::unique_ptr<Module>
52 #define MovePTR(ptr) std::move(ptr)
53 #define PASS_MANAGER legacy::PassManager
54 #define FUNCTION_PASS_MANAGER legacy::FunctionPassManager
55 #define sysfs_binary_flag sys::fs::OF_None
56 #define OwningPtr std::unique_ptr
57 #define llvmcreatePrintModulePass(out) createPrintModulePass(out)
58 #define GET_CPU_NAME llvm::sys::getHostCPUName().str()
59 
60 #define BUFFER_SIZE 1024
61 #define SAMPLE_RATE 44100
62 #define MAX_CHAN 64
63 #define MAX_SOUNDFILE_PARTS 256
64 
65 #ifdef _MSC_VER
66 #define PRE_PACKED_STRUCTURE __pragma(pack(push, 1))
67 #define POST_PACKED_STRUCTURE \
68 ;                         \
69 __pragma(pack(pop))
70 #else
71 #define PRE_PACKED_STRUCTURE
72 #define POST_PACKED_STRUCTURE __attribute__((__packed__))
73 #endif
74 
75 PRE_PACKED_STRUCTURE
76 struct Soundfile {
77     double** fBuffers; // use the largest size to cover 'float' and 'double' cases
78     int* fLength;      // length of each part
79     int* fSR;          // sample rate of each part
80     int* fOffset;      // offset of each part in the global buffer
81     int fChannels;     // max number of channels of all concatenated files
82     bool fIsDouble;
83 
SoundfileSoundfile84     Soundfile(int max_chan)
85     {
86         fBuffers = new double*[max_chan];
87         fLength  = new int[MAX_SOUNDFILE_PARTS];
88         fSR      = new int[MAX_SOUNDFILE_PARTS];
89         fOffset  = new int[MAX_SOUNDFILE_PARTS];
90 
91         for (int part = 0; part < MAX_SOUNDFILE_PARTS; part++) {
92             fLength[part] = BUFFER_SIZE;
93             fSR[part]     = SAMPLE_RATE;
94             fOffset[part] = 0;
95         }
96 
97         // Allocate 1 channel
98         fChannels   = 1;
99         fBuffers[0] = new double[BUFFER_SIZE];
100         faustassert(fBuffers[0]);
101         memset(fBuffers[0], 0, BUFFER_SIZE * sizeof(double));
102 
103         // Share the same buffer for all other channels so that we have max_chan channels available
104         for (int chan = fChannels; chan < max_chan; chan++) {
105             fBuffers[chan] = fBuffers[0];
106         }
107     }
108 
~SoundfileSoundfile109     ~Soundfile()
110     {
111         // Free the real channels only
112         for (int chan = 0; chan < fChannels; chan++) {
113             delete[] fBuffers[chan];
114         }
115         delete[] fBuffers;
116         delete[] fLength;
117         delete[] fSR;
118         delete[] fOffset;
119     }
120 
121 } POST_PACKED_STRUCTURE;
122 
123 extern Soundfile* dynamic_defaultsound;
124 
125 // namespace llvm
126 namespace llvm {
127 class LLVMContext;
128 class ExecutionEngine;
129 class Module;
130 }  // namespace llvm
131 
132 class llvm_dsp_factory;
133 
134 // Public C++ interface
135 
136 class EXPORT llvm_dsp : public dsp {
137    private:
138     llvm_dsp_factory* fFactory;
139     JSONUIDecoderBase* fDecoder;
140     dsp_imp*          fDSP;
141 
142    public:
143     llvm_dsp(llvm_dsp_factory* factory, dsp_imp* dsp);
144     virtual ~llvm_dsp();
145 
146     void operator delete(void* ptr);
147 
148     virtual int getNumInputs();
149 
150     virtual int getNumOutputs();
151 
152     virtual void buildUserInterface(UI* ui_interface);
153 
154     virtual void buildUserInterface(UIGlue* glue);
155 
156     virtual int getSampleRate();
157 
158     virtual void init(int sample_rate);
159 
160     virtual void instanceInit(int sample_rate);
161 
162     virtual void instanceConstants(int sample_rate);
163 
164     virtual void instanceResetUserInterface();
165 
166     virtual void instanceClear();
167 
168     virtual void classInit(int sample_rate);
169 
170     virtual llvm_dsp* clone();
171 
172     virtual void metadata(Meta* m);
173 
174     virtual void metadata(MetaGlue* glue);
175 
176     virtual void compute(int count, FAUSTFLOAT** input, FAUSTFLOAT** output);
177 };
178 
179 class FaustObjectCache : public llvm::ObjectCache {
180    private:
181     std::string fMachineCode;
182 
anchor()183     virtual void anchor() {}
184 
185    public:
FaustObjectCache(const std::string & machine_code="")186     FaustObjectCache(const std::string& machine_code = "") : fMachineCode(machine_code) {}
187 
~FaustObjectCache()188     virtual ~FaustObjectCache() {}
189 
notifyObjectCompiled(const llvm::Module * M,llvm::MemoryBufferRef Obj)190     virtual void notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj)
191     {
192         fMachineCode = Obj.getBuffer().str();
193     }
194 
getObject(const llvm::Module * M)195     virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M)
196     {
197         return (fMachineCode == "") ? nullptr : llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(fMachineCode));
198     }
199 
getMachineCode()200     std::string getMachineCode() { return fMachineCode; }
201 };
202 
203 typedef class faust_smartptr<llvm_dsp_factory> SDsp_factory;
204 
205 // Internal API
206 typedef void (* deleteDspFun) (dsp_imp* dsp);
207 typedef void (* allocateDspFun) (dsp_imp* dsp);
208 typedef const char* (* getJSONFun) ();
209 
210 class llvm_dsp_factory_aux : public dsp_factory_imp {
211     friend class llvm_dsp;
212     friend class llvm_dsp_factory;
213 
214    protected:
215     llvm::ExecutionEngine*  fJIT;
216     FaustObjectCache*       fObjectCache;
217     llvm::Module*           fModule;
218     llvm::LLVMContext*      fContext;
219     JSONUIDecoderBase*      fDecoder;
220 
221     int         fOptLevel;
222     std::string fTarget;
223     std::string fClassName;
224     std::string fTypeName;
225 
226     allocateDspFun   fAllocate;
227     destroyDspFun    fDestroy;
228     initFun          fInstanceConstants;
229     instanceClearFun fInstanceClear;
230     classInitFun     fClassInit;
231     computeFun       fCompute;
232     getJSONFun       fGetJSON;
233 
234     uint64_t loadOptimize(const std::string& function);
235 
236     void init(const std::string& dsp_name, const std::string& type_name);
237 
238     bool crossCompile(const std::string& target);
239 
240     static void LLVMFatalErrorHandler(const char* reason);
241 
242     void startLLVMLibrary();
243     void stopLLVMLibrary();
244 
245     std::string writeDSPFactoryToMachineAux(const std::string& target);
246 
checkDecoder()247     void checkDecoder()
248     {
249         if (!fDecoder) fDecoder = createJSONUIDecoder(fGetJSON());
250     }
251 
252    public:
253     llvm_dsp_factory_aux(const std::string& sha_key, llvm::Module* module, llvm::LLVMContext* context,
254                          const std::string& target, int opt_level = 0);
255 
256     llvm_dsp_factory_aux(const std::string& sha_key, const std::string& machine_code, const std::string& target);
257 
258     virtual ~llvm_dsp_factory_aux();
259 
260     std::string              getCompileOptions();
261     std::vector<std::string> getLibraryList();
262     std::vector<std::string> getIncludePathnames();
263 
264     virtual bool initJIT(std::string& error_msg);
265     bool         initJITAux();
266 
267     static llvm_dsp_factory* readDSPFactoryFromMachineAux(MEMORY_BUFFER buffer, const std::string& target,
268                                                           std::string& error_msg);
269 
270     // Bitcode
writeDSPFactoryToBitcode()271     virtual std::string writeDSPFactoryToBitcode() { return ""; }
272 
writeDSPFactoryToBitcodeFile(const std::string & bit_code_path)273     virtual bool writeDSPFactoryToBitcodeFile(const std::string& bit_code_path) { return false; }
274 
275     // IR
writeDSPFactoryToIR()276     virtual std::string writeDSPFactoryToIR() { return ""; }
277 
writeDSPFactoryToIRFile(const std::string & ir_code_path)278     virtual bool writeDSPFactoryToIRFile(const std::string& ir_code_path) { return false; }
279 
280     // Machine
281     virtual std::string writeDSPFactoryToMachine(const std::string& target);
282 
283     virtual bool writeDSPFactoryToMachineFile(const std::string& machine_code_path, const std::string& target);
284 
285     // Object
writeDSPFactoryToObjectcodeFile(const std::string & object_code_path,const std::string & target)286     virtual bool writeDSPFactoryToObjectcodeFile(const std::string& object_code_path, const std::string& target)
287     {
288         return false;
289     }
290 
291     std::string getTarget();
setTarget(const std::string & target)292     void        setTarget(const std::string& target) { fTarget = target; }
293 
294     int  getOptlevel();
setOptlevel(int opt_level)295     void setOptlevel(int opt_level)
296     {
297         fOptLevel = ((opt_level == -1) || (opt_level > LLVM_MAX_OPT_LEVEL)) ? LLVM_MAX_OPT_LEVEL : opt_level;
298     }
299 
setClassName(const std::string & class_name)300     void setClassName(const std::string& class_name) { fClassName = class_name; }
301 
302     llvm_dsp* createDSPInstance(dsp_factory* factory);
303 
304     void metadata(Meta* m);
305 
306     void metadata(MetaGlue* glue);
307 
308     static int gInstance;
309 
310     static dsp_factory_table<SDsp_factory> gLLVMFactoryTable;
311 };
312 
313 // Public C++ interface
314 
315 class EXPORT llvm_dsp_factory : public dsp_factory, public faust_smartable {
316    private:
317     llvm_dsp_factory_aux* fFactory;
318 
~llvm_dsp_factory()319     virtual ~llvm_dsp_factory() { delete fFactory; }
320 
321    public:
llvm_dsp_factory(llvm_dsp_factory_aux * factory)322     llvm_dsp_factory(llvm_dsp_factory_aux* factory) : fFactory(factory) {}
323 
getName()324     std::string getName() { return fFactory->getName(); }
325 
getSHAKey()326     std::string getSHAKey() { return fFactory->getSHAKey(); }
setSHAKey(std::string sha_key)327     void        setSHAKey(std::string sha_key) { fFactory->setSHAKey(sha_key); }
328 
getDSPCode()329     std::string getDSPCode() { return fFactory->getDSPCode(); }
setDSPCode(std::string code)330     void        setDSPCode(std::string code) { fFactory->setDSPCode(code); }
331 
getCompileOptions()332     std::string getCompileOptions() { return fFactory->getCompileOptions(); }
333 
getLibraryList()334     std::vector<std::string> getLibraryList() { return fFactory->getLibraryList(); }
getIncludePathnames()335     std::vector<std::string> getIncludePathnames() { return fFactory->getIncludePathnames(); }
336 
getTarget()337     std::string getTarget() { return fFactory->getTarget(); }
338 
339     llvm_dsp* createDSPInstance();
340 
setMemoryManager(dsp_memory_manager * manager)341     void                setMemoryManager(dsp_memory_manager* manager) { fFactory->setMemoryManager(manager); }
getMemoryManager()342     dsp_memory_manager* getMemoryManager() { return fFactory->getMemoryManager(); }
343 
setMemoryManager(MemoryManagerGlue * manager)344     void setMemoryManager(MemoryManagerGlue* manager)
345     {
346         // To check
347         fFactory->setMemoryManager(static_cast<dsp_memory_manager*>(manager->managerInterface));
348     }
349 
write(std::ostream * out,bool binary,bool compact=false)350     void write(std::ostream* out, bool binary, bool compact = false) {}
351 
writeDSPFactoryToBitcode()352     std::string writeDSPFactoryToBitcode() { return fFactory->writeDSPFactoryToBitcode(); }
353 
writeDSPFactoryToBitcodeFile(const std::string & bit_code_path)354     bool writeDSPFactoryToBitcodeFile(const std::string& bit_code_path)
355     {
356         return fFactory->writeDSPFactoryToBitcodeFile(bit_code_path);
357     }
358 
writeDSPFactoryToIR()359     std::string writeDSPFactoryToIR() { return fFactory->writeDSPFactoryToIR(); }
360 
writeDSPFactoryToIRFile(const std::string & ir_code_path)361     bool writeDSPFactoryToIRFile(const std::string& ir_code_path)
362     {
363         return fFactory->writeDSPFactoryToIRFile(ir_code_path);
364     }
365 
writeDSPFactoryToMachine(const std::string & target)366     std::string writeDSPFactoryToMachine(const std::string& target)
367     {
368         return fFactory->writeDSPFactoryToMachine(target);
369     }
370 
writeDSPFactoryToMachineFile(const std::string & machine_code_path,const std::string & target)371     bool writeDSPFactoryToMachineFile(const std::string& machine_code_path, const std::string& target)
372     {
373         return fFactory->writeDSPFactoryToMachineFile(machine_code_path, target);
374     }
375 
writeDSPFactoryToObjectcodeFile(const std::string & object_code_path,const std::string & target)376     bool writeDSPFactoryToObjectcodeFile(const std::string& object_code_path, const std::string& target)
377     {
378         return fFactory->writeDSPFactoryToObjectcodeFile(object_code_path, target);
379     }
380 
getFactory()381     llvm_dsp_factory_aux* getFactory() { return fFactory; }
382 };
383 
384 EXPORT llvm_dsp_factory* getDSPFactoryFromSHAKey(const std::string& sha_key);
385 
386 EXPORT bool deleteDSPFactory(llvm_dsp_factory* factory);
387 
388 EXPORT std::string getDSPMachineTarget();
389 
390 EXPORT std::vector<std::string> getLibraryList(llvm_dsp_factory* factory);
391 
392 EXPORT std::vector<std::string> getAllDSPFactories();
393 
394 EXPORT void deleteAllDSPFactories();
395 
396 // machine <==> string
397 EXPORT llvm_dsp_factory* readDSPFactoryFromMachine(const std::string& machine_code, const std::string& target,
398                                                    std::string& error_msg);
399 
400 // machine <==> file
401 EXPORT llvm_dsp_factory* readDSPFactoryFromMachineFile(const std::string& machine_code_path, const std::string& target,
402                                                        std::string& error_msg);
403 
404 EXPORT std::string writeDSPFactoryToMachine(llvm_dsp_factory* factory, const std::string& target);
405 
406 EXPORT bool writeDSPFactoryToMachineFile(llvm_dsp_factory* factory, const std::string& machine_code_path,
407                                          const std::string& target);
408 
409 #ifdef __cplusplus
410 extern "C" {
411 #endif
412 
413 // Public C interface
414 
415 EXPORT llvm_dsp_factory* getCDSPFactoryFromSHAKey(const char* sha_key);
416 
417 EXPORT bool deleteCDSPFactory(llvm_dsp_factory* factory);
418 
419 EXPORT char* getCName(llvm_dsp_factory* factory);
420 
421 EXPORT char* getCSHAKey(llvm_dsp_factory* factory);
422 
423 EXPORT char* getCTarget(llvm_dsp_factory* factory);
424 
425 EXPORT char* getCDSPCode(llvm_dsp_factory* factory);
426 
427 EXPORT char* getCDSPMachineTarget();
428 
429 EXPORT const char** getCDSPFactoryLibraryList(llvm_dsp_factory* factory);
430 
431 EXPORT const char** getCDSPFactoryIncludePathnames(llvm_dsp_factory* factory);
432 
433 EXPORT char* getCDSPFactoryCompileOptions(llvm_dsp_factory* factory);
434 
435 EXPORT void deleteAllCDSPFactories();
436 
437 EXPORT const char** getAllCDSPFactories();
438 
439 EXPORT bool startMTCDSPFactories();
440 
441 EXPORT void stopMTCDSPFactories();
442 
443 EXPORT llvm_dsp_factory* readCDSPFactoryFromMachine(const char* machine_code, const char* target, char* error_msg);
444 
445 EXPORT char* writeCDSPFactoryToMachine(llvm_dsp_factory* factory, const char* target);
446 
447 EXPORT llvm_dsp_factory* readCDSPFactoryFromMachineFile(const char* machine_code_path, const char* target,
448                                                         char* error_msg);
449 
450 EXPORT bool writeCDSPFactoryToMachineFile(llvm_dsp_factory* factory, const char* machine_code_path, const char* target);
451 
452 EXPORT bool writeCDSPFactoryToObjectcodeFile(llvm_dsp_factory* factory, const char* object_code_path,
453                                              const char* target);
454 
455 EXPORT void metadataCDSPInstance(llvm_dsp* dsp, MetaGlue* meta);
456 
457 EXPORT int getNumInputsCDSPInstance(llvm_dsp* dsp);
458 
459 EXPORT int getNumOutputsCDSPInstance(llvm_dsp* dsp);
460 
461 EXPORT void buildUserInterfaceCDSPInstance(llvm_dsp* dsp, UIGlue* ui_interface);
462 
463 EXPORT int getSampleRateCDSPInstance(llvm_dsp* dsp);
464 
465 EXPORT void initCDSPInstance(llvm_dsp* dsp, int sample_rate);
466 
467 EXPORT void instanceInitCDSPInstance(llvm_dsp* dsp, int sample_rate);
468 
469 EXPORT void instanceConstantsCDSPInstance(llvm_dsp* dsp, int sample_rate);
470 
471 EXPORT void instanceResetUserInterfaceCDSPInstance(llvm_dsp* dsp);
472 
473 EXPORT void instanceClearCDSPInstance(llvm_dsp* dsp);
474 
475 EXPORT llvm_dsp* cloneCDSPInstance(llvm_dsp* dsp);
476 
477 EXPORT void computeCDSPInstance(llvm_dsp* dsp, int count, FAUSTFLOAT** input, FAUSTFLOAT** output);
478 
479 EXPORT void setCMemoryManager(llvm_dsp_factory* factory, MemoryManagerGlue* manager);
480 
481 EXPORT llvm_dsp* createCDSPInstance(llvm_dsp_factory* factory);
482 
483 EXPORT void deleteCDSPInstance(llvm_dsp* dsp);
484 
485 EXPORT void generateCSHA1(const char* data, char* key);
486 
487 #ifdef __cplusplus
488 }
489 #endif
490 
491 #endif
492