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