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 #ifdef WIN32
23 #pragma warning(disable : 4141 4146 4244 4267 4275 4800)
24 //# define strdup _strdup
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <fstream>
30 #include <iostream>
31 #include <list>
32 #include <sstream>
33
34 #include <llvm-c/Core.h>
35 #include <llvm/Bitcode/BitcodeReader.h>
36 #include <llvm/Bitcode/BitcodeWriter.h>
37 #include <llvm/ExecutionEngine/MCJIT.h>
38 #include <llvm/Support/FileSystem.h>
39 #include <llvm/Support/TargetSelect.h>
40 #include <llvm/Support/Host.h>
41
42 #include "faust/gui/JSONUIDecoder.h"
43 #include "libfaust.h"
44 #include "llvm_dsp_aux.hh"
45 #include "rn_base64.h"
46 #include "lock_api.hh"
47
48 using namespace llvm;
49 using namespace std;
50
51 // Used by LLVM backend (for now)
52 Soundfile* dynamic_defaultsound = new Soundfile(64);
53
54 #define LLVM_BACKEND_NAME "Faust LLVM backend"
55
56 #ifdef LLVM_MACHINE
57
faustassert(bool)58 void faustassert(bool)
59 {
60 }
getCLibFaustVersion()61 extern "C" EXPORT const char* getCLibFaustVersion()
62 {
63 return FAUSTVERSION;
64 }
65
66 #endif
67
68 // Debug tools
printInt32(int val)69 extern "C" EXPORT void printInt32(int val)
70 {
71 cout << "printInt32 : " << val << endl;
72 }
73
printFloat(float val)74 extern "C" EXPORT void printFloat(float val)
75 {
76 cout << "printFloat : " << val << endl;
77 }
78
printDouble(double val)79 extern "C" EXPORT void printDouble(double val)
80 {
81 cout << "printDouble : " << val << endl;
82 }
83
printPtr(void * val)84 extern "C" EXPORT void printPtr(void* val)
85 {
86 cout << "printPtr : " << val << endl;
87 }
88
89 // Factories instances management
90 int llvm_dsp_factory_aux::gInstance = 0;
91
92 dsp_factory_table<SDsp_factory> llvm_dsp_factory_aux::gLLVMFactoryTable;
93
loadOptimize(const string & function)94 uint64_t llvm_dsp_factory_aux::loadOptimize(const string& function)
95 {
96 uint64_t fun = fJIT->getFunctionAddress(function);
97 if (fun) {
98 return fun;
99 } else {
100 stringstream error;
101 error << "ERROR : loadOptimize failed for '" << function << "'\n";
102 throw faustexception(error.str());
103 }
104 }
105
crossCompile(const string & target)106 bool llvm_dsp_factory_aux::crossCompile(const string& target)
107 {
108 delete fObjectCache;
109 fObjectCache = new FaustObjectCache();
110 setTarget(target);
111 string error;
112 return initJIT(error);
113 }
114
startLLVMLibrary()115 void llvm_dsp_factory_aux::startLLVMLibrary()
116 {
117 if (llvm_dsp_factory_aux::gInstance++ == 0) {
118 LLVMInstallFatalErrorHandler(llvm_dsp_factory_aux::LLVMFatalErrorHandler);
119 }
120 }
121
stopLLVMLibrary()122 void llvm_dsp_factory_aux::stopLLVMLibrary()
123 {
124 if (--llvm_dsp_factory_aux::gInstance == 0) {
125 // Remove the LLVM error handler
126 #if defined(__APPLE__) && (defined(LLVM_110) || defined(LLVM_120))
127 #warning Crash on OSX so deactivated in this case
128 #else
129 LLVMResetFatalErrorHandler();
130 #endif
131 }
132 }
133
llvm_dsp_factory_aux(const string & sha_key,const string & machine_code,const string & target)134 llvm_dsp_factory_aux::llvm_dsp_factory_aux(const string& sha_key, const string& machine_code, const string& target)
135 : dsp_factory_imp("MachineDSP", sha_key, "")
136 {
137 startLLVMLibrary();
138
139 init("MachineDSP", "");
140 fSHAKey = sha_key;
141 fTarget = (target == "") ? fTarget = (sys::getDefaultTargetTriple() + ":" + GET_CPU_NAME) : target;
142
143 // Restoring the cache
144 fObjectCache = new FaustObjectCache(machine_code);
145
146 // Creates module and context
147 fContext = new LLVMContext();
148 fModule = new Module(string(LLVM_BACKEND_NAME) + ", v" + string(FAUSTVERSION), *fContext);
149 fDecoder = nullptr;
150 }
151
llvm_dsp_factory_aux(const string & sha_key,Module * module,LLVMContext * context,const string & target,int opt_level)152 llvm_dsp_factory_aux::llvm_dsp_factory_aux(const string& sha_key, Module* module, LLVMContext* context,
153 const string& target, int opt_level)
154 : dsp_factory_imp("BitcodeDSP", sha_key, "")
155 {
156 startLLVMLibrary();
157
158 init("BitcodeDSP", "");
159 fSHAKey = sha_key;
160 fTarget = (target == "") ? fTarget = (sys::getDefaultTargetTriple() + ":" + GET_CPU_NAME) : target;
161 setOptlevel(opt_level);
162
163 fObjectCache = nullptr;
164 fContext = context;
165 fModule = module;
166 fDecoder = nullptr;
167 }
168
~llvm_dsp_factory_aux()169 llvm_dsp_factory_aux::~llvm_dsp_factory_aux()
170 {
171 delete fObjectCache;
172 if (fJIT) {
173 fJIT->runStaticConstructorsDestructors(true);
174 // fModule is kept and deleted by fJIT
175 delete fJIT;
176 }
177 delete fContext;
178 delete fDecoder;
179 stopLLVMLibrary();
180 }
181
LLVMFatalErrorHandler(const char * reason)182 void llvm_dsp_factory_aux::LLVMFatalErrorHandler(const char* reason)
183 {
184 throw faustexception("ERROR : " + string(reason));
185 }
186
init(const string & type_name,const string & dsp_name)187 void llvm_dsp_factory_aux::init(const string& type_name, const string& dsp_name)
188 {
189 fJIT = nullptr;
190 fAllocate = nullptr;
191 fDestroy = nullptr;
192 fInstanceConstants = nullptr;
193 fInstanceClear = nullptr;
194 fClassInit = nullptr;
195 fCompute = nullptr;
196 fClassName = "mydsp";
197 fName = dsp_name;
198 fTypeName = type_name;
199 fExpandedDSP = "";
200 fOptLevel = 0;
201 fTarget = "";
202
203 // To keep Debug functions in generated code
204 #if 0
205 printInt32(1);
206 printFloat(0.5f);
207 printDouble(0.8);
208 printPtr(this);
209 #endif
210 }
211
initJIT(string & error_msg)212 bool llvm_dsp_factory_aux::initJIT(string& error_msg)
213 {
214 startTiming("initJIT");
215
216 // For host target support
217 InitializeNativeTarget();
218 InitializeNativeTargetAsmPrinter();
219 InitializeNativeTargetAsmParser();
220
221 // For ObjectCache to work...
222 LLVMLinkInMCJIT();
223
224 // Restoring from machine code
225 EngineBuilder builder((unique_ptr<Module>(fModule)));
226 string buider_error;
227 builder.setErrorStr(&buider_error);
228 TargetMachine* tm = builder.selectTarget();
229 fJIT = builder.create(tm);
230 if (!fJIT) {
231 error_msg = "ERROR : " + buider_error;
232 return false;
233 }
234
235 fJIT->setObjectCache(fObjectCache);
236 fJIT->finalizeObject();
237 return initJITAux();
238 }
239
initJITAux()240 bool llvm_dsp_factory_aux::initJITAux()
241 {
242 // Run static constructors.
243 fJIT->runStaticConstructorsDestructors(false);
244 fJIT->DisableLazyCompilation(true);
245
246 fAllocate = (allocateDspFun)loadOptimize("allocate" + fClassName);
247 fDestroy = (destroyDspFun)loadOptimize("destroy" + fClassName);
248 fInstanceConstants = (instanceConstantsFun)loadOptimize("instanceConstants" + fClassName);
249 fInstanceClear = (instanceClearFun)loadOptimize("instanceClear" + fClassName);
250 fClassInit = (classInitFun)loadOptimize("classInit" + fClassName);
251 fCompute = (computeFun)loadOptimize("compute" + fClassName);
252 fGetJSON = (getJSONFun)loadOptimize("getJSON" + fClassName);
253
254 endTiming("initJIT");
255 return true;
256 }
257
getOptlevel()258 int llvm_dsp_factory_aux::getOptlevel()
259 {
260 // TODO LLVM_36
261 /*
262 NamedMDNode* meta_data = fModule->getOrInsertNamedMetadata("OptLevel");
263 if (meta_data->getNumOperands() > 0) {
264 MDNode* node = meta_data->getOperand(0);
265 return (node) ? atoi(static_cast<MDString*>(node->getOperand(0))->getString().data()) : -1;
266 } else {
267 char opt_level[32];
268 sprintf(opt_level, "%d", fOptLevel);
269 Value* values[] = { MDString::get(fModule->getContext(), opt_level) };
270 meta_data->addOperand(MDNode::get(fModule->getContext(), values));
271 return -1;
272 }
273 */
274 return -1;
275 }
276
metadata(Meta * m)277 void llvm_dsp_factory_aux::metadata(Meta* m)
278 {
279 checkDecoder();
280 fDecoder->metadata(m);
281 }
282
metadata(MetaGlue * glue)283 void llvm_dsp_factory_aux::metadata(MetaGlue* glue)
284 {
285 checkDecoder();
286 fDecoder->metadata(glue);
287 }
288
createDSPInstance(dsp_factory * factory_aux)289 llvm_dsp* llvm_dsp_factory_aux::createDSPInstance(dsp_factory* factory_aux)
290 {
291 llvm_dsp_factory* factory = static_cast<llvm_dsp_factory*>(factory_aux);
292 faustassert(factory);
293 checkDecoder();
294
295 if (factory->getFactory()->getMemoryManager()) {
296 dsp_imp* dsp = static_cast<dsp_imp*>(factory->getFactory()->allocate(fDecoder->getDSPSize()));
297 return (dsp) ? new (factory->getFactory()->allocate(sizeof(llvm_dsp))) llvm_dsp(factory, dsp) : nullptr;
298 } else {
299 // LLVM module memory code
300 dsp_imp* dsp = static_cast<dsp_imp*>(calloc(1, fDecoder->getDSPSize()));
301 return (dsp) ? new llvm_dsp(factory, dsp) : nullptr;
302 }
303 }
304
getCompileOptions()305 string llvm_dsp_factory_aux::getCompileOptions()
306 {
307 checkDecoder();
308 return fDecoder->getCompileOptions();
309 }
310
getLibraryList()311 vector<string> llvm_dsp_factory_aux::getLibraryList()
312 {
313 checkDecoder();
314 return fDecoder->getLibraryList();
315 }
316
getIncludePathnames()317 vector<string> llvm_dsp_factory_aux::getIncludePathnames()
318 {
319 checkDecoder();
320 return fDecoder->getIncludePathnames();
321 }
322
323 // Instance
324
llvm_dsp(llvm_dsp_factory * factory,dsp_imp * dsp)325 llvm_dsp::llvm_dsp(llvm_dsp_factory* factory, dsp_imp* dsp):fFactory(factory), fDSP(dsp)
326 {
327 // Used in -sch mode
328 fDecoder = createJSONUIDecoder(fFactory->getFactory()->fGetJSON());
329 fFactory->getFactory()->fAllocate(fDSP);
330 }
331
~llvm_dsp()332 llvm_dsp::~llvm_dsp()
333 {
334 LOCK_API
335 llvm_dsp_factory_aux::gLLVMFactoryTable.removeDSP(fFactory, this);
336
337 // Used in -sch mode
338 fFactory->getFactory()->fDestroy(fDSP);
339
340 if (fFactory->getMemoryManager()) {
341 fFactory->getMemoryManager()->destroy(fDSP);
342 } else {
343 // LLVM module memory code
344 free(fDSP);
345 }
346 delete fDecoder;
347 }
348
metadata(Meta * m)349 void llvm_dsp::metadata(Meta* m)
350 {
351 fFactory->getFactory()->fDecoder->metadata(m);
352 }
353
metadata(MetaGlue * glue)354 void llvm_dsp::metadata(MetaGlue* glue)
355 {
356 fFactory->getFactory()->fDecoder->metadata(glue);
357 }
358
getNumInputs()359 int llvm_dsp::getNumInputs()
360 {
361 return fFactory->getFactory()->fDecoder->getNumInputs();
362 }
363
getNumOutputs()364 int llvm_dsp::getNumOutputs()
365 {
366 return fFactory->getFactory()->fDecoder->getNumOutputs();
367 }
368
init(int sample_rate)369 void llvm_dsp::init(int sample_rate)
370 {
371 classInit(sample_rate);
372 instanceInit(sample_rate);
373 }
374
classInit(int sample_rate)375 void llvm_dsp::classInit(int sample_rate)
376 {
377 fFactory->getFactory()->fClassInit(sample_rate);
378 }
379
instanceInit(int sample_rate)380 void llvm_dsp::instanceInit(int sample_rate)
381 {
382 instanceConstants(sample_rate);
383 instanceResetUserInterface();
384 instanceClear();
385 }
386
instanceConstants(int sample_rate)387 void llvm_dsp::instanceConstants(int sample_rate)
388 {
389 fFactory->getFactory()->fInstanceConstants(fDSP, sample_rate);
390 }
391
instanceResetUserInterface()392 void llvm_dsp::instanceResetUserInterface()
393 {
394 // Reset the DSP proxy
395 fDecoder->resetUserInterface();
396 // Reset the real DSP
397 fDecoder->resetUserInterface(fDSP, dynamic_defaultsound);
398 }
399
instanceClear()400 void llvm_dsp::instanceClear()
401 {
402 fFactory->getFactory()->fInstanceClear(fDSP);
403 }
404
clone()405 llvm_dsp* llvm_dsp::clone()
406 {
407 return fFactory->createDSPInstance();
408 }
409
getSampleRate()410 int llvm_dsp::getSampleRate()
411 {
412 return fDecoder->getSampleRate(fDSP);
413 }
414
buildUserInterface(UI * ui_interface)415 void llvm_dsp::buildUserInterface(UI* ui_interface)
416 {
417 if (fDecoder->hasCompileOption("-double") && ui_interface->sizeOfFAUSTFLOAT() == 4) {
418 // Setup a DSP proxy
419 fDecoder->setupDSPProxy(ui_interface, fDSP);
420 fDecoder->buildUserInterface(ui_interface);
421 } else {
422 fDecoder->buildUserInterface(ui_interface, fDSP);
423 }
424 }
425
buildUserInterface(UIGlue * glue)426 void llvm_dsp::buildUserInterface(UIGlue* glue)
427 {
428 fDecoder->buildUserInterface(glue, fDSP);
429 }
430
compute(int count,FAUSTFLOAT ** input,FAUSTFLOAT ** output)431 void llvm_dsp::compute(int count, FAUSTFLOAT** input, FAUSTFLOAT** output)
432 {
433 if (fDecoder->hasDSPProxy()) {
434 // Update inputs control
435 for (const auto& i : fDecoder->getInputControls()) {
436 i->reflectZone();
437 }
438 fFactory->getFactory()->fCompute(fDSP, count, input, output);
439 // Update outputs control
440 for (const auto& i : fDecoder->getOutputControls()) {
441 i->modifyZone();
442 }
443 } else {
444 fFactory->getFactory()->fCompute(fDSP, count, input, output);
445 }
446 }
447
writeDSPFactoryToMachineAux(const string & target)448 string llvm_dsp_factory_aux::writeDSPFactoryToMachineAux(const string& target)
449 {
450 if (target == "" || target == getTarget()) {
451 return fObjectCache->getMachineCode();
452 } else {
453 string old_target = getTarget();
454 if (crossCompile(target)) { // Recompilation is required
455 string machine_code = fObjectCache->getMachineCode();
456 crossCompile(old_target); // Restore old target
457 return machine_code;
458 } else {
459 return "";
460 }
461 }
462 }
463
writeDSPFactoryToMachine(const string & target)464 string llvm_dsp_factory_aux::writeDSPFactoryToMachine(const string& target)
465 {
466 return base64_encode(writeDSPFactoryToMachineAux(target));
467 }
468
writeDSPFactoryToMachineFile(const string & machine_code_path,const string & target)469 bool llvm_dsp_factory_aux::writeDSPFactoryToMachineFile(const string& machine_code_path, const string& target)
470 {
471 STREAM_ERROR err;
472 raw_fd_ostream out(machine_code_path.c_str(), err, sysfs_binary_flag);
473 if (err) {
474 cerr << "ERROR : writeDSPFactoryToMachineFile could not open file : " << err.message();
475 return false;
476 }
477 out << writeDSPFactoryToMachineAux(target);
478 out.flush();
479 return true;
480 }
481
readDSPFactoryFromMachineAux(MEMORY_BUFFER buffer,const string & target,string & error_msg)482 llvm_dsp_factory* llvm_dsp_factory_aux::readDSPFactoryFromMachineAux(MEMORY_BUFFER buffer, const string& target,
483 string& error_msg)
484 {
485 string sha_key = generateSHA1(MEMORY_BUFFER_GET(buffer).str());
486 dsp_factory_table<SDsp_factory>::factory_iterator it;
487
488 if (llvm_dsp_factory_aux::gLLVMFactoryTable.getFactory(sha_key, it)) {
489 SDsp_factory sfactory = (*it).first;
490 sfactory->addReference();
491 return sfactory;
492 } else {
493 try {
494 llvm_dsp_factory_aux* factory_aux = new llvm_dsp_factory_aux(sha_key, MEMORY_BUFFER_GET(buffer).str(), target);
495 if (factory_aux->initJIT(error_msg)) {
496 llvm_dsp_factory* factory = new llvm_dsp_factory(factory_aux);
497 llvm_dsp_factory_aux::gLLVMFactoryTable.setFactory(factory);
498 factory->setSHAKey(sha_key);
499 return factory;
500 } else {
501 delete factory_aux;
502 return nullptr;
503 }
504 } catch (faustexception& e) {
505 error_msg = e.what();
506 return nullptr;
507 }
508 }
509 }
510
getTarget()511 string llvm_dsp_factory_aux::getTarget()
512 {
513 return fTarget;
514 }
515
516 // Public C++ API
517
getDSPFactoryFromSHAKey(const string & sha_key)518 EXPORT llvm_dsp_factory* getDSPFactoryFromSHAKey(const string& sha_key)
519 {
520 LOCK_API
521 return static_cast<llvm_dsp_factory*>(llvm_dsp_factory_aux::gLLVMFactoryTable.getDSPFactoryFromSHAKey(sha_key));
522 }
523
getAllDSPFactories()524 EXPORT vector<string> getAllDSPFactories()
525 {
526 LOCK_API
527 return llvm_dsp_factory_aux::gLLVMFactoryTable.getAllDSPFactories();
528 }
529
deleteDSPFactory(llvm_dsp_factory * factory)530 EXPORT bool deleteDSPFactory(llvm_dsp_factory* factory)
531 {
532 LOCK_API
533 return (factory) ? llvm_dsp_factory_aux::gLLVMFactoryTable.deleteDSPFactory(factory) : false;
534 }
535
getDSPMachineTarget()536 EXPORT string getDSPMachineTarget()
537 {
538 return (sys::getDefaultTargetTriple() + ":" + GET_CPU_NAME);
539 }
540
getLibraryList(llvm_dsp_factory * factory)541 EXPORT vector<string> getLibraryList(llvm_dsp_factory* factory)
542 {
543 LOCK_API
544 return factory->getLibraryList();
545 }
546
deleteAllDSPFactories()547 EXPORT void deleteAllDSPFactories()
548 {
549 LOCK_API
550 llvm_dsp_factory_aux::gLLVMFactoryTable.deleteAllDSPFactories();
551 }
552
553 // machine <==> string
readDSPFactoryFromMachine(const string & machine_code,const string & target,string & error_msg)554 EXPORT llvm_dsp_factory* readDSPFactoryFromMachine(const string& machine_code, const string& target, string& error_msg)
555 {
556 LOCK_API
557 return llvm_dsp_factory_aux::readDSPFactoryFromMachineAux(
558 MEMORY_BUFFER_CREATE(StringRef(base64_decode(machine_code))), target, error_msg);
559 }
560
561 // machine <==> file
readDSPFactoryFromMachineFile(const string & machine_code_path,const string & target,string & error_msg)562 EXPORT llvm_dsp_factory* readDSPFactoryFromMachineFile(const string& machine_code_path, const string& target,
563 string& error_msg)
564 {
565 LOCK_API
566 ErrorOr<OwningPtr<MemoryBuffer>> buffer = MemoryBuffer::getFileOrSTDIN(machine_code_path);
567 if (error_code ec = buffer.getError()) {
568 error_msg = "ERROR : " + ec.message() + "\n";
569 return nullptr;
570 } else {
571 return llvm_dsp_factory_aux::readDSPFactoryFromMachineAux(MEMORY_BUFFER_GET_REF(buffer), target, error_msg);
572 }
573 }
574
writeDSPFactoryToMachine(llvm_dsp_factory * factory,const string & target)575 EXPORT string writeDSPFactoryToMachine(llvm_dsp_factory* factory, const string& target)
576 {
577 LOCK_API
578 return factory->writeDSPFactoryToMachine(target);
579 }
580
writeDSPFactoryToMachineFile(llvm_dsp_factory * factory,const string & machine_code_path,const string & target)581 EXPORT bool writeDSPFactoryToMachineFile(llvm_dsp_factory* factory, const string& machine_code_path,
582 const string& target)
583 {
584 LOCK_API
585 return (factory) ? factory->writeDSPFactoryToMachineFile(machine_code_path, target) : false;
586 }
587
writeDSPFactoryToObjectcodeFile(llvm_dsp_factory * factory,const string & object_code_path,const string & target)588 EXPORT bool writeDSPFactoryToObjectcodeFile(llvm_dsp_factory* factory, const string& object_code_path,
589 const string& target)
590 {
591 LOCK_API
592 return (factory) ? factory->writeDSPFactoryToObjectcodeFile(object_code_path, target) : false;
593 }
594
595 // Instance
createDSPInstance()596 EXPORT llvm_dsp* llvm_dsp_factory::createDSPInstance()
597 {
598 LOCK_API
599 dsp* dsp = fFactory->createDSPInstance(this);
600 llvm_dsp_factory_aux::gLLVMFactoryTable.addDSP(this, dsp);
601 return static_cast<llvm_dsp*>(dsp);
602 }
603
604 // Use the memory manager if needed
operator delete(void * ptr)605 EXPORT void llvm_dsp::operator delete(void* ptr)
606 {
607 dsp_memory_manager* manager = static_cast<llvm_dsp*>(ptr)->fFactory->getMemoryManager();
608 if (manager) {
609 manager->destroy(ptr);
610 } else {
611 ::operator delete(ptr);
612 }
613 }
614
615 // Public C interface : lock management is done by called C++ API
616
617 #ifdef __cplusplus
618 extern "C" {
619 #endif
620
getCDSPFactoryFromSHAKey(const char * sha_key)621 EXPORT llvm_dsp_factory* getCDSPFactoryFromSHAKey(const char* sha_key)
622 {
623 return getDSPFactoryFromSHAKey(sha_key);
624 }
625
getAllCDSPFactories()626 EXPORT const char** getAllCDSPFactories()
627 {
628 vector<string> sha_key_list1 = getAllDSPFactories();
629 const char** sha_key_list2 = (const char**)malloc(sizeof(char*) * (sha_key_list1.size() + 1));
630
631 size_t i;
632 for (i = 0; i < sha_key_list1.size(); i++) {
633 sha_key_list2[i] = strdup(sha_key_list1[i].c_str());
634 }
635
636 // Last element is NULL
637 sha_key_list2[i] = nullptr;
638 return sha_key_list2;
639 }
640
deleteCDSPFactory(llvm_dsp_factory * factory)641 EXPORT bool deleteCDSPFactory(llvm_dsp_factory* factory)
642 {
643 return deleteDSPFactory(factory);
644 }
645
getCName(llvm_dsp_factory * factory)646 EXPORT char* getCName(llvm_dsp_factory* factory)
647 {
648 if (factory) {
649 string name = factory->getName();
650 return strdup(name.c_str());
651 } else {
652 return nullptr;
653 }
654 }
655
getCSHAKey(llvm_dsp_factory * factory)656 EXPORT char* getCSHAKey(llvm_dsp_factory* factory)
657 {
658 if (factory) {
659 string shakey = factory->getSHAKey();
660 return strdup(shakey.c_str());
661 } else {
662 return nullptr;
663 }
664 }
665
getCTarget(llvm_dsp_factory * factory)666 EXPORT char* getCTarget(llvm_dsp_factory* factory)
667 {
668 if (factory) {
669 string target = factory->getTarget();
670 return strdup(target.c_str());
671 } else {
672 return nullptr;
673 }
674 }
675
getCDSPCode(llvm_dsp_factory * factory)676 EXPORT char* getCDSPCode(llvm_dsp_factory* factory)
677 {
678 if (factory) {
679 string dspcode = factory->getDSPCode();
680 return strdup(dspcode.c_str());
681 } else {
682 return nullptr;
683 }
684 }
685
getCDSPMachineTarget()686 EXPORT char* getCDSPMachineTarget()
687 {
688 string dspmachinetarget = getDSPMachineTarget();
689 return strdup(dspmachinetarget.c_str());
690 }
691
getCDSPFactoryLibraryList(llvm_dsp_factory * factory)692 EXPORT const char** getCDSPFactoryLibraryList(llvm_dsp_factory* factory)
693 {
694 if (factory) {
695 vector<string> library_list1 = factory->getLibraryList();
696 const char** library_list2 = (const char**)malloc(sizeof(char*) * (library_list1.size() + 1));
697
698 size_t i;
699 for (i = 0; i < library_list1.size(); i++) {
700 library_list2[i] = strdup(library_list1[i].c_str());
701 }
702
703 // Last element is NULL
704 library_list2[i] = nullptr;
705 return library_list2;
706 } else {
707 return nullptr;
708 }
709 }
710
getCDSPFactoryIncludePathnames(llvm_dsp_factory * factory)711 EXPORT const char** getCDSPFactoryIncludePathnames(llvm_dsp_factory* factory)
712 {
713 if (factory) {
714 vector<string> include_list1 = factory->getIncludePathnames();
715 const char** include_list2 = (const char**)malloc(sizeof(char*) * (include_list1.size() + 1));
716
717 size_t i;
718 for (i = 0; i < include_list1.size(); i++) {
719 include_list2[i] = strdup(include_list1[i].c_str());
720 }
721
722 // Last element is NULL
723 include_list2[i] = nullptr;
724 return include_list2;
725 } else {
726 return nullptr;
727 }
728 }
729
getCDSPFactoryCompileOptions(llvm_dsp_factory * factory)730 EXPORT char* getCDSPFactoryCompileOptions(llvm_dsp_factory* factory)
731 {
732 if (factory) {
733 string options = factory->getCompileOptions();
734 return strdup(options.c_str());
735 } else {
736 return nullptr;
737 }
738 }
739
deleteAllCDSPFactories()740 EXPORT void deleteAllCDSPFactories()
741 {
742 deleteAllDSPFactories();
743 }
744
readCDSPFactoryFromMachine(const char * machine_code,const char * target,char * error_msg)745 EXPORT llvm_dsp_factory* readCDSPFactoryFromMachine(const char* machine_code, const char* target, char* error_msg)
746 {
747 string error_msg_aux;
748 llvm_dsp_factory* factory = readDSPFactoryFromMachine(machine_code, target, error_msg_aux);
749 strncpy(error_msg, error_msg_aux.c_str(), 4096);
750 return factory;
751 }
752
writeCDSPFactoryToMachine(llvm_dsp_factory * factory,const char * target)753 EXPORT char* writeCDSPFactoryToMachine(llvm_dsp_factory* factory, const char* target)
754 {
755 return (factory) ? strdup(writeDSPFactoryToMachine(factory, target).c_str()) : nullptr;
756 }
757
readCDSPFactoryFromMachineFile(const char * machine_code_path,const char * target,char * error_msg)758 EXPORT llvm_dsp_factory* readCDSPFactoryFromMachineFile(const char* machine_code_path, const char* target,
759 char* error_msg)
760 {
761 string error_msg_aux;
762 llvm_dsp_factory* factory = readDSPFactoryFromMachineFile(machine_code_path, target, error_msg_aux);
763 strncpy(error_msg, error_msg_aux.c_str(), 4096);
764 return factory;
765 }
766
writeCDSPFactoryToMachineFile(llvm_dsp_factory * factory,const char * machine_code_path,const char * target)767 EXPORT bool writeCDSPFactoryToMachineFile(llvm_dsp_factory* factory, const char* machine_code_path, const char* target)
768 {
769 return (factory) ? writeDSPFactoryToMachineFile(factory, machine_code_path, target) : false;
770 }
771
writeCDSPFactoryToObjectcodeFile(llvm_dsp_factory * factory,const char * object_code_path,const char * target)772 EXPORT bool writeCDSPFactoryToObjectcodeFile(llvm_dsp_factory* factory, const char* object_code_path,
773 const char* target)
774 {
775 return (factory) ? writeDSPFactoryToObjectcodeFile(factory, object_code_path, target) : false;
776 }
777
metadataCDSPInstance(llvm_dsp * dsp,MetaGlue * glue)778 EXPORT void metadataCDSPInstance(llvm_dsp* dsp, MetaGlue* glue)
779 {
780 if (dsp) {
781 dsp->metadata(glue);
782 }
783 }
784
getNumInputsCDSPInstance(llvm_dsp * dsp)785 EXPORT int getNumInputsCDSPInstance(llvm_dsp* dsp)
786 {
787 return (dsp) ? dsp->getNumInputs() : -1;
788 }
789
getNumOutputsCDSPInstance(llvm_dsp * dsp)790 EXPORT int getNumOutputsCDSPInstance(llvm_dsp* dsp)
791 {
792 return (dsp) ? dsp->getNumOutputs() : -1;
793 }
794
initCDSPInstance(llvm_dsp * dsp,int sample_rate)795 EXPORT void initCDSPInstance(llvm_dsp* dsp, int sample_rate)
796 {
797 if (dsp) {
798 dsp->init(sample_rate);
799 }
800 }
801
instanceInitCDSPInstance(llvm_dsp * dsp,int sample_rate)802 EXPORT void instanceInitCDSPInstance(llvm_dsp* dsp, int sample_rate)
803 {
804 if (dsp) {
805 dsp->instanceInit(sample_rate);
806 }
807 }
808
instanceConstantsCDSPInstance(llvm_dsp * dsp,int sample_rate)809 EXPORT void instanceConstantsCDSPInstance(llvm_dsp* dsp, int sample_rate)
810 {
811 if (dsp) {
812 dsp->instanceConstants(sample_rate);
813 }
814 }
815
instanceResetUserInterfaceCDSPInstance(llvm_dsp * dsp)816 EXPORT void instanceResetUserInterfaceCDSPInstance(llvm_dsp* dsp)
817 {
818 if (dsp) {
819 dsp->instanceResetUserInterface();
820 }
821 }
822
instanceClearCDSPInstance(llvm_dsp * dsp)823 EXPORT void instanceClearCDSPInstance(llvm_dsp* dsp)
824 {
825 if (dsp) {
826 dsp->instanceClear();
827 }
828 }
829
getSampleRateCDSPInstance(llvm_dsp * dsp)830 EXPORT int getSampleRateCDSPInstance(llvm_dsp* dsp)
831 {
832 return (dsp) ? dsp->getSampleRate() : 0;
833 }
834
buildUserInterfaceCDSPInstance(llvm_dsp * dsp,UIGlue * glue)835 EXPORT void buildUserInterfaceCDSPInstance(llvm_dsp* dsp, UIGlue* glue)
836 {
837 if (dsp) {
838 dsp->buildUserInterface(glue);
839 }
840 }
841
computeCDSPInstance(llvm_dsp * dsp,int count,FAUSTFLOAT ** input,FAUSTFLOAT ** output)842 EXPORT void computeCDSPInstance(llvm_dsp* dsp, int count, FAUSTFLOAT** input, FAUSTFLOAT** output)
843 {
844 if (dsp) {
845 dsp->compute(count, input, output);
846 }
847 }
848
cloneCDSPInstance(llvm_dsp * dsp)849 EXPORT llvm_dsp* cloneCDSPInstance(llvm_dsp* dsp)
850 {
851 return (dsp) ? dsp->clone() : nullptr;
852 }
853
setCMemoryManager(llvm_dsp_factory * factory,MemoryManagerGlue * manager)854 EXPORT void setCMemoryManager(llvm_dsp_factory* factory, MemoryManagerGlue* manager)
855 {
856 if (factory) {
857 factory->setMemoryManager(manager);
858 }
859 }
860
createCDSPInstance(llvm_dsp_factory * factory)861 EXPORT llvm_dsp* createCDSPInstance(llvm_dsp_factory* factory)
862 {
863 return (factory) ? factory->createDSPInstance() : nullptr;
864 }
865
deleteCDSPInstance(llvm_dsp * dsp)866 EXPORT void deleteCDSPInstance(llvm_dsp* dsp)
867 {
868 delete dsp;
869 }
870
871 #ifdef __cplusplus
872 }
873 #endif
874