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 #include <fstream>
23 
24 #include "instructions.hh"
25 #include "floats.hh"
26 #include "global.hh"
27 #include "sigtype.hh"
28 #include "fir_to_fir.hh"
29 
30 // Used when inlining functions
31 std::stack<BlockInst*> BasicCloneVisitor::fBlockStack;
32 
isStructType(const string & name)33 DeclareStructTypeInst* isStructType(const string& name)
34 {
35     if (gGlobal->gVarTypeTable.find(name) != gGlobal->gVarTypeTable.end()) {
36         Typed*         type     = gGlobal->gVarTypeTable[name];
37         Typed::VarType ext_type = Typed::getTypeFromPtr(type->getType());
38         // If type is an external Structured type
39         if (gGlobal->gExternalStructTypes.find(ext_type) != gGlobal->gExternalStructTypes.end()) {
40             return gGlobal->gExternalStructTypes[ext_type];
41         }
42     }
43     return nullptr;
44 }
45 
genTypedZero(Typed::VarType type)46 ValueInst* InstBuilder::genTypedZero(Typed::VarType type)
47 {
48     if (type == Typed::kInt32) {
49         return genInt32NumInst(0);
50     } else if (type == Typed::kInt64) {
51         return genInt64NumInst(0);
52     } else if (isRealType(type)) {
53         return genRealNumInst(type, 0.);
54     } else {
55         // Pointer type
56         if (gGlobal->gMachinePtrSize == 4) {
57             return genInt32NumInst(0);
58         } else {
59             return genInt64NumInst(0);
60         }
61     }
62 }
63 
ctType(Type t)64 Typed::VarType ctType(Type t)
65 {
66     return (t->nature() == kInt) ? Typed::kInt32 : Typed::kFloat;
67 }
68 
69 string Typed::gTypeString[] = {"kInt32",          "kInt32_ptr",      "kInt32_vec",          "kInt32_vec_ptr",
70                                "kInt64",          "kInt64_ptr",      "kInt64_vec",          "kInt64_vec_ptr",
71                                "kBool",           "kBool_ptr",       "kBool_vec",           "kBool_vec_ptr",
72                                "kFloat",          "kFloat_ptr",      "kFloat_ptr_ptr",      "kFloat_vec",
73                                "kFloat_vec_ptr",  "kFloatMacro",     "kFloatMacro_ptr",     "kFloatMacro_ptr_ptr",
74                                "kDouble",         "kDouble_ptr",     "kDouble_ptr_ptr",     "kDouble_vec",       "kDouble_vec_ptr",
75                                "kQuad",           "kQuad_ptr",       "kQuad_ptr_ptr",       "kQuad_vec",         "kQuad_vec_ptr",
76                                "kFixedPoint",     "kFixedPoint_ptr", "kFixedPoint_ptr_ptr", "kFixedPoint_vec",   "kFixedPoint_vec_ptr",
77                                "kVoid",           "kVoid_ptr",       "kVoid_ptr_ptr",
78                                "kObj",            "kObj_ptr",        "kSound",
79                                "kSound_ptr",      "kUint_ptr",       "kNoType"};
80 
cleanup()81 void BasicTyped::cleanup()
82 {
83     gGlobal->gTypeTable.clear();
84 }
cleanup()85 void DeclareVarInst::cleanup()
86 {
87     gGlobal->gVarTypeTable.clear();
88 }
89 
90 // Variable types are kept in the global name <===> type table
DeclareVarInst(Address * address,Typed * type,ValueInst * value)91 DeclareVarInst::DeclareVarInst(Address* address, Typed* type, ValueInst* value)
92     : fAddress(address), fType(type), fValue(value)
93 {
94     if (gGlobal->gVarTypeTable.find(fAddress->getName()) == gGlobal->gVarTypeTable.end()) {
95         gGlobal->gVarTypeTable[fAddress->getName()] = type;
96     } else if (gGlobal->gVarTypeTable[fAddress->getName()] != type) {
97         // If named type, check their name and internal type
98         NamedTyped* name_t1 = dynamic_cast<NamedTyped*>(gGlobal->gVarTypeTable[fAddress->getName()]);
99         NamedTyped* name_t2 = dynamic_cast<NamedTyped*>(type);
100         if (name_t1 && name_t2) {
101             faustassert(name_t1->fName == name_t2->fName && name_t1->fType == name_t2->fType);
102         } else {
103             // If array type, check their size and internal type
104             ArrayTyped* array_t1 = dynamic_cast<ArrayTyped*>(gGlobal->gVarTypeTable[fAddress->getName()]);
105             ArrayTyped* arry_t2  = dynamic_cast<ArrayTyped*>(type);
106             if (array_t1 && arry_t2) {
107                 faustassert(array_t1->fSize == arry_t2->fSize && array_t1->fType == arry_t2->fType);
108             } else {
109                 faustassert(false);
110             }
111         }
112     }
113 }
114 
115 // Function types (return type) are kept in the global name <===> type table
DeclareFunInst(const string & name,FunTyped * type,BlockInst * code)116 DeclareFunInst::DeclareFunInst(const string& name, FunTyped* type, BlockInst* code)
117     : fName(name), fType(type), fCode(code)
118 {
119     if (gGlobal->gVarTypeTable.find(name) == gGlobal->gVarTypeTable.end()) {
120         gGlobal->gVarTypeTable[name] = type;
121     } else {
122         FunTyped* fun_type = static_cast<FunTyped*>(gGlobal->gVarTypeTable[name]);
123         // If same result type
124         if (fun_type->getTyped() == type->getTyped()) {
125             if ((gGlobal->gOutputLang == "llvm") && (fun_type->getPrototype() != type->getPrototype())) {
126                 stringstream str;
127                 str << "ERROR : foreign function '" << name
128                     << "' conflicts with another (possibly compiler internally defined) function with a different "
129                        "prototype\n";
130                 throw faustexception(str.str());
131             }
132         } else {
133             stringstream str;
134             str << "ERROR : foreign function '" << name
135                 << "' conflicts with another (possibly compiler internally defined) function with a different return "
136                    "type\n";
137             throw faustexception(str.str());
138         }
139     }
140 }
141 
genBasicTyped(Typed::VarType type)142 BasicTyped* InstBuilder::genBasicTyped(Typed::VarType type)
143 {
144     return gGlobal->genBasicTyped(type);
145 }
146 
getSize() const147 int BasicTyped::getSize() const
148 {
149     faustassert(gGlobal->gTypeSizeMap.find(fType) != gGlobal->gTypeSizeMap.end());
150     return gGlobal->gTypeSizeMap[fType];
151 }
152 
getSize() const153 int FunTyped::getSize() const
154 {
155     return gGlobal->gTypeSizeMap[Typed::kVoid_ptr];
156 }
157 
getSize() const158 int ArrayTyped::getSize() const
159 {
160     if (fSize == 0) {
161         // Array of zero size are treated as pointer in the corresponding type
162         faustassert(gGlobal->gTypeSizeMap.find(getType()) != gGlobal->gTypeSizeMap.end());
163         return gGlobal->gTypeSizeMap[getType()];
164     } else {
165         return fType->getSize() * fSize;
166     }
167 }
168 
169 // Function argument variable types are kept in the global num <===> type table
genNamedTyped(const string & name,Typed * type)170 NamedTyped* InstBuilder::genNamedTyped(const string& name, Typed* type)
171 {
172     if (gGlobal->gVarTypeTable.find(name) == gGlobal->gVarTypeTable.end()) {
173         // cout << "InstBuilder::genNamedTyped " << name << " " << Typed::gTypeString[type->getType()] << endl;
174         gGlobal->gVarTypeTable[name] = type;
175     }
176     return new NamedTyped(name, type);
177 }
178 
179 // Function argument variable types are kept in the global num <===> type table
genNamedTyped(const string & name,Typed::VarType type)180 NamedTyped* InstBuilder::genNamedTyped(const string& name, Typed::VarType type)
181 {
182     return genNamedTyped(name, genBasicTyped(type));
183 }
184 
genCastFloatInst(ValueInst * inst)185 ValueInst* InstBuilder::genCastFloatInst(ValueInst* inst)
186 {
187     return InstBuilder::genCastInst(inst, InstBuilder::genBasicTyped(itfloat()));
188 }
189 
genCastFloatMacroInst(ValueInst * inst)190 ValueInst* InstBuilder::genCastFloatMacroInst(ValueInst* inst)
191 {
192     return InstBuilder::genCastInst(inst, InstBuilder::genFloatMacroTyped());
193 }
194 
genCastInt32Inst(ValueInst * inst)195 ValueInst* InstBuilder::genCastInt32Inst(ValueInst* inst)
196 {
197     return InstBuilder::genCastInst(inst, InstBuilder::genInt32Typed());
198 }
199 
200 // BasicTyped are not cloned, but actually point on the same underlying type
visit(BasicTyped * typed)201 Typed* BasicCloneVisitor::visit(BasicTyped* typed)
202 {
203     return gGlobal->gTypeTable[typed->fType];
204 }
205 
hasReturn() const206 bool BlockInst::hasReturn() const
207 {
208     list<StatementInst*>::const_iterator it = fCode.end();
209     it--;
210     return dynamic_cast<RetInst*>(*it);
211 }
212 
213 // Return the block value (if is has one) and remove it from the block
getReturnValue()214 ValueInst* BlockInst::getReturnValue()
215 {
216     list<StatementInst*>::const_iterator it = fCode.end();
217     it--;
218     RetInst* ret = dynamic_cast<RetInst*>(*it);
219     if (ret) {
220         fCode.pop_back();
221         return ret->fResult;
222     } else {
223         return InstBuilder::genNullValueInst();
224     }
225 }
226 
store(ValueInst * exp)227 struct StoreVarInst* DeclareVarInst::store(ValueInst* exp)
228 {
229     return InstBuilder::genStoreVarInst(fAddress, exp);
230 }
231 
load()232 struct LoadVarInst* DeclareVarInst::load()
233 {
234     return InstBuilder::genLoadVarInst(fAddress);
235 }
236 
hasCondition(ValueInst * cond)237 bool ControlInst::hasCondition(ValueInst* cond)
238 {
239     // Compare string representation of both conditions
240     stringstream res1;
241     stringstream res2;
242     dump2FIR(fCond, &res1, false);
243     dump2FIR(cond, &res2, false);
244     return (res1.str() == res2.str());
245 }
246 
247 // Function calls
genVoidFunction(const string & name,BlockInst * code)248 DeclareFunInst* InstBuilder::genVoidFunction(const string& name, BlockInst* code)
249 {
250     list<NamedTyped*> args;
251     FunTyped*         fun_type = InstBuilder::genFunTyped(args, InstBuilder::genVoidTyped());
252     return InstBuilder::genDeclareFunInst(name, fun_type, code);
253 }
254 
genVoidFunction(const string & name,list<NamedTyped * > & args,BlockInst * code,bool isvirtual)255 DeclareFunInst* InstBuilder::genVoidFunction(const string& name, list<NamedTyped*>& args, BlockInst* code,
256                                              bool isvirtual)
257 {
258     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genVoidTyped(),
259                                                   (isvirtual) ? FunTyped::kVirtual : FunTyped::kDefault);
260     return InstBuilder::genDeclareFunInst(name, fun_type, code);
261 }
262 
genFunction0(const string & name,Typed::VarType res,BlockInst * code)263 DeclareFunInst* InstBuilder::genFunction0(const string& name, Typed::VarType res, BlockInst* code)
264 {
265     list<NamedTyped*> args;
266     FunTyped*         fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
267     return InstBuilder::genDeclareFunInst(name, fun_type, code);
268 }
269 
genFunction1(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,BlockInst * code)270 DeclareFunInst* InstBuilder::genFunction1(const string& name, Typed::VarType res, const string& arg1,
271                                           Typed::VarType arg1_ty, BlockInst* code)
272 {
273     list<NamedTyped*> args;
274     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
275     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
276     return InstBuilder::genDeclareFunInst(name, fun_type, code);
277 }
278 
genFunction2(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,const string & arg2,Typed::VarType arg2_ty,BlockInst * code)279 DeclareFunInst* InstBuilder::genFunction2(const string& name, Typed::VarType res, const string& arg1,
280                                           Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
281                                           BlockInst* code)
282 {
283     list<NamedTyped*> args;
284     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
285     args.push_back(InstBuilder::genNamedTyped(arg2, arg2_ty));
286     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
287     return InstBuilder::genDeclareFunInst(name, fun_type, code);
288 }
289 
genFunction3(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,const string & arg2,Typed::VarType arg2_ty,const string & arg3,Typed::VarType arg3_ty,BlockInst * code)290 DeclareFunInst* InstBuilder::genFunction3(const string& name, Typed::VarType res, const string& arg1,
291                                           Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
292                                           const string& arg3, Typed::VarType arg3_ty, BlockInst* code)
293 {
294     list<NamedTyped*> args;
295     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
296     args.push_back(InstBuilder::genNamedTyped(arg2, arg2_ty));
297     args.push_back(InstBuilder::genNamedTyped(arg3, arg3_ty));
298     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
299     return InstBuilder::genDeclareFunInst(name, fun_type, code);
300 }
301 
genFunction4(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,const string & arg2,Typed::VarType arg2_ty,const string & arg3,Typed::VarType arg3_ty,const string & arg4,Typed::VarType arg4_ty,BlockInst * code)302 DeclareFunInst* InstBuilder::genFunction4(const string& name, Typed::VarType res, const string& arg1,
303                                           Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
304                                           const string& arg3, Typed::VarType arg3_ty, const string& arg4,
305                                           Typed::VarType arg4_ty, BlockInst* code)
306 {
307     list<NamedTyped*> args;
308     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
309     args.push_back(InstBuilder::genNamedTyped(arg2, arg2_ty));
310     args.push_back(InstBuilder::genNamedTyped(arg3, arg3_ty));
311     args.push_back(InstBuilder::genNamedTyped(arg4, arg4_ty));
312     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
313     return InstBuilder::genDeclareFunInst(name, fun_type, code);
314 }
315 
genFunction5(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,const string & arg2,Typed::VarType arg2_ty,const string & arg3,Typed::VarType arg3_ty,const string & arg4,Typed::VarType arg4_ty,const string & arg5,Typed::VarType arg5_ty,BlockInst * code)316 DeclareFunInst* InstBuilder::genFunction5(const string& name, Typed::VarType res, const string& arg1,
317                                           Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
318                                           const string& arg3, Typed::VarType arg3_ty, const string& arg4,
319                                           Typed::VarType arg4_ty, const string& arg5, Typed::VarType arg5_ty,
320                                           BlockInst* code)
321 {
322     list<NamedTyped*> args;
323     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
324     args.push_back(InstBuilder::genNamedTyped(arg2, arg2_ty));
325     args.push_back(InstBuilder::genNamedTyped(arg3, arg3_ty));
326     args.push_back(InstBuilder::genNamedTyped(arg4, arg4_ty));
327     args.push_back(InstBuilder::genNamedTyped(arg5, arg5_ty));
328     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
329     return InstBuilder::genDeclareFunInst(name, fun_type, code);
330 }
331 
genFunction6(const string & name,Typed::VarType res,const string & arg1,Typed::VarType arg1_ty,const string & arg2,Typed::VarType arg2_ty,const string & arg3,Typed::VarType arg3_ty,const string & arg4,Typed::VarType arg4_ty,const string & arg5,Typed::VarType arg5_ty,const string & arg6,Typed::VarType arg6_ty,BlockInst * code)332 DeclareFunInst* InstBuilder::genFunction6(const string& name, Typed::VarType res, const string& arg1,
333                                           Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
334                                           const string& arg3, Typed::VarType arg3_ty, const string& arg4,
335                                           Typed::VarType arg4_ty, const string& arg5, Typed::VarType arg5_ty,
336                                           const string& arg6, Typed::VarType arg6_ty, BlockInst* code)
337 {
338     list<NamedTyped*> args;
339     args.push_back(InstBuilder::genNamedTyped(arg1, arg1_ty));
340     args.push_back(InstBuilder::genNamedTyped(arg2, arg2_ty));
341     args.push_back(InstBuilder::genNamedTyped(arg3, arg3_ty));
342     args.push_back(InstBuilder::genNamedTyped(arg4, arg4_ty));
343     args.push_back(InstBuilder::genNamedTyped(arg5, arg5_ty));
344     args.push_back(InstBuilder::genNamedTyped(arg6, arg6_ty));
345     FunTyped* fun_type = InstBuilder::genFunTyped(args, InstBuilder::genBasicTyped(res));
346     return InstBuilder::genDeclareFunInst(name, fun_type, code);
347 }
348 
isSimpleValue() const349 bool LoadVarInst::isSimpleValue() const
350 {
351     NamedAddress* named = dynamic_cast<NamedAddress*>(fAddress);
352     IndexedAddress* indexed = dynamic_cast<IndexedAddress*>(fAddress);
353     return named || (indexed && dynamic_cast<Int32NumInst*>(indexed->getIndex()));
354 }
355 
Dispatch2Visitor(ValueInst * inst)356 void ScalVecDispatcherVisitor::Dispatch2Visitor(ValueInst* inst)
357 {
358     std::cout << "Dispatch2Visitor %d\n";
359     fScalarVisitor->visit(inst);
360 
361     /*
362      if (inst->fSize == 1) {
363         fScalarVisitor->visit(inst);
364      } else {
365         fVectorVisitor->visit(inst);
366      }
367     */
368 }
369 
370 //--------------------------
371 // Coding Types as trees
372 //--------------------------
373 
374 // // 09/12/11 : HACK
375 /*
376 static Sym TYPEINT = symbol ("TypeInt");
377 Tree  typeInt()                    { return tree(TYPEINT);         }
378 bool  isTypeInt(Tree t)            { return isTree(t, TYPEINT);    }
379 
380 static Sym TYPEFLOAT = symbol ("TypeFloat");
381 Tree  typeFloat()                { return tree(TYPEFLOAT);         }
382 bool  isTypeFloat(Tree t)        { return isTree(t, TYPEFLOAT);    }
383 
384 static Sym TYPEARRAY = symbol ("TypeArray");
385 Tree  typeArray(int n, Tree t)                    { return tree(TYPEARRAY, tree(n), t);         }
386 bool  isTypeArray(Tree t, int* n, Tree& u)        { Tree x; return isTree(t, TYPEARRAY, x, u) && isInt(x->node(), n); }
387 
388 static property<DeclareTypeInst* > gFirTypeProperty;
389 
390 map<string, int> InstBuilder::fIDCounters;
391 
392 static Tree signalTypeToSharedType(AudioType* type)
393 {
394     if (isSimpleType(type)) {
395         if (type->nature() == kInt32) {
396             return typeInt();
397         } else if (type->nature() == kReal) {
398             return typeFloat();
399         } else {
400             faustassert(false);
401         }
402     } else if (FaustVectorType* vec = isVectorType(type)) {
403         return typeArray(vec->size(), signalTypeToSharedType(vec->dereferenceType()));
404     } else {
405         faustassert(false);
406     }
407 }
408 
409 DeclareTypeInst* InstBuilder::genType(AudioType* type)
410 {
411     Tree shared_type = signalTypeToSharedType(type);
412     DeclareTypeInst* dec_type;
413 
414     if (gFirTypeProperty.get(shared_type, dec_type)) {
415         return dec_type;
416     } else {
417         if (isSimpleType(type)) {
418             if (type->nature() == kInt32) {
419                 printf("FaustVectorType intType \n");
420                 dec_type = genDeclareTypeInst(InstBuilder::genInt32Typed());
421             } else if (type->nature() == kReal) {
422                 printf("FaustVectorType floatType \n");
423                 dec_type = genDeclareTypeInst(InstBuilder::genFloatTyped());
424             } else {
425                 faustassert(false);
426             }
427         } else if (FaustVectorType* vec = isVectorType(type)) {
428             printf("FaustVectorType size %d\n", vec->size());
429             DeclareTypeInst* sub_type = genType(vec->dereferenceType());
430             dec_type = genDeclareTypeInst(genStructTyped(getFreshID("vecType"),
431 InstBuilder::genArrayTyped(sub_type->fType, vec->size()))); } else { faustassert(false);
432         }
433     }
434 
435     gFirTypeProperty.set(shared_type, dec_type);
436     return dec_type;
437 }
438 
439 static Typed* sharedTypeToFirType(Tree t)
440 {
441     int size;
442     Tree subtree;
443 
444     if (isTypeInt(t)) {
445         printf("sharedTypeToFirType isTypeInt\n");
446         return InstBuilder::genInt32Typed();
447     } else if (isTypeFloat(t)) {
448         printf("sharedTypeToFirType isTypeFloat\n");
449         return InstBuilder::genFloatTyped();
450     } else if (isTypeArray(t, &size, subtree)) {
451         printf("sharedTypeToFirType isTypeArray size %d\n", size);
452         return InstBuilder::genArrayTyped(sharedTypeToFirType(subtree), size);
453     } else {
454         faustassert(false);
455         return nullptr;
456     }
457 }
458 
459 DeclareTypeInst* InstBuilder::genType(AudioType* type)
460 {
461     Tree shared_type = signalTypeToSharedType(type);
462     DeclareTypeInst* dec_type;
463 
464     if (gFirTypeProperty.get(shared_type, dec_type)) {
465         return dec_type;
466     } else {
467         DeclareTypeInst* dec_type
468             = genDeclareTypeInst(getFreshID("vecType"), sharedTypeToFirType(shared_type));
469         gFirTypeProperty.set(shared_type, dec_type);
470         return dec_type;
471     }
472 }
473 */
474