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_CODE_CONTAINER_H
23 #define _LLVM_CODE_CONTAINER_H
24 
25 #include "code_container.hh"
26 #include "llvm_instructions.hh"
27 #include "omp_code_container.hh"
28 #include "struct_manager.hh"
29 #include "vec_code_container.hh"
30 #include "wss_code_container.hh"
31 
32 using namespace std;
33 using namespace llvm;
34 
35 class LLVMCodeContainer : public virtual CodeContainer {
36    protected:
37     using CodeContainer::generateFillFun;
38     using CodeContainer::generateInstanceInitFun;
39 
40     IRBuilder<>*      fBuilder;
41     LLVMInstVisitor*  fCodeProducer;
42     StructInstVisitor fStructVisitor;
43 
44     Module*      fModule;
45     LLVMContext* fContext;
46 
47     // To be used for mathematical function mapping (-fm and exp10 on OSX)
48     void generateFunMap(const string& fun1_aux, const string& fun2_aux, int num_args, bool body = false);
49     void generateFunMaps();
50 
51     PointerType* generateDspStruct();
52 
53     // To be implemented in each LLVMScalarCodeContainer, LLVMVectorCodeContainer and LLVMWorkStealingCodeContainer
54     // classes
55     virtual void generateCompute() = 0;
56 
57     template <typename REAL>
generateGetJSON()58     void generateGetJSON()
59     {
60         PointerType*  string_ptr = PointerType::get(fBuilder->getInt8Ty(), 0);
61         LLVMVecTypes  getJSON_args;
62         FunctionType* getJSON_type = FunctionType::get(string_ptr, makeArrayRef(getJSON_args), false);
63         Function* getJSON = Function::Create(getJSON_type, GlobalValue::ExternalLinkage, "getJSON" + fKlassName, fModule);
64 
65         // Prepare compilation options
66         stringstream compile_options;
67         gGlobal->printCompilationOptions(compile_options, false);
68 
69         // JSON generation
70         JSONInstVisitor<REAL> json_visitor1;
71         generateUserInterface(&json_visitor1);
72 
73         map<string, int> path_index_table;
74         for (const auto& it : json_visitor1.fPathTable) {
75             // Get field index
76             path_index_table[it.second] = fStructVisitor.getFieldOffset(it.first);
77         }
78 
79         faustassert(fStructVisitor.getFieldOffset("fSampleRate") != -1);
80 
81         JSONInstVisitor<REAL> json_visitor2("", "", fNumInputs, fNumOutputs, fStructVisitor.getFieldOffset("fSampleRate"), "", "",
82         FAUSTVERSION, compile_options.str(), gGlobal->gReader.listLibraryFiles(),
83         gGlobal->gImportDirList, fStructVisitor.getStructSize(), path_index_table);
84         generateUserInterface(&json_visitor2);
85         generateMetaData(&json_visitor2);
86 
87         BasicBlock* return_block = BasicBlock::Create(*fContext, "return_block", getJSON);
88         ReturnInst::Create(*fContext, fCodeProducer->genStringConstant(json_visitor2.JSON(true)), return_block);
89 
90         verifyFunction(*getJSON);
91         fBuilder->ClearInsertionPoint();
92     }
93 
94     void init(const string& name, int numInputs, int numOutputs, Module* module, LLVMContext* context);
95 
96    public:
97     LLVMCodeContainer(const string& name, int numInputs, int numOutputs);
98     LLVMCodeContainer(const string& name, int numInputs, int numOutputs, Module* module, LLVMContext* context);
99     virtual ~LLVMCodeContainer();
100 
101     virtual dsp_factory_base* produceFactory();
102     void                      produceInternal();
103 
104     CodeContainer* createScalarContainer(const string& name, int sub_container_type);
105 
106     static CodeContainer* createContainer(const string& name, int numInputs, int numOutputs);
107 };
108 
109 class LLVMScalarCodeContainer : public LLVMCodeContainer {
110    protected:
111     void       generateCompute();
112     BlockInst* generateComputeAux();
113 
114    public:
115     LLVMScalarCodeContainer(const string& name, int numInputs, int numOutputs);
116     LLVMScalarCodeContainer(const string& name, int numInputs, int numOutputs, Module* module, LLVMContext* context,
117                             int sub_container_type);
118     virtual ~LLVMScalarCodeContainer();
119 };
120 
121 class LLVMVectorCodeContainer : public VectorCodeContainer, public LLVMCodeContainer {
122    protected:
123     void       generateCompute();
124     BlockInst* generateComputeAux();
125 
126    public:
127     LLVMVectorCodeContainer(const string& name, int numInputs, int numOutputs);
128     virtual ~LLVMVectorCodeContainer();
129 };
130 
131 class LLVMOpenMPCodeContainer : public OpenMPCodeContainer, public LLVMCodeContainer {
132    protected:
133     void       generateOMPDeclarations();
134     void       generateOMPCompute();
135     void       generateCompute();
136     BlockInst* generateComputeAux();
137 
138     void      generateGOMP_parallel_start();
139     void      generateGOMP_parallel_end();
140     LLVMValue generateGOMP_single_start();
141     void      generateGOMP_barrier();
142     void      generateGOMP_sections_start(LLVMValue num);
143     void      generateGOMP_sections_end();
144     void      generateGOMP_sections_next();
145 
146     void generateDSPOMPCompute();
147 
148    public:
149     LLVMOpenMPCodeContainer(const string& name, int numInputs, int numOutputs);
150     virtual ~LLVMOpenMPCodeContainer();
151 };
152 
153 class LLVMWorkStealingCodeContainer : public WSSCodeContainer, public LLVMCodeContainer {
154    protected:
155     void       generateCompute();
156     BlockInst* generateComputeAux();
157 
158    public:
159     LLVMWorkStealingCodeContainer(const string& name, int numInputs, int numOutputs);
160     virtual ~LLVMWorkStealingCodeContainer();
161 };
162 
163 #endif
164