1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2016 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 __dsp_factory_base__
23 #define __dsp_factory_base__
24 
25 #include <string.h>
26 #include <ostream>
27 #include <string>
28 
29 #include "exception.hh"
30 #include "export.hh"
31 #include "faust/gui/CInterface.h"
32 #include "faust/gui/meta.h"
33 #include "faust/dsp/dsp.h"
34 
35 #define COMPILATION_OPTIONS_KEY "compilation_options"
36 #define COMPILATION_OPTIONS "declare compilation_options    "
37 
38 /*
39  In order to better separate compilation and execution for dynamic backends (LLVM, Interpreter, WebAssembly).
40  A dsp_factory_base* object will either be generated by the compiler from a dsp,
41  or by reading an already compiled dsp (in LLVM IR, Interpreter or WebAssembly bytecode).
42  */
43 
44 struct dsp_factory_base {
45 
~dsp_factory_basedsp_factory_base46     virtual ~dsp_factory_base() {}
47 
48     virtual void write(std::ostream* out, bool binary = false, bool compact = false) = 0;
49 
writeHelperdsp_factory_base50     virtual void writeHelper(std::ostream* out, bool binary = false, bool compact = false) {}  // Helper functions
51 
52     virtual std::string getName()                        = 0;
53     virtual void        setName(const std::string& name) = 0;
54 
55     virtual std::string getSHAKey()                           = 0;
56     virtual void        setSHAKey(const std::string& sha_key) = 0;
57 
58     virtual std::string getDSPCode()                        = 0;
59     virtual void        setDSPCode(const std::string& code) = 0;
60 
61     virtual std::string getCompileOptions() = 0;
62 
63     virtual dsp* createDSPInstance(dsp_factory* factory) = 0;
64 
65     virtual void                setMemoryManager(dsp_memory_manager* manager) = 0;
66     virtual dsp_memory_manager* getMemoryManager()                            = 0;
67 
68     virtual void* allocate(size_t size) = 0;
69     virtual void  destroy(void* ptr)    = 0;
70 
71     virtual void metadata(Meta* meta) = 0;
72 
73     virtual std::string getBinaryCode() = 0;
74 
75     // Sub-classes will typically implement this method to create a factory from a stream
readdsp_factory_base76     static dsp_factory_base* read(std::istream* in) { return nullptr; }
77 };
78 
79 class dsp_factory_imp : public dsp_factory_base {
80    protected:
81     std::string         fName;
82     std::string         fSHAKey;
83     std::string         fExpandedDSP;
84     dsp_memory_manager* fManager;
85 
86    public:
dsp_factory_imp(const std::string & name,const std::string & sha_key,const std::string & dsp)87     dsp_factory_imp(const std::string& name, const std::string& sha_key, const std::string& dsp)
88         : fName(name), fSHAKey(sha_key), fExpandedDSP(dsp), fManager(nullptr)
89     {
90     }
91 
~dsp_factory_imp()92     virtual ~dsp_factory_imp() {}
93 
getName()94     std::string getName()
95     {
96         struct MyMeta : public Meta {
97             std::string  name;
98             virtual void declare(const char* key, const char* value)
99             {
100                 if (strcmp(key, "name") == 0) name = value;
101             }
102         };
103 
104         MyMeta meta_data;
105         metadata(&meta_data);
106         return (meta_data.name != "") ? meta_data.name : fName;
107     }
108 
setName(const std::string & name)109     void setName(const std::string& name) { fName = name; }
110 
getSHAKey()111     std::string getSHAKey() { return fSHAKey; }
setSHAKey(const std::string & sha_key)112     void        setSHAKey(const std::string& sha_key) { fSHAKey = sha_key; }
113 
getDSPCode()114     std::string getDSPCode() { return fExpandedDSP; }
setDSPCode(const std::string & code)115     void        setDSPCode(const std::string& code) { fExpandedDSP = code; }
116 
getCompileOptions()117     virtual std::string getCompileOptions() { return ""; };
118 
createDSPInstance(dsp_factory * factory)119     virtual dsp* createDSPInstance(dsp_factory* factory)
120     {
121         faustassert(false);
122         return nullptr;
123     }
124 
setMemoryManager(dsp_memory_manager * manager)125     virtual void                setMemoryManager(dsp_memory_manager* manager) { fManager = manager; }
getMemoryManager()126     virtual dsp_memory_manager* getMemoryManager() { return fManager; }
127 
allocate(size_t size)128     virtual void* allocate(size_t size)
129     {
130         if (fManager) {
131             return fManager->allocate(size);
132         } else {
133             faustassert(false);
134             return nullptr;
135         }
136     }
137 
destroy(void * ptr)138     virtual void destroy(void* ptr)
139     {
140         if (fManager) {
141             fManager->destroy(ptr);
142         } else {
143             faustassert(false);
144         }
145     }
146 
metadata(Meta * meta)147     virtual void metadata(Meta* meta) { faustassert(false); }
148 
write(std::ostream * out,bool binary=false,bool compact=false)149     virtual void write(std::ostream* out, bool binary = false, bool compact = false) {}
150 
getBinaryCode()151     virtual std::string getBinaryCode() { return ""; }
152 };
153 
154 /* To be used by textual backends */
155 class text_dsp_factory_aux : public dsp_factory_imp {
156    protected:
157     std::string fCode;
158     std::string fHelpers;
159 
160    public:
text_dsp_factory_aux(const std::string & name,const std::string & sha_key,const std::string & dsp,const std::string & code,const std::string & helpers)161     text_dsp_factory_aux(const std::string& name, const std::string& sha_key, const std::string& dsp,
162                          const std::string& code, const std::string& helpers)
163         : dsp_factory_imp(name, sha_key, dsp), fCode(code), fHelpers(helpers)
164     {
165     }
166 
write(std::ostream * out,bool binary=false,bool compact=false)167     virtual void write(std::ostream* out, bool binary = false, bool compact = false) { *out << fCode; }
168 
writeHelper(std::ostream * out,bool binary=false,bool compact=false)169     virtual void writeHelper(std::ostream* out, bool binary = false, bool compact = false) { *out << fHelpers; }
170 
getBinaryCode()171     virtual std::string getBinaryCode() { return fCode; }
172 };
173 
174 // Backend API implemented in libcode.cpp
175 
176 class CTree;
177 typedef CTree* Signal;
178 typedef std::vector<Signal> tvec;
179 
180 dsp_factory_base* createFactory(const char* name, const char* input,
181                                 int argc, const char* argv[],
182                                 std::string& error_msg, bool generate);
183 
184 dsp_factory_base* createFactory(const char* name, tvec signals,
185                                 int argc, const char* argv[],
186                                 std::string& error_msg);
187 
188 std::string expandDSP(int argc, const char* argv[], const char* name,
189                       const char* input, std::string& sha_key,
190                       std::string& error_msg);
191 
192 #endif
193