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 _INSTRUCTIONS_H
23 #define _INSTRUCTIONS_H
24 
25 #include <stdio.h>
26 #include <algorithm>
27 #include <iostream>
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <sstream>
32 #include <stack>
33 #include <string>
34 #include <vector>
35 
36 #ifdef WIN32
37 #pragma warning(disable : 4800)
38 #endif
39 
40 #include "Text.hh"
41 #include "binop.hh"
42 #include "exception.hh"
43 #include "garbageable.hh"
44 #include "instructions_type.hh"
45 #include "property.hh"
46 #include "sigtype.hh"
47 
48 // ============================
49 // Generic instruction visitor
50 // ============================
51 
52 struct Printable;
53 struct NullValueInst;
54 struct NullStatementInst;
55 struct DeclareVarInst;
56 struct DeclareBufferIterators;
57 struct DeclareFunInst;
58 struct DeclareStructTypeInst;
59 struct LoadVarInst;
60 struct LoadVarAddressInst;
61 struct TeeVarInst;
62 struct StoreVarInst;
63 struct ShiftArrayVarInst;
64 template <class TYPE>
65 struct ArrayNumInst;
66 struct FloatNumInst;
67 struct FloatArrayNumInst;
68 struct Int32NumInst;
69 struct Int64NumInst;
70 struct Int32ArrayNumInst;
71 struct BoolNumInst;
72 struct DoubleNumInst;
73 struct DoubleArrayNumInst;
74 struct FixedPointNumInst;
75 struct FixedPointArrayNumInst;
76 struct BinopInst;
77 struct CastInst;
78 struct BitcastInst;
79 struct RetInst;
80 struct DropInst;
81 
82 struct FunCallInst;
83 struct Select2Inst;
84 struct ControlInst;
85 struct IfInst;
86 struct ForLoopInst;
87 struct SimpleForLoopInst;
88 struct IteratorForLoopInst;
89 struct WhileLoopInst;
90 struct BlockInst;
91 struct SwitchInst;
92 
93 // User interface
94 struct AddMetaDeclareInst;
95 struct OpenboxInst;
96 struct CloseboxInst;
97 struct AddButtonInst;
98 struct AddSliderInst;
99 struct AddBargraphInst;
100 struct AddSoundfileInst;
101 struct LabelInst;
102 
103 struct Typed;
104 struct Address;
105 struct ValueInst;
106 struct StatementInst;
107 
108 struct BasicTyped;
109 struct NamedTyped;
110 struct FunTyped;
111 struct ArrayTyped;
112 struct StructTyped;
113 struct VectorTyped;
114 
115 struct NamedAddress;
116 struct IndexedAddress;
117 
118 // Type checking
119 
isRealType(Typed::VarType type)120 inline bool isRealType(Typed::VarType type)
121 {
122     return (type == Typed::kFloat || type == Typed::kFloatMacro || type == Typed::kDouble);
123 }
124 
isRealPtrType(Typed::VarType type)125 inline bool isRealPtrType(Typed::VarType type)
126 {
127     return (type == Typed::kFloat_ptr
128             || type == Typed::kFloat_ptr_ptr
129             || type == Typed::kFloatMacro_ptr
130             || type == Typed::kFloatMacro_ptr_ptr
131             || type == Typed::kDouble_ptr
132             || type == Typed::kDouble_ptr_ptr);
133 }
134 
isIntType(Typed::VarType type)135 inline bool isIntType(Typed::VarType type)
136 {
137     return (type == Typed::kInt32 || type == Typed::kInt64);
138 }
139 
isInt32Type(Typed::VarType type)140 inline bool isInt32Type(Typed::VarType type)
141 {
142     return (type == Typed::kInt32);
143 }
144 
isInt64Type(Typed::VarType type)145 inline bool isInt64Type(Typed::VarType type)
146 {
147     return (type == Typed::kInt64);
148 }
149 
isFloatType(Typed::VarType type)150 inline bool isFloatType(Typed::VarType type)
151 {
152     return (type == Typed::kFloat);
153 }
154 
isDoubleType(Typed::VarType type)155 inline bool isDoubleType(Typed::VarType type)
156 {
157     return (type == Typed::kDouble);
158 }
159 
isIntPtrType(Typed::VarType type)160 inline bool isIntPtrType(Typed::VarType type)
161 {
162     return (type == Typed::kInt32_ptr || type == Typed::kInt64_ptr);
163 }
164 
isPtrType(Typed::VarType type)165 inline bool isPtrType(Typed::VarType type)
166 {
167     return isRealPtrType(type) || isIntPtrType(type);
168 }
169 
isBoolType(Typed::VarType type)170 inline bool isBoolType(Typed::VarType type)
171 {
172     return (type == Typed::kBool);
173 }
174 
isIntOrPtrType(Typed::VarType type)175 inline bool isIntOrPtrType(Typed::VarType type)
176 {
177     return (isIntType(type)
178             || isIntPtrType(type)
179             || isRealPtrType(type)
180             || type == Typed::kVoid_ptr
181             || type == Typed::kObj_ptr
182             || type == Typed::kSound_ptr);
183 }
184 
185 DeclareStructTypeInst* isStructType(const string& name);
186 
187 // =========
188 // Visitors
189 // =========
190 
191 struct InstVisitor : public virtual Garbageable {
InstVisitorInstVisitor192     InstVisitor() {}
~InstVisitorInstVisitor193     virtual ~InstVisitor() {}
194 
195     // User interface
visitInstVisitor196     virtual void visit(AddMetaDeclareInst* inst) {}
visitInstVisitor197     virtual void visit(OpenboxInst* inst) {}
visitInstVisitor198     virtual void visit(CloseboxInst* inst) {}
visitInstVisitor199     virtual void visit(AddButtonInst* inst) {}
visitInstVisitor200     virtual void visit(AddSliderInst* inst) {}
visitInstVisitor201     virtual void visit(AddBargraphInst* inst) {}
visitInstVisitor202     virtual void visit(AddSoundfileInst* inst) {}
203 
visitInstVisitor204     virtual void visit(LabelInst* inst) {}
205 
visitInstVisitor206     virtual void visit(Printable* inst) {}
visitInstVisitor207     virtual void visit(NullValueInst* inst) {}
visitInstVisitor208     virtual void visit(NullStatementInst* inst) {}
209 
210     // Declarations
visitInstVisitor211     virtual void visit(DeclareVarInst* inst) {}
visitInstVisitor212     virtual void visit(DeclareFunInst* inst) {}
visitInstVisitor213     virtual void visit(DeclareStructTypeInst* inst) {}
visitInstVisitor214     virtual void visit(DeclareBufferIterators* inst) {}
215 
216     // Memory
visitInstVisitor217     virtual void visit(LoadVarInst* inst) {}
visitInstVisitor218     virtual void visit(LoadVarAddressInst* inst) {}
visitInstVisitor219     virtual void visit(TeeVarInst* inst) {}
visitInstVisitor220     virtual void visit(StoreVarInst* inst) {}
visitInstVisitor221     virtual void visit(ShiftArrayVarInst* inst) {}
222 
223     // Addresses
visitInstVisitor224     virtual void visit(NamedAddress* address) {}
visitInstVisitor225     virtual void visit(IndexedAddress* address) {}
226 
227     // Numbers
visitInstVisitor228     virtual void visit(FloatNumInst* inst) {}
visitInstVisitor229     virtual void visit(FloatArrayNumInst* inst) {}
visitInstVisitor230     virtual void visit(Int32NumInst* inst) {}
visitInstVisitor231     virtual void visit(Int64NumInst* inst) {}
visitInstVisitor232     virtual void visit(Int32ArrayNumInst* inst) {}
visitInstVisitor233     virtual void visit(BoolNumInst* inst) {}
visitInstVisitor234     virtual void visit(DoubleNumInst* inst) {}
visitInstVisitor235     virtual void visit(DoubleArrayNumInst* inst) {}
visitInstVisitor236     virtual void visit(FixedPointNumInst* inst) {}
visitInstVisitor237     virtual void visit(FixedPointArrayNumInst* inst) {}
238 
239     // Numerical computation
visitInstVisitor240     virtual void visit(BinopInst* inst) {}
241 
242     // Cast
visitInstVisitor243     virtual void visit(CastInst* inst) {}
visitInstVisitor244     virtual void visit(BitcastInst* inst) {}
245 
246     // Function call
visitInstVisitor247     virtual void visit(FunCallInst* inst) {}
visitInstVisitor248     virtual void visit(RetInst* inst) {}
visitInstVisitor249     virtual void visit(DropInst* inst) {}
250 
251     // Conditional
visitInstVisitor252     virtual void visit(Select2Inst* inst) {}
visitInstVisitor253     virtual void visit(ControlInst* inst) {}
visitInstVisitor254     virtual void visit(IfInst* inst) {}
visitInstVisitor255     virtual void visit(SwitchInst* inst) {}
256 
257     // Loops
visitInstVisitor258     virtual void visit(ForLoopInst* inst) {}
visitInstVisitor259     virtual void visit(SimpleForLoopInst* inst) {}
visitInstVisitor260     virtual void visit(IteratorForLoopInst* inst) {}
visitInstVisitor261     virtual void visit(WhileLoopInst* inst) {}
262 
263     // Block
visitInstVisitor264     virtual void visit(BlockInst* inst) {}
265 
266     // Typed
visitInstVisitor267     virtual void visit(BasicTyped* typed) {}
visitInstVisitor268     virtual void visit(NamedTyped* typed) {}
visitInstVisitor269     virtual void visit(FunTyped* typed) {}
visitInstVisitor270     virtual void visit(ArrayTyped* typed) {}
visitInstVisitor271     virtual void visit(StructTyped* typed) {}
visitInstVisitor272     virtual void visit(VectorTyped* typed) {}
273 };
274 
275 // Clone a FIR expression
276 
277 struct CloneVisitor : public virtual Garbageable {
CloneVisitorCloneVisitor278     CloneVisitor() {}
~CloneVisitorCloneVisitor279     virtual ~CloneVisitor() {}
280 
281     virtual ValueInst*     visit(NullValueInst* inst)     = 0;
282     virtual StatementInst* visit(NullStatementInst* inst) = 0;
283 
284     // Declarations
285     virtual StatementInst* visit(DeclareVarInst* inst)        = 0;
286     virtual StatementInst* visit(DeclareFunInst* inst)        = 0;
287     virtual StatementInst* visit(DeclareStructTypeInst* inst) = 0;
288     virtual StatementInst* visit(DeclareBufferIterators* inst) = 0;
289 
290     // Memory
291     virtual ValueInst*     visit(LoadVarInst* inst)        = 0;
292     virtual ValueInst*     visit(LoadVarAddressInst* inst) = 0;
293     virtual ValueInst*     visit(TeeVarInst* inst)         = 0;
294     virtual StatementInst* visit(StoreVarInst* inst)       = 0;
295     virtual StatementInst* visit(ShiftArrayVarInst* inst)  = 0;
296 
297     // Addresses
298     virtual Address* visit(NamedAddress* address)   = 0;
299     virtual Address* visit(IndexedAddress* address) = 0;
300 
301     // Numbers
302     virtual ValueInst* visit(FloatNumInst* inst)       = 0;
303     virtual ValueInst* visit(FloatArrayNumInst* inst)  = 0;
304     virtual ValueInst* visit(Int32NumInst* inst)       = 0;
305     virtual ValueInst* visit(Int64NumInst* inst)       = 0;
306     virtual ValueInst* visit(Int32ArrayNumInst* inst)  = 0;
307     virtual ValueInst* visit(BoolNumInst* inst)        = 0;
308     virtual ValueInst* visit(DoubleNumInst* inst)      = 0;
309     virtual ValueInst* visit(DoubleArrayNumInst* inst) = 0;
310     virtual ValueInst* visit(FixedPointNumInst* inst)      = 0;
311     virtual ValueInst* visit(FixedPointArrayNumInst* inst) = 0;
312 
313     // Numerical computation
314     virtual ValueInst* visit(BinopInst* inst) = 0;
315 
316     // Cast
317     virtual ValueInst* visit(CastInst* inst)    = 0;
318     virtual ValueInst* visit(BitcastInst* inst) = 0;
319 
320     // Function call
321     virtual ValueInst*     visit(FunCallInst* inst) = 0;
322     virtual StatementInst* visit(RetInst* inst)     = 0;
323     virtual StatementInst* visit(DropInst* inst)    = 0;
324 
325     // Conditional
326     virtual ValueInst*     visit(Select2Inst* inst) = 0;
327     virtual StatementInst* visit(ControlInst* inst) = 0;
328     virtual StatementInst* visit(IfInst* inst)      = 0;
329     virtual StatementInst* visit(SwitchInst* inst)  = 0;
330 
331     // Loops
332     virtual StatementInst* visit(ForLoopInst* inst)       = 0;
333     virtual StatementInst* visit(SimpleForLoopInst* inst) = 0;
334     virtual StatementInst* visit(IteratorForLoopInst* inst) = 0;
335     virtual StatementInst* visit(WhileLoopInst* inst)     = 0;
336 
337     // Block
338     virtual StatementInst* visit(BlockInst* inst) = 0;
339 
340     // User interface
341     virtual StatementInst* visit(AddMetaDeclareInst* inst) = 0;
342     virtual StatementInst* visit(OpenboxInst* inst)        = 0;
343     virtual StatementInst* visit(CloseboxInst* inst)       = 0;
344     virtual StatementInst* visit(AddButtonInst* inst)      = 0;
345     virtual StatementInst* visit(AddSliderInst* inst)      = 0;
346     virtual StatementInst* visit(AddBargraphInst* inst)    = 0;
347     virtual StatementInst* visit(AddSoundfileInst* inst)   = 0;
348     virtual StatementInst* visit(LabelInst* inst)          = 0;
349 
350     // Types
351     virtual Typed* visit(BasicTyped* type)  = 0;
352     virtual Typed* visit(NamedTyped* type)  = 0;
353     virtual Typed* visit(FunTyped* type)    = 0;
354     virtual Typed* visit(ArrayTyped* type)  = 0;
355     virtual Typed* visit(StructTyped* type) = 0;
356     virtual Typed* visit(VectorTyped* type) = 0;
357 };
358 
359 // ============================
360 // Base class for instructions
361 // ============================
362 
363 // Printable is defined in instructions_type.h
364 
365 // Added in compilation environment
366 struct StatementInst : public Printable {
367     virtual void accept(InstVisitor* visitor) = 0;
368 
369     virtual StatementInst* clone(CloneVisitor* cloner) = 0;
370 
getNameStatementInst371     virtual string getName() const { return ""; }
372 };
373 
374 // Results from the compilation
375 struct ValueInst : public Printable {
376     virtual void accept(InstVisitor* visitor) = 0;
377 
378     virtual ValueInst* clone(CloneVisitor* cloner) = 0;
379 
ValueInstValueInst380     ValueInst() {}
381 
sizeValueInst382     virtual int size() const { return 1; }
383 
isSimpleValueValueInst384     virtual bool isSimpleValue() const { return false; }
385 };
386 
387 // =======================
388 // Null value instruction
389 // =======================
390 
391 struct NullValueInst : public ValueInst {
NullValueInstNullValueInst392     NullValueInst() {}
393 
acceptNullValueInst394     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
395 
cloneNullValueInst396     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
397 };
398 
399 // ===========================
400 // Null statement instruction
401 // ===========================
402 
403 struct NullStatementInst : public StatementInst {
NullStatementInstNullStatementInst404     NullStatementInst() {}
405 
acceptNullStatementInst406     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
407 
cloneNullStatementInst408     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
409 };
410 
411 // ==========================
412 //  Instruction with a type
413 // ==========================
414 
415 // Base type is defined in instructions_type.h
416 
417 Typed::VarType ctType(Type t);
418 
419 struct BasicTyped : public Typed {
420     const VarType fType;
421 
422     static void cleanup();
423 
BasicTypedBasicTyped424     BasicTyped(VarType type) : fType(type) {}
425 
getTypeBasicTyped426     VarType getType() const { return fType; }
427 
428     int getSize() const;  // moved in "instructions.cpp"
429 
acceptBasicTyped430     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
431 
cloneBasicTyped432     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
433 };
434 
435 struct NamedTyped : public Typed {
436     const string fName;
437     Typed* fType;
438 
NamedTypedNamedTyped439     NamedTyped(const string& name, Typed* type) : fName(name), fType(type) {}
440 
~NamedTypedNamedTyped441     virtual ~NamedTyped() {}
442 
getTypeNamedTyped443     VarType getType() const { return fType->getType(); }
444 
getSizeNamedTyped445     int getSize() const { return fType->getSize(); }
446 
acceptNamedTyped447     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
448 
cloneNamedTyped449     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
450 };
451 
452 struct FunTyped : public Typed {
453     enum FunAttribute { kDefault = 0x1, kLocal = 0x2, kVirtual = 0x4, kStatic = 0x8, kInline = 0x10 };
454 
455     list<NamedTyped*> fArgsTypes;
456     BasicTyped*       fResult;
457     FunAttribute      fAttribute;
458 
FunTypedFunTyped459     FunTyped(const list<NamedTyped*>& args, BasicTyped* result, FunAttribute attribute = kDefault)
460         : fArgsTypes(args), fResult(result), fAttribute(attribute)
461     {
462     }
463 
getTypeFunTyped464     VarType getType() const { return fResult->getType(); }
465 
getTypedFunTyped466     Typed* getTyped() { return fResult; }
467 
468     // Arguments type encoded as a string
getPrototypeFunTyped469     string getPrototype()
470     {
471         string res;
472         if (fArgsTypes.size() > 0) {
473             for (const auto& it : fArgsTypes) {
474                 res += gTypeString[it->getType()];
475             }
476         } else {
477             res = "void";
478         }
479         return res;
480     }
481 
482     int getSize() const;  // moved in "instructions.cpp"
483 
acceptFunTyped484     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
485 
cloneFunTyped486     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
487 };
488 
489 struct ArrayTyped : public Typed {
490     Typed*     fType;
491     const int  fSize;
492     const bool fIsPtr;
493 
ArrayTypedArrayTyped494     ArrayTyped(Typed* type, int size, bool is_ptr = false) : fType(type), fSize(size), fIsPtr(is_ptr) {}
495 
~ArrayTypedArrayTyped496     virtual ~ArrayTyped() {}
497 
getTypeArrayTyped498     VarType getType() const { return getPtrFromType(fType->getType()); }
499 
500     int getSize() const;  // moved in "instructions.cpp"
501 
acceptArrayTyped502     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
503 
cloneArrayTyped504     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
505 };
506 
507 struct StructTyped : public Typed {
508     const string        fName;
509     vector<NamedTyped*> fFields;
510 
StructTypedStructTyped511     StructTyped(const string& name, const vector<NamedTyped*>& fields) : fName(name), fFields(fields) {}
512 
~StructTypedStructTyped513     virtual ~StructTyped() {}
514 
getTypeStructTyped515     VarType getType() const { return kObj_ptr; }
getTypeStructTyped516     VarType getType(int index) { return fFields[index]->getType(); }
517 
getSizeStructTyped518     int getSize() const
519     {
520         int size = 0;
521         for (const auto& it : fFields) {
522             size += it->getSize();
523         }
524         return size;
525     }
526 
getOffsetStructTyped527     int getOffset(int field) const
528     {
529         int offset = 0;
530         for (int i = 0; i < field; i++) {
531             offset += fFields[i]->getSize();
532         }
533         return offset;
534     }
535 
getNameStructTyped536     string getName(int index) { return fFields[index]->fName; }
537 
acceptStructTyped538     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
539 
cloneStructTyped540     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
541 };
542 
543 struct VectorTyped : public Typed {
544     BasicTyped* fType;
545     const int  fSize;
546 
VectorTypedVectorTyped547     VectorTyped(BasicTyped* type, int size) : fType(type), fSize(size) {}
548 
~VectorTypedVectorTyped549     virtual ~VectorTyped() {}
550 
getTypeVectorTyped551     VarType getType() const { return getVecFromType(fType->getType()); }
552 
getSizeVectorTyped553     int getSize() const { return fType->getSize() * fSize; }
554 
acceptVectorTyped555     virtual void accept(InstVisitor* visitor) { visitor->visit(this); }
556 
cloneVectorTyped557     Typed* clone(CloneVisitor* cloner) { return cloner->visit(this); }
558 };
559 
560 struct NumValueInst {
561 };
562 
563 // ===========
564 //  Addresses
565 // ===========
566 
567 struct Address : public Printable {
568     enum AccessType {
569         kStruct       = 0x1,
570         kStaticStruct = 0x2,  // Static shared variable between all DSPs
571         kFunArgs      = 0x4,
572         kStack        = 0x8,
573         kGlobal       = 0x10,
574         kLink         = 0x20,
575         kLoop         = 0x40,
576         kVolatile     = 0x80,
577         kReference    = 0x100,  // Access by reference (for Rust backend)
578         kMutable      = 0x200,  // Mutable access (for Rust backend)
579         kConst        = 0x400   // Const access
580     };
581 
AddressAddress582     Address() {}
583 
584     virtual void                setAccess(Address::AccessType type) = 0;
585     virtual Address::AccessType getAccess() const                   = 0;
586 
587     virtual void   setName(const string& name) = 0;
588     virtual string getName() const             = 0;
589 
dumpAddress590     static void dump(AccessType access) { *fOut << dumpString(access); }
591 
592 #define hasAccess(arg) res += (res != "") ? (string("|") + string(arg)) : string(arg);
593 
dumpStringAddress594     static string dumpString(AccessType access)
595     {
596         string res;
597         if (access & kStruct) hasAccess("kStruct");
598         if (access & kStaticStruct) hasAccess("kStaticStruct");
599         if (access & kFunArgs) hasAccess("kFunArgs");
600         if (access & kStack) hasAccess("kStack");
601         if (access & kGlobal) hasAccess("kGlobal");
602         if (access & kLink) hasAccess("kLink");
603         if (access & kLoop) hasAccess("kLoop");
604         if (access & kVolatile) hasAccess("kVolatile");
605         if (access & kReference) hasAccess("kReference");
606         if (access & kMutable) hasAccess("kMutable");
607         if (access & kConst) hasAccess("kConst");
608         return res;
609     }
610 
611     virtual Address* clone(CloneVisitor* cloner) = 0;
612 
613     virtual void accept(InstVisitor* visitor) = 0;
614 };
615 
616 struct NamedAddress : public Address {
617     string fName;
618     AccessType   fAccess;
619 
NamedAddressNamedAddress620     NamedAddress(const string& name, AccessType access) : fName(name), fAccess(access) {}
621 
setAccessNamedAddress622     void                setAccess(Address::AccessType type) { fAccess = type; }
getAccessNamedAddress623     Address::AccessType getAccess() const { return fAccess; }
624 
setNameNamedAddress625     void   setName(const string& name) { fName = name; }
getNameNamedAddress626     string getName() const { return fName; }
627 
cloneNamedAddress628     Address* clone(CloneVisitor* cloner) { return cloner->visit(this); }
629 
acceptNamedAddress630     void accept(InstVisitor* visitor) { visitor->visit(this); }
631 };
632 
633 struct IndexedAddress : public Address {
634     Address*   fAddress;
635     ValueInst* fIndex;
636 
IndexedAddressIndexedAddress637     IndexedAddress(Address* address, ValueInst* index) : fAddress(address), fIndex(index) {}
638 
~IndexedAddressIndexedAddress639     virtual ~IndexedAddress() {}
640 
setAccessIndexedAddress641     void                setAccess(Address::AccessType type) { fAddress->setAccess(type); }
getAccessIndexedAddress642     Address::AccessType getAccess() const { return fAddress->getAccess(); }
643 
setNameIndexedAddress644     void   setName(const string& name) { fAddress->setName(name); }
getNameIndexedAddress645     string getName() const { return fAddress->getName(); }
646 
getIndexIndexedAddress647     ValueInst* getIndex() const { return fIndex; }
648 
cloneIndexedAddress649     Address* clone(CloneVisitor* cloner) { return cloner->visit(this); }
650 
acceptIndexedAddress651     void accept(InstVisitor* visitor) { visitor->visit(this); }
652 };
653 
654 // ===============
655 // User interface
656 // ===============
657 
658 struct AddMetaDeclareInst : public StatementInst {
659     const string fZone;
660     const string fKey;
661     const string fValue;
662 
AddMetaDeclareInstAddMetaDeclareInst663     AddMetaDeclareInst(const string& zone, const string& key, const string& value)
664         : fZone(zone), fKey(key), fValue(value)
665     {
666     }
667 
acceptAddMetaDeclareInst668     void accept(InstVisitor* visitor) { visitor->visit(this); }
669 
cloneAddMetaDeclareInst670     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
671 };
672 
673 struct OpenboxInst : public StatementInst {
674     enum BoxType { kVerticalBox, kHorizontalBox, kTabBox };
675 
676     const string  fName;
677     const BoxType fOrient;
678 
OpenboxInstOpenboxInst679     OpenboxInst(const string& name, BoxType orient) : fName(name), fOrient(orient) {}
680 
acceptOpenboxInst681     void accept(InstVisitor* visitor) { visitor->visit(this); }
682 
cloneOpenboxInst683     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
684 };
685 
686 struct CloseboxInst : public StatementInst {
CloseboxInstCloseboxInst687     CloseboxInst() {}
688 
acceptCloseboxInst689     void accept(InstVisitor* visitor) { visitor->visit(this); }
690 
cloneCloseboxInst691     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
692 };
693 
694 struct AddButtonInst : public StatementInst {
695     enum ButtonType { kDefaultButton, kCheckButton };
696 
697     const string     fLabel;
698     const string     fZone;
699     const ButtonType fType;
700 
AddButtonInstAddButtonInst701     AddButtonInst(const string& label, const string& zone, ButtonType type) : fLabel(label), fZone(zone), fType(type) {}
702 
acceptAddButtonInst703     void accept(InstVisitor* visitor) { visitor->visit(this); }
704 
cloneAddButtonInst705     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
706 };
707 
708 struct AddSliderInst : public StatementInst {
709     enum SliderType { kHorizontal, kVertical, kNumEntry };
710 
711     const string     fLabel;
712     const string     fZone;
713     const double     fInit;
714     const double     fMin;
715     const double     fMax;
716     const double     fStep;
717     const SliderType fType;
718 
AddSliderInstAddSliderInst719     AddSliderInst(const string& label, const string& zone, double init, double min, double max, double step,
720                   SliderType type)
721         : fLabel(label), fZone(zone), fInit(init), fMin(min), fMax(max), fStep(step), fType(type)
722     {
723     }
724 
acceptAddSliderInst725     void accept(InstVisitor* visitor) { visitor->visit(this); }
726 
cloneAddSliderInst727     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
728 };
729 
730 struct AddBargraphInst : public StatementInst {
731     enum BargraphType { kHorizontal, kVertical };
732 
733     const string       fLabel;
734     const string       fZone;
735     const double       fMin;
736     const double       fMax;
737     const BargraphType fType;
738 
AddBargraphInstAddBargraphInst739     AddBargraphInst(const string& label, const string& zone, double min, double max, BargraphType type)
740         : fLabel(label), fZone(zone), fMin(min), fMax(max), fType(type)
741     {
742     }
743 
acceptAddBargraphInst744     void accept(InstVisitor* visitor) { visitor->visit(this); }
745 
cloneAddBargraphInst746     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
747 };
748 
749 struct AddSoundfileInst : public StatementInst {
750     const string fLabel;
751     const string fURL;
752     const string fSFZone;
753 
AddSoundfileInstAddSoundfileInst754     AddSoundfileInst(const string& label, const string& url, const string& sf_zone)
755         : fLabel(label), fURL(url), fSFZone(sf_zone)
756     {
757     }
758 
acceptAddSoundfileInst759     void accept(InstVisitor* visitor) { visitor->visit(this); }
760 
cloneAddSoundfileInst761     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
762 };
763 
764 struct LabelInst : public StatementInst {
765     const string fLabel;
766 
LabelInstLabelInst767     LabelInst(const string& label) : fLabel(label) {}
768 
acceptLabelInst769     void accept(InstVisitor* visitor) { visitor->visit(this); }
770 
cloneLabelInst771     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
772 };
773 
774 // =============
775 // Declarations
776 // =============
777 
778 struct DeclareVarInst : public StatementInst {
779     Address*   fAddress;
780     Typed*     fType;
781     ValueInst* fValue;
782 
783     static void cleanup();
784 
785     DeclareVarInst(Address* address, Typed* typed, ValueInst* value);
786 
~DeclareVarInstDeclareVarInst787     virtual ~DeclareVarInst() {}
788 
setAccessDeclareVarInst789     void                setAccess(Address::AccessType type) { fAddress->setAccess(type); }
getAccessDeclareVarInst790     Address::AccessType getAccess() const  { return fAddress->getAccess(); }
791 
setNameDeclareVarInst792     void   setName(const string& name) { fAddress->setName(name); }
getNameDeclareVarInst793     string getName() const { return fAddress->getName(); }
794 
acceptDeclareVarInst795     void accept(InstVisitor* visitor) { visitor->visit(this); }
796 
cloneDeclareVarInst797     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
798 
799     struct StoreVarInst* store(ValueInst* val);
800     struct LoadVarInst*  load();
801 };
802 
803 struct DeclareBufferIterators : public StatementInst {
804     std::string fBufferName1;
805     std::string fBufferName2;
806     int         fNumChannels;
807     bool        fMutable;
808 
DeclareBufferIteratorsDeclareBufferIterators809     DeclareBufferIterators(const std::string& name1, const std::string& name2, int num_channels, bool mut) :
810         fBufferName1(name1), fBufferName2(name2), fNumChannels(num_channels), fMutable(mut)
811         {};
812 
~DeclareBufferIteratorsDeclareBufferIterators813     virtual ~DeclareBufferIterators() {}
814 
acceptDeclareBufferIterators815     void accept(InstVisitor* visitor) { visitor->visit(this); }
816 
cloneDeclareBufferIterators817     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
818 };
819 
820 // ==============
821 // Memory access
822 // ==============
823 
824 struct DropInst : public StatementInst {
825     ValueInst* fResult;
826 
DropInstDropInst827     DropInst(ValueInst* result = nullptr) : fResult(result) {}
828 
~DropInstDropInst829     virtual ~DropInst() {}
830 
acceptDropInst831     void accept(InstVisitor* visitor) { visitor->visit(this); }
832 
cloneDropInst833     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
834 };
835 
836 struct LoadVarInst : public ValueInst {
837     Address* fAddress;
838 
LoadVarInstLoadVarInst839     LoadVarInst(Address* address) : ValueInst(), fAddress(address) {}
840 
~LoadVarInstLoadVarInst841     virtual ~LoadVarInst() {}
842 
setNameLoadVarInst843     void   setName(const string& name) { fAddress->setName(name); }
getNameLoadVarInst844     string getName() const { return fAddress->getName(); }
845 
acceptLoadVarInst846     void accept(InstVisitor* visitor) { visitor->visit(this); }
847 
cloneLoadVarInst848     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
849 
850     virtual bool isSimpleValue() const;
851 
852 };
853 
854 struct LoadVarAddressInst : public ValueInst {
855     Address* fAddress;
856 
LoadVarAddressInstLoadVarAddressInst857     LoadVarAddressInst(Address* address) : ValueInst(), fAddress(address) {}
858 
~LoadVarAddressInstLoadVarAddressInst859     virtual ~LoadVarAddressInst() {}
860 
setNameLoadVarAddressInst861     void   setName(const string& name) { fAddress->setName(name); }
getNameLoadVarAddressInst862     string getName() const { return fAddress->getName(); }
863 
acceptLoadVarAddressInst864     void accept(InstVisitor* visitor) { visitor->visit(this); }
865 
cloneLoadVarAddressInst866     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
867 
isSimpleValueLoadVarAddressInst868     virtual bool isSimpleValue() const { return dynamic_cast<NamedAddress*>(fAddress); }
869 };
870 
871 // Special for wast/wasm backend : combine a store and a load
872 struct TeeVarInst : public ValueInst {
873     Address*   fAddress;
874     ValueInst* fValue;
875 
TeeVarInstTeeVarInst876     TeeVarInst(Address* address, ValueInst* value) : ValueInst(), fAddress(address), fValue(value) {}
877 
~TeeVarInstTeeVarInst878     virtual ~TeeVarInst() {}
879 
setNameTeeVarInst880     void   setName(const string& name) { fAddress->setName(name); }
getNameTeeVarInst881     string getName() const { return fAddress->getName(); }
882 
acceptTeeVarInst883     void accept(InstVisitor* visitor) { visitor->visit(this); }
884 
cloneTeeVarInst885     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
886 };
887 
888 struct StoreVarInst : public StatementInst {
889     Address*   fAddress;
890     ValueInst* fValue;
891 
StoreVarInstStoreVarInst892     StoreVarInst(Address* address, ValueInst* value) : fAddress(address), fValue(value) {}
893 
~StoreVarInstStoreVarInst894     virtual ~StoreVarInst() {}
895 
setNameStoreVarInst896     void   setName(const string& name) { fAddress->setName(name); }
getNameStoreVarInst897     string getName() const { return fAddress->getName(); }
898 
acceptStoreVarInst899     void accept(InstVisitor* visitor) { visitor->visit(this); }
900 
cloneStoreVarInst901     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
902 };
903 
904 struct ShiftArrayVarInst : public StatementInst {
905     Address*  fAddress;
906     const int fDelay;
907 
ShiftArrayVarInstShiftArrayVarInst908     ShiftArrayVarInst(Address* address, int delay) : fAddress(address), fDelay(delay) {}
909 
~ShiftArrayVarInstShiftArrayVarInst910     virtual ~ShiftArrayVarInst() {}
911 
acceptShiftArrayVarInst912     void accept(InstVisitor* visitor) { visitor->visit(this); }
913 
cloneShiftArrayVarInst914     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
915 };
916 
917 // ========
918 // Numbers
919 // ========
920 
921 struct FloatNumInst : public ValueInst, public NumValueInst {
922     const float fNum;
923 
FloatNumInstFloatNumInst924     FloatNumInst(float num) : ValueInst(), fNum(num) {}
925 
acceptFloatNumInst926     void accept(InstVisitor* visitor) { visitor->visit(this); }
927 
cloneFloatNumInst928     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
929 
isSimpleValueFloatNumInst930     virtual bool isSimpleValue() const { return true; }
931 };
932 
933 template <class TYPE>
934 struct ArrayNumInst : public ValueInst {
935     vector<TYPE> fNumTable;
936 
ArrayNumInstArrayNumInst937     ArrayNumInst(const vector<TYPE>& nums) : ValueInst(), fNumTable(nums) {}
938 
ArrayNumInstArrayNumInst939     ArrayNumInst(int size) : ValueInst() { fNumTable.resize(size); }
940 
setValueArrayNumInst941     void setValue(int index, TYPE num) { fNumTable[index] = num; }
addValueArrayNumInst942     void addValue(TYPE num) { fNumTable.push_back(num); }
getValueArrayNumInst943     TYPE getValue(int index) { return fNumTable[index]; }
944 
acceptArrayNumInst945     void accept(InstVisitor* visitor) { visitor->visit(this); }
946 
isSimpleValueArrayNumInst947     virtual bool isSimpleValue() const { return true; }
948 };
949 
950 struct FloatArrayNumInst : public ArrayNumInst<float> {
FloatArrayNumInstFloatArrayNumInst951     FloatArrayNumInst(const vector<float>& nums) : ArrayNumInst<float>(nums) {}
FloatArrayNumInstFloatArrayNumInst952     FloatArrayNumInst(int size) : ArrayNumInst<float>(size) {}
953 
acceptFloatArrayNumInst954     void accept(InstVisitor* visitor) { visitor->visit(this); }
955 
cloneFloatArrayNumInst956     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
957 };
958 
959 struct DoubleNumInst : public ValueInst, public NumValueInst {
960     const double fNum;
961 
DoubleNumInstDoubleNumInst962     DoubleNumInst(double num) : ValueInst(), fNum(num) {}
963 
acceptDoubleNumInst964     void accept(InstVisitor* visitor) { visitor->visit(this); }
965 
cloneDoubleNumInst966     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
967 
isSimpleValueDoubleNumInst968     virtual bool isSimpleValue() const { return true; }
969 };
970 
971 struct DoubleArrayNumInst : public ArrayNumInst<double> {
DoubleArrayNumInstDoubleArrayNumInst972     DoubleArrayNumInst(const vector<double>& nums) : ArrayNumInst<double>(nums) {}
DoubleArrayNumInstDoubleArrayNumInst973     DoubleArrayNumInst(int size) : ArrayNumInst<double>(size) {}
974 
acceptDoubleArrayNumInst975     void accept(InstVisitor* visitor) { visitor->visit(this); }
976 
cloneDoubleArrayNumInst977     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
978 };
979 
980 struct FixedPointNumInst : public ValueInst, public NumValueInst {
981     const double fNum;
982 
FixedPointNumInstFixedPointNumInst983     FixedPointNumInst(double num) : ValueInst(), fNum(num) {}
984 
acceptFixedPointNumInst985     void accept(InstVisitor* visitor) { visitor->visit(this); }
986 
cloneFixedPointNumInst987     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
988 
isSimpleValueFixedPointNumInst989     virtual bool isSimpleValue() const { return true; }
990 };
991 
992 struct FixedPointArrayNumInst : public ArrayNumInst<double> {
FixedPointArrayNumInstFixedPointArrayNumInst993     FixedPointArrayNumInst(const vector<double>& nums) : ArrayNumInst<double>(nums) {}
FixedPointArrayNumInstFixedPointArrayNumInst994     FixedPointArrayNumInst(int size) : ArrayNumInst<double>(size) {}
995 
acceptFixedPointArrayNumInst996     void accept(InstVisitor* visitor) { visitor->visit(this); }
997 
cloneFixedPointArrayNumInst998     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
999 };
1000 
1001 struct Int32NumInst : public ValueInst, public NumValueInst {
1002     const int fNum;
1003 
Int32NumInstInt32NumInst1004     Int32NumInst(int num) : ValueInst(), fNum(num) {}
1005 
acceptInt32NumInst1006     void accept(InstVisitor* visitor) { visitor->visit(this); }
1007 
cloneInt32NumInst1008     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1009 
isSimpleValueInt32NumInst1010     virtual bool isSimpleValue() const { return true; }
1011 };
1012 
1013 struct Int64NumInst : public ValueInst, public NumValueInst {
1014     const int64_t fNum;
1015 
Int64NumInstInt64NumInst1016     Int64NumInst(int64_t num) : ValueInst(), fNum(num) {}
1017 
acceptInt64NumInst1018     void accept(InstVisitor* visitor) { visitor->visit(this); }
1019 
cloneInt64NumInst1020     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1021 
isSimpleValueInt64NumInst1022     virtual bool isSimpleValue() const { return true; }
1023 };
1024 
1025 struct Int32ArrayNumInst : public ArrayNumInst<int> {
Int32ArrayNumInstInt32ArrayNumInst1026     Int32ArrayNumInst(const vector<int>& nums) : ArrayNumInst<int>(nums) {}
Int32ArrayNumInstInt32ArrayNumInst1027     Int32ArrayNumInst(int size) : ArrayNumInst<int>(size) {}
1028 
acceptInt32ArrayNumInst1029     void accept(InstVisitor* visitor) { visitor->visit(this); }
1030 
cloneInt32ArrayNumInst1031     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1032 };
1033 
1034 struct BoolNumInst : public ValueInst, public NumValueInst {
1035     const bool fNum;
1036 
BoolNumInstBoolNumInst1037     BoolNumInst(bool num) : ValueInst(), fNum(num) {}
1038 
acceptBoolNumInst1039     void accept(InstVisitor* visitor) { visitor->visit(this); }
1040 
cloneBoolNumInst1041     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1042 
isSimpleValueBoolNumInst1043     virtual bool isSimpleValue() const { return true; }
1044 };
1045 
1046 // ======================
1047 // Numerical computation
1048 // ======================
1049 
1050 struct BinopInst : public ValueInst {
1051     const int  fOpcode;
1052     ValueInst* fInst1;
1053     ValueInst* fInst2;
1054 
BinopInstBinopInst1055     BinopInst(int opcode, ValueInst* inst1, ValueInst* inst2)
1056         : ValueInst(), fOpcode(opcode), fInst1(inst1), fInst2(inst2)
1057     {
1058     }
1059 
~BinopInstBinopInst1060     virtual ~BinopInst() {}
1061 
acceptBinopInst1062     void accept(InstVisitor* visitor) { visitor->visit(this); }
1063 
cloneBinopInst1064     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1065 
sizeBinopInst1066     virtual int size() const { return fInst1->size() + fInst2->size(); }
1067 };
1068 
1069 // =====
1070 // Cast
1071 // =====
1072 
1073 struct CastInst : public ValueInst {
1074     Typed*     fType;
1075     ValueInst* fInst;
1076 
CastInstCastInst1077     CastInst(ValueInst* inst, Typed* typed) : ValueInst(), fType(typed), fInst(inst) {}
1078 
~CastInstCastInst1079     virtual ~CastInst() {}
1080 
acceptCastInst1081     void accept(InstVisitor* visitor) { visitor->visit(this); }
1082 
cloneCastInst1083     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1084 
sizeCastInst1085     virtual int size() const { return fInst->size(); }
1086 };
1087 
1088 struct BitcastInst : public ValueInst {
1089     Typed*     fType;
1090     ValueInst* fInst;
1091 
BitcastInstBitcastInst1092     BitcastInst(ValueInst* inst, Typed* typed) : ValueInst(), fType(typed), fInst(inst) {}
1093 
~BitcastInstBitcastInst1094     virtual ~BitcastInst() {}
1095 
acceptBitcastInst1096     void accept(InstVisitor* visitor) { visitor->visit(this); }
1097 
cloneBitcastInst1098     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1099 
sizeBitcastInst1100     virtual int size() const { return fInst->size(); }
1101 };
1102 
1103 // =============
1104 // Control flow
1105 // =============
1106 
1107 struct BlockInst : public StatementInst {
1108     list<StatementInst*> fCode;
1109     bool                 fIndent;
1110 
BlockInstBlockInst1111     BlockInst(list<StatementInst*> code) : fCode(code), fIndent(false) {}
1112 
BlockInstBlockInst1113     BlockInst() : fIndent(false) {}
1114 
~BlockInstBlockInst1115     virtual ~BlockInst() {}
1116 
setIndentBlockInst1117     void setIndent(bool indent) { fIndent = indent; }
getIndentBlockInst1118     bool getIndent() { return fIndent; }
1119 
acceptBlockInst1120     void accept(InstVisitor* visitor) { visitor->visit(this); }
1121 
cloneBlockInst1122     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1123 
pushFrontInstBlockInst1124     void pushFrontInst(StatementInst* inst) { fCode.push_front(inst); }
1125 
pushBackInstBlockInst1126     void pushBackInst(StatementInst* inst) { fCode.push_back(inst); }
1127 
mergeBlockInst1128     void merge(BlockInst* inst)
1129     {
1130         for (const auto& it : inst->fCode) {
1131             fCode.push_back(it);
1132         }
1133     }
1134 
sizeBlockInst1135     int size() const { return int(fCode.size()); }
1136 
1137     bool hasReturn() const;
1138     ValueInst* getReturnValue();
1139 };
1140 
1141 struct Select2Inst : public ValueInst {
1142     ValueInst* fCond;
1143     ValueInst* fThen;
1144     ValueInst* fElse;
1145 
Select2InstSelect2Inst1146     Select2Inst(ValueInst* cond_inst, ValueInst* then_inst, ValueInst* else_inst)
1147         : ValueInst(), fCond(cond_inst), fThen(then_inst), fElse(else_inst)
1148     {
1149     }
1150 
~Select2InstSelect2Inst1151     virtual ~Select2Inst() {}
1152 
acceptSelect2Inst1153     void accept(InstVisitor* visitor) { visitor->visit(this); }
1154 
cloneSelect2Inst1155     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1156 
sizeSelect2Inst1157     virtual int size() const { return std::max(fThen->size(), fElse->size()); }
1158 };
1159 
1160 // Contains a condition (derived from 'enable/contol') and a statement to be computed if the cond is true
1161 struct ControlInst : public StatementInst {
1162     ValueInst* fCond;
1163     StatementInst* fStatement;
1164 
ControlInstControlInst1165     ControlInst(ValueInst* cond_inst, StatementInst* exp_inst)
1166     : fCond(cond_inst), fStatement(exp_inst)
1167     {
1168     }
1169 
~ControlInstControlInst1170     virtual ~ControlInst() {}
1171 
1172     // Test if (cond == fCond)
1173     bool hasCondition(ValueInst* cond);
1174 
acceptControlInst1175     void accept(InstVisitor* visitor) { visitor->visit(this); }
1176 
cloneControlInst1177     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1178 
1179 };
1180 
1181 struct IfInst : public StatementInst {
1182     ValueInst* fCond;
1183     BlockInst* fThen;
1184     BlockInst* fElse;
1185 
IfInstIfInst1186     IfInst(ValueInst* cond_inst, BlockInst* then_inst, BlockInst* else_inst)
1187         : fCond(cond_inst), fThen(then_inst), fElse(else_inst)
1188     {
1189     }
1190 
IfInstIfInst1191     IfInst(ValueInst* cond_inst, BlockInst* then_inst) : fCond(cond_inst), fThen(then_inst), fElse(new BlockInst()) {}
1192 
~IfInstIfInst1193     virtual ~IfInst() {}
1194 
acceptIfInst1195     void accept(InstVisitor* visitor) { visitor->visit(this); }
1196 
cloneIfInst1197     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1198 };
1199 
1200 struct SwitchInst : public StatementInst {
1201     ValueInst*                   fCond;
1202     list<pair<int, BlockInst*> > fCode;
1203 
SwitchInstSwitchInst1204     SwitchInst(ValueInst* cond, const list<pair<int, BlockInst*> >& code) : fCond(cond), fCode(code) {}
1205 
SwitchInstSwitchInst1206     SwitchInst(ValueInst* cond) : fCond(cond) {}
1207 
~SwitchInstSwitchInst1208     virtual ~SwitchInst() {}
1209 
addCaseSwitchInst1210     void addCase(int value, BlockInst* block) { fCode.push_back(make_pair(value, block)); }
1211 
acceptSwitchInst1212     void accept(InstVisitor* visitor) { visitor->visit(this); }
1213 
cloneSwitchInst1214     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1215 };
1216 
1217 struct RetInst : public StatementInst {
1218     ValueInst* fResult;
1219 
RetInstRetInst1220     RetInst(ValueInst* result = nullptr) : fResult(result) {}
1221 
~RetInstRetInst1222     virtual ~RetInst() {}
1223 
acceptRetInst1224     void accept(InstVisitor* visitor) { visitor->visit(this); }
1225 
cloneRetInst1226     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1227 };
1228 
1229 struct FunCallInst : public ValueInst {
1230     const string     fName;
1231     list<ValueInst*> fArgs;  // List of arguments
1232     const bool       fMethod;
1233 
FunCallInstFunCallInst1234     FunCallInst(const string& name, const list<ValueInst*>& args, bool method)
1235         : ValueInst(), fName(name), fArgs(args), fMethod(method)
1236     {
1237     }
1238 
~FunCallInstFunCallInst1239     virtual ~FunCallInst() {}
1240 
acceptFunCallInst1241     void accept(InstVisitor* visitor) { visitor->visit(this); }
1242 
cloneFunCallInst1243     ValueInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1244 };
1245 
1246 struct DeclareFunInst : public StatementInst {
1247     const string fName;
1248     FunTyped*    fType;  // Describes type of all arguments and function result
1249     BlockInst*   fCode;  // Code is a list of StatementInst*
1250 
1251     DeclareFunInst(const string& name, FunTyped* type, BlockInst* code = new BlockInst());
1252 
~DeclareFunInstDeclareFunInst1253     virtual ~DeclareFunInst() {}
1254 
getResTypeDeclareFunInst1255     Typed::VarType getResType() { return fType->fResult->getType(); }
1256 
acceptDeclareFunInst1257     void accept(InstVisitor* visitor) { visitor->visit(this); }
1258 
cloneDeclareFunInst1259     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1260 };
1261 
1262 struct DeclareStructTypeInst : public StatementInst {
1263     StructTyped* fType;
1264 
DeclareStructTypeInstDeclareStructTypeInst1265     DeclareStructTypeInst(StructTyped* type) : fType(type) {}
1266 
~DeclareStructTypeInstDeclareStructTypeInst1267     virtual ~DeclareStructTypeInst() {}
1268 
acceptDeclareStructTypeInst1269     void accept(InstVisitor* visitor) { visitor->visit(this); }
1270 
cloneDeclareStructTypeInst1271     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1272 };
1273 
1274 // ======
1275 // Loops
1276 // ======
1277 
1278 struct ForLoopInst : public StatementInst {
1279     StatementInst* fInit;
1280     StatementInst* fIncrement;
1281     ValueInst*     fEnd;
1282     BlockInst*     fCode;
1283     const bool     fIsRecursive;
1284 
ForLoopInstForLoopInst1285     ForLoopInst(StatementInst* init, ValueInst* end, StatementInst* increment, BlockInst* code, bool is_recursive)
1286         : fInit(init), fIncrement(increment), fEnd(end), fCode(code), fIsRecursive(is_recursive)
1287     {
1288     }
1289 
~ForLoopInstForLoopInst1290     virtual ~ForLoopInst() {}
1291 
pushFrontInstForLoopInst1292     void pushFrontInst(StatementInst* inst) { fCode->pushFrontInst(inst); }
1293 
pushBackInstForLoopInst1294     void pushBackInst(StatementInst* inst) { fCode->pushBackInst(inst); }
1295 
getNameForLoopInst1296     string getName() const { return fInit->getName(); }
1297 
acceptForLoopInst1298     void accept(InstVisitor* visitor) { visitor->visit(this); }
1299 
cloneForLoopInst1300     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1301 };
1302 
1303 // To be used for the 'rust' backend
1304 struct SimpleForLoopInst : public StatementInst {
1305     ValueInst*   fUpperBound;
1306     ValueInst*   fLowerBound;
1307     const string fName;
1308     const bool   fReverse;
1309     BlockInst* fCode;
1310 
SimpleForLoopInstSimpleForLoopInst1311     SimpleForLoopInst(const string& name, ValueInst* upperBound, ValueInst* lowerBound, bool reverse, BlockInst* code)
1312         : fUpperBound(upperBound), fLowerBound(lowerBound), fName(name), fReverse(reverse), fCode(code)
1313     {
1314     }
1315 
getNameSimpleForLoopInst1316     string getName() const { return fName; }
1317 
~SimpleForLoopInstSimpleForLoopInst1318     virtual ~SimpleForLoopInst() {}
1319 
pushFrontInstSimpleForLoopInst1320     void pushFrontInst(StatementInst* inst) { fCode->pushFrontInst(inst); }
1321 
pushBackInstSimpleForLoopInst1322     void pushBackInst(StatementInst* inst) { fCode->pushBackInst(inst); }
1323 
acceptSimpleForLoopInst1324     void accept(InstVisitor* visitor) { visitor->visit(this); }
1325 
cloneSimpleForLoopInst1326     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1327 };
1328 
1329 struct IteratorForLoopInst : public StatementInst {
1330     std::vector<NamedAddress*> fIterators;
1331     const bool                 fReverse;
1332     BlockInst*                 fCode;
1333 
IteratorForLoopInstIteratorForLoopInst1334     IteratorForLoopInst(const std::vector<NamedAddress*>& iterators, bool reverse, BlockInst* code)
1335         : fIterators(iterators), fReverse(reverse), fCode(code)
1336     {
1337     }
1338 
~IteratorForLoopInstIteratorForLoopInst1339     virtual ~IteratorForLoopInst() {}
1340 
pushFrontInstIteratorForLoopInst1341     void pushFrontInst(StatementInst* inst) { fCode->pushFrontInst(inst); }
1342 
pushBackInstIteratorForLoopInst1343     void pushBackInst(StatementInst* inst) { fCode->pushBackInst(inst); }
1344 
acceptIteratorForLoopInst1345     void accept(InstVisitor* visitor) { visitor->visit(this); }
1346 
cloneIteratorForLoopInst1347     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1348 };
1349 
1350 struct WhileLoopInst : public StatementInst {
1351     ValueInst* fCond;
1352     BlockInst* fCode;
1353 
WhileLoopInstWhileLoopInst1354     WhileLoopInst(ValueInst* cond, BlockInst* code) : fCond(cond), fCode(code) {}
1355 
~WhileLoopInstWhileLoopInst1356     virtual ~WhileLoopInst() {}
1357 
acceptWhileLoopInst1358     void accept(InstVisitor* visitor) { visitor->visit(this); }
1359 
cloneWhileLoopInst1360     StatementInst* clone(CloneVisitor* cloner) { return cloner->visit(this); }
1361 };
1362 
1363 // ====================
1364 // Basic clone visitor
1365 // ====================
1366 
1367 class BasicCloneVisitor : public CloneVisitor {
1368    protected:
1369     // Used when inlining functions
1370     static std::stack<BlockInst*> fBlockStack;
1371 
1372    public:
BasicCloneVisitor()1373     BasicCloneVisitor() {}
1374 
visit(NullValueInst * inst)1375     virtual NullValueInst*     visit(NullValueInst* inst) { return new NullValueInst(); }
visit(NullStatementInst * inst)1376     virtual NullStatementInst* visit(NullStatementInst* inst) { return new NullStatementInst(); }
1377 
1378     // Declarations
visit(DeclareVarInst * inst)1379     virtual StatementInst* visit(DeclareVarInst* inst)
1380     {
1381         return new DeclareVarInst(inst->fAddress->clone(this), inst->fType->clone(this),
1382                                   ((inst->fValue) ? inst->fValue->clone(this) : nullptr));
1383     }
visit(DeclareFunInst * inst)1384     virtual StatementInst* visit(DeclareFunInst* inst)
1385     {
1386         return new DeclareFunInst(inst->fName, static_cast<FunTyped*>(inst->fType->clone(this)),
1387                                   static_cast<BlockInst*>(inst->fCode->clone(this)));
1388     }
visit(DeclareStructTypeInst * inst)1389     virtual StatementInst* visit(DeclareStructTypeInst* inst)
1390     {
1391         return new DeclareStructTypeInst(static_cast<StructTyped*>(inst->fType->clone(this)));
1392     }
visit(DeclareBufferIterators * inst)1393     virtual StatementInst* visit(DeclareBufferIterators* inst)
1394     {
1395         return new DeclareBufferIterators(inst->fBufferName1, inst->fBufferName2, inst->fNumChannels, inst->fMutable);
1396     }
1397 
1398     // Memory
visit(LoadVarInst * inst)1399     virtual ValueInst* visit(LoadVarInst* inst) { return new LoadVarInst(inst->fAddress->clone(this)); }
visit(LoadVarAddressInst * inst)1400     virtual ValueInst* visit(LoadVarAddressInst* inst) { return new LoadVarAddressInst(inst->fAddress->clone(this)); }
visit(TeeVarInst * inst)1401     virtual ValueInst* visit(TeeVarInst* inst)
1402     {
1403         return new TeeVarInst(inst->fAddress->clone(this), inst->fValue->clone(this));
1404     }
visit(StoreVarInst * inst)1405     virtual StatementInst* visit(StoreVarInst* inst)
1406     {
1407         return new StoreVarInst(inst->fAddress->clone(this), inst->fValue->clone(this));
1408     }
visit(ShiftArrayVarInst * inst)1409     virtual StatementInst* visit(ShiftArrayVarInst* inst)
1410     {
1411         return new ShiftArrayVarInst(inst->fAddress->clone(this), inst->fDelay);
1412     }
1413 
1414     // Addresses
visit(NamedAddress * address)1415     virtual Address* visit(NamedAddress* address) { return new NamedAddress(address->fName, address->fAccess); }
visit(IndexedAddress * address)1416     virtual Address* visit(IndexedAddress* address)
1417     {
1418         return new IndexedAddress(address->fAddress->clone(this), address->fIndex->clone(this));
1419     }
1420 
1421     // Numbers
visit(FloatNumInst * inst)1422     virtual ValueInst* visit(FloatNumInst* inst) { return new FloatNumInst(inst->fNum); }
visit(FloatArrayNumInst * inst)1423     virtual ValueInst* visit(FloatArrayNumInst* inst) { return new FloatArrayNumInst(inst->fNumTable); }
visit(Int32NumInst * inst)1424     virtual ValueInst* visit(Int32NumInst* inst) { return new Int32NumInst(inst->fNum); }
visit(Int64NumInst * inst)1425     virtual ValueInst* visit(Int64NumInst* inst) { return new Int64NumInst(inst->fNum); }
visit(Int32ArrayNumInst * inst)1426     virtual ValueInst* visit(Int32ArrayNumInst* inst) { return new Int32ArrayNumInst(inst->fNumTable); }
visit(BoolNumInst * inst)1427     virtual ValueInst* visit(BoolNumInst* inst) { return new BoolNumInst(inst->fNum); }
visit(DoubleNumInst * inst)1428     virtual ValueInst* visit(DoubleNumInst* inst) { return new DoubleNumInst(inst->fNum); }
visit(DoubleArrayNumInst * inst)1429     virtual ValueInst* visit(DoubleArrayNumInst* inst) { return new DoubleArrayNumInst(inst->fNumTable); }
visit(FixedPointNumInst * inst)1430     virtual ValueInst* visit(FixedPointNumInst* inst) { return new FixedPointNumInst(inst->fNum); }
visit(FixedPointArrayNumInst * inst)1431     virtual ValueInst* visit(FixedPointArrayNumInst* inst) { return new FixedPointArrayNumInst(inst->fNumTable); }
1432 
1433     // Numerical computation
visit(BinopInst * inst)1434     virtual ValueInst* visit(BinopInst* inst)
1435     {
1436         return new BinopInst(inst->fOpcode, inst->fInst1->clone(this), inst->fInst2->clone(this));
1437     }
1438 
1439     // Cast
visit(CastInst * inst)1440     virtual ValueInst* visit(CastInst* inst)
1441     {
1442         return new CastInst(inst->fInst->clone(this), inst->fType->clone(this));
1443     }
1444 
visit(BitcastInst * inst)1445     virtual ValueInst* visit(BitcastInst* inst)
1446     {
1447         return new BitcastInst(inst->fInst->clone(this), inst->fType->clone(this));
1448     }
1449 
1450     // Function call
visit(FunCallInst * inst)1451     virtual ValueInst* visit(FunCallInst* inst)
1452     {
1453         list<ValueInst*> cloned_args;
1454         for (const auto& it : inst->fArgs) {
1455             cloned_args.push_back(it->clone(this));
1456         }
1457 
1458         return new FunCallInst(inst->fName, cloned_args, inst->fMethod);
1459     }
visit(RetInst * inst)1460     virtual StatementInst* visit(RetInst* inst)
1461     {
1462         return new RetInst((inst->fResult) ? inst->fResult->clone(this) : nullptr);
1463     }
visit(DropInst * inst)1464     virtual StatementInst* visit(DropInst* inst)
1465     {
1466         return new DropInst((inst->fResult) ? inst->fResult->clone(this) : nullptr);
1467     }
1468 
1469     // Conditional
visit(Select2Inst * inst)1470     virtual ValueInst* visit(Select2Inst* inst)
1471     {
1472         ValueInst* then_exp = inst->fThen->clone(this);
1473         ValueInst* else_exp = inst->fElse->clone(this);
1474         ValueInst* cond_exp = inst->fCond->clone(this);
1475         // cond_exp has to be evaluated last for FunctionInliner to correctly work in gHasTeeLocal mode
1476         return new Select2Inst(cond_exp, then_exp, else_exp);
1477     }
1478 
visit(ControlInst * inst)1479     virtual StatementInst* visit(ControlInst* inst)
1480     {
1481         return new ControlInst(inst->fCond->clone(this), inst->fStatement->clone(this));
1482     }
1483 
visit(IfInst * inst)1484     virtual StatementInst* visit(IfInst* inst)
1485     {
1486         return new IfInst(inst->fCond->clone(this), static_cast<BlockInst*>(inst->fThen->clone(this)),
1487                           static_cast<BlockInst*>(inst->fElse->clone(this)));
1488     }
visit(SwitchInst * inst)1489     virtual StatementInst* visit(SwitchInst* inst)
1490     {
1491         SwitchInst* cloned = new SwitchInst(inst->fCond->clone(this));
1492         for (const auto& it : inst->fCode) {
1493             cloned->addCase(it.first, static_cast<BlockInst*>((it.second)->clone(this)));
1494         }
1495         return cloned;
1496     }
1497 
1498     // Loop
visit(ForLoopInst * inst)1499     virtual StatementInst* visit(ForLoopInst* inst)
1500     {
1501         return new ForLoopInst(inst->fInit->clone(this), inst->fEnd->clone(this), inst->fIncrement->clone(this),
1502                                static_cast<BlockInst*>(inst->fCode->clone(this)), inst->fIsRecursive);
1503     }
1504 
visit(SimpleForLoopInst * inst)1505     virtual StatementInst* visit(SimpleForLoopInst* inst)
1506     {
1507         return new SimpleForLoopInst(inst->fName, inst->fUpperBound->clone(this), inst->fLowerBound->clone(this),
1508                                      inst->fReverse, static_cast<BlockInst*>(inst->fCode->clone(this)));
1509     }
1510 
visit(IteratorForLoopInst * inst)1511     virtual StatementInst* visit(IteratorForLoopInst* inst)
1512     {
1513         return new IteratorForLoopInst(inst->fIterators, inst->fReverse, static_cast<BlockInst*>(inst->fCode->clone(this)));
1514     }
1515 
visit(WhileLoopInst * inst)1516     virtual StatementInst* visit(WhileLoopInst* inst)
1517     {
1518         return new WhileLoopInst(inst->fCond->clone(this), static_cast<BlockInst*>(inst->fCode->clone(this)));
1519     }
1520 
1521     // Block
visit(BlockInst * inst)1522     virtual StatementInst* visit(BlockInst* inst)
1523     {
1524         // fBlockStack is used when inlining functions
1525         BlockInst* cloned = new BlockInst();
1526         fBlockStack.push(cloned);
1527         for (const auto& it : inst->fCode) {
1528             cloned->pushBackInst(it->clone(this));
1529         }
1530         fBlockStack.pop();
1531         return cloned;
1532     }
1533 
1534     // User interface
visit(AddMetaDeclareInst * inst)1535     virtual StatementInst* visit(AddMetaDeclareInst* inst)
1536     {
1537         return new AddMetaDeclareInst(inst->fZone, inst->fKey, inst->fValue);
1538     }
visit(OpenboxInst * inst)1539     virtual StatementInst* visit(OpenboxInst* inst) { return new OpenboxInst(inst->fName, inst->fOrient); }
visit(CloseboxInst * inst)1540     virtual StatementInst* visit(CloseboxInst* inst) { return new CloseboxInst(); }
visit(AddButtonInst * inst)1541     virtual StatementInst* visit(AddButtonInst* inst)
1542     {
1543         return new AddButtonInst(inst->fLabel, inst->fZone, inst->fType);
1544     }
visit(AddSliderInst * inst)1545     virtual StatementInst* visit(AddSliderInst* inst)
1546     {
1547         return new AddSliderInst(inst->fLabel, inst->fZone, inst->fInit, inst->fMin, inst->fMax, inst->fStep,
1548                                  inst->fType);
1549     }
visit(AddBargraphInst * inst)1550     virtual StatementInst* visit(AddBargraphInst* inst)
1551     {
1552         return new AddBargraphInst(inst->fLabel, inst->fZone, inst->fMin, inst->fMax, inst->fType);
1553     }
visit(AddSoundfileInst * inst)1554     virtual StatementInst* visit(AddSoundfileInst* inst)
1555     {
1556         return new AddSoundfileInst(inst->fLabel, inst->fURL, inst->fSFZone);
1557     }
visit(LabelInst * inst)1558     virtual StatementInst* visit(LabelInst* inst) { return new LabelInst(inst->fLabel); }
1559 
1560     // Typed
1561     virtual Typed* visit(BasicTyped* typed);  // Moved in instructions.cpp
visit(NamedTyped * typed)1562     virtual Typed* visit(NamedTyped* typed) { return new NamedTyped(typed->fName, typed->fType); }
visit(FunTyped * typed)1563     virtual Typed* visit(FunTyped* typed)
1564     {
1565         list<NamedTyped*> cloned;
1566         for (const auto& it : typed->fArgsTypes) {
1567             cloned.push_back(static_cast<NamedTyped*>(it->clone(this)));
1568         }
1569         return new FunTyped(cloned, static_cast<BasicTyped*>(typed->fResult->clone(this)), typed->fAttribute);
1570     }
visit(ArrayTyped * typed)1571     virtual Typed* visit(ArrayTyped* typed)
1572     {
1573         return new ArrayTyped(typed->fType->clone(this), typed->fSize, typed->fIsPtr);
1574     }
visit(StructTyped * typed)1575     virtual Typed* visit(StructTyped* typed)
1576     {
1577         vector<NamedTyped*> cloned;
1578         for (const auto& it : typed->fFields) {
1579             cloned.push_back(static_cast<NamedTyped*>(it->clone(this)));
1580         }
1581         return new StructTyped(typed->fName, cloned);
1582     }
1583 
visit(VectorTyped * typed)1584     virtual Typed* visit(VectorTyped* typed)
1585     {
1586         return new VectorTyped(static_cast<BasicTyped*>(typed->fType->clone(this)), typed->fSize);
1587     }
1588 };
1589 
1590 // =======================
1591 // Basic dispatch visitor
1592 // =======================
1593 
1594 struct DispatchVisitor : public InstVisitor {
1595     using InstVisitor::visit;
1596 
visitDispatchVisitor1597     virtual void visit(DeclareVarInst* inst)
1598     {
1599         inst->fAddress->accept(this);
1600         // No visitor on types
1601         if (inst->fValue) {
1602             inst->fValue->accept(this);
1603         }
1604     }
1605 
visitDispatchVisitor1606     virtual void visit(DeclareFunInst* inst)
1607     {
1608         if (inst->fCode) {
1609             inst->fCode->accept(this);
1610         }
1611     }
1612 
visitDispatchVisitor1613     virtual void visit(LoadVarInst* inst) { inst->fAddress->accept(this); }
visitDispatchVisitor1614     virtual void visit(LoadVarAddressInst* inst) { inst->fAddress->accept(this); }
visitDispatchVisitor1615     virtual void visit(TeeVarInst* inst)
1616     {
1617         inst->fAddress->accept(this);
1618         inst->fValue->accept(this);
1619     }
visitDispatchVisitor1620     virtual void visit(StoreVarInst* inst)
1621     {
1622         inst->fAddress->accept(this);
1623         inst->fValue->accept(this);
1624     }
1625 
visitDispatchVisitor1626     virtual void visit(ShiftArrayVarInst* inst) { inst->fAddress->accept(this); }
1627 
visitDispatchVisitor1628     virtual void visit(IndexedAddress* address)
1629     {
1630         address->fAddress->accept(this);
1631         address->fIndex->accept(this);
1632     }
1633 
visitDispatchVisitor1634     virtual void visit(BinopInst* inst)
1635     {
1636         inst->fInst1->accept(this);
1637         inst->fInst2->accept(this);
1638     }
1639 
visitDispatchVisitor1640     virtual void visit(CastInst* inst) { inst->fInst->accept(this); }
1641 
visitDispatchVisitor1642     virtual void visit(BitcastInst* inst) { inst->fInst->accept(this); }
1643 
visitDispatchVisitor1644     virtual void visit(FunCallInst* inst)
1645     {
1646         for (const auto& it : inst->fArgs) {
1647             it->accept(this);
1648         }
1649     }
1650 
visitDispatchVisitor1651     virtual void visit(RetInst* inst)
1652     {
1653         if (inst->fResult) {
1654             inst->fResult->accept(this);
1655         }
1656     }
1657 
visitDispatchVisitor1658     virtual void visit(DropInst* inst)
1659     {
1660         if (inst->fResult) {
1661             inst->fResult->accept(this);
1662         }
1663     }
1664 
visitDispatchVisitor1665     virtual void visit(Select2Inst* inst)
1666     {
1667         inst->fCond->accept(this);
1668         inst->fThen->accept(this);
1669         inst->fElse->accept(this);
1670     }
1671 
visitDispatchVisitor1672     virtual void visit(ControlInst* inst)
1673     {
1674         inst->fCond->accept(this);
1675         inst->fStatement->accept(this);
1676     }
1677 
visitDispatchVisitor1678     virtual void visit(IfInst* inst)
1679     {
1680         inst->fCond->accept(this);
1681         inst->fThen->accept(this);
1682         inst->fElse->accept(this);
1683     }
1684 
visitDispatchVisitor1685     virtual void visit(ForLoopInst* inst)
1686     {
1687         inst->fInit->accept(this);
1688         inst->fEnd->accept(this);
1689         inst->fIncrement->accept(this);
1690         inst->fCode->accept(this);
1691     }
1692 
visitDispatchVisitor1693     virtual void visit(SimpleForLoopInst* inst)
1694     {
1695         inst->fUpperBound->accept(this);
1696         inst->fLowerBound->accept(this);
1697         inst->fCode->accept(this);
1698     }
1699 
visitDispatchVisitor1700     virtual void visit(IteratorForLoopInst* inst)
1701     {
1702         for (const auto& it : inst->fIterators) {
1703             it->accept(this);
1704         }
1705         inst->fCode->accept(this);
1706     }
1707 
visitDispatchVisitor1708     virtual void visit(WhileLoopInst* inst)
1709     {
1710         inst->fCond->accept(this);
1711         inst->fCode->accept(this);
1712     }
1713 
visitDispatchVisitor1714     virtual void visit(SwitchInst* inst)
1715     {
1716         inst->fCond->accept(this);
1717         for (const auto& it : inst->fCode) {
1718             (it.second)->accept(this);
1719         }
1720     }
1721 
visitDispatchVisitor1722     virtual void visit(BlockInst* inst)
1723     {
1724         for (const auto& it : inst->fCode) {
1725             it->accept(this);
1726         }
1727     }
1728 
1729     // Typed
visitDispatchVisitor1730     virtual void visit(FunTyped* typed)
1731     {
1732         typed->fResult->accept(this);
1733         for (const auto& it : typed->fArgsTypes) {
1734             it->accept(this);
1735         }
1736     }
visitDispatchVisitor1737     virtual void visit(ArrayTyped* typed) { typed->fType->accept(this); }
visitDispatchVisitor1738     virtual void visit(StructTyped* typed)
1739     {
1740         for (const auto& it : typed->fFields) {
1741             it->accept(this);
1742         }
1743     }
1744 
visitDispatchVisitor1745     virtual void visit(VectorTyped* typed) { typed->fType->accept(this); }
1746 };
1747 
1748 struct VariableScopeVisitor : public DispatchVisitor {
1749     stack<list<DeclareVarInst*> > fBlockVarTable;
1750 
VariableScopeVisitorVariableScopeVisitor1751     VariableScopeVisitor() {}
1752 
visitVariableScopeVisitor1753     virtual void visit(DeclareVarInst* inst)
1754     {
1755         fBlockVarTable.top().push_back(inst);
1756         DispatchVisitor::visit(inst);
1757     }
1758 
visitVariableScopeVisitor1759     virtual void visit(BlockInst* inst)
1760     {
1761         list<DeclareVarInst*> variable_block;
1762         fBlockVarTable.push(variable_block);
1763         DispatchVisitor::visit(inst);
1764         fBlockVarTable.pop();
1765     }
1766 };
1767 
1768 class ScalVecDispatcherVisitor : public DispatchVisitor {
1769    protected:
1770     InstVisitor* fScalarVisitor;
1771     InstVisitor* fVectorVisitor;
1772 
1773     void Dispatch2Visitor(ValueInst* inst);
1774 
1775    public:
1776     using DispatchVisitor::visit;
1777 
ScalVecDispatcherVisitor(InstVisitor * scal,InstVisitor * vec)1778     ScalVecDispatcherVisitor(InstVisitor* scal, InstVisitor* vec) : fScalarVisitor(scal), fVectorVisitor(vec) {}
1779 
~ScalVecDispatcherVisitor()1780     ~ScalVecDispatcherVisitor()
1781     {
1782         delete fScalarVisitor;
1783         delete fVectorVisitor;
1784     }
1785 
visit(LoadVarInst * inst)1786     virtual void visit(LoadVarInst* inst) { Dispatch2Visitor(inst); }
1787 
visit(LoadVarAddressInst * inst)1788     virtual void visit(LoadVarAddressInst* inst) { Dispatch2Visitor(inst); }
1789 
visit(TeeVarInst * inst)1790     virtual void visit(TeeVarInst* inst) { Dispatch2Visitor(inst); }
1791 
visit(StoreVarInst * inst)1792     virtual void visit(StoreVarInst* inst)
1793     {
1794         /*
1795         if (inst->fValue->fSize == 1) {
1796             fScalarVisitor->visit(inst);
1797         } else {
1798             fVectorVisitor->visit(inst);
1799         }
1800         */
1801 
1802         fScalarVisitor->visit(inst);
1803     }
1804 
visit(ShiftArrayVarInst * inst)1805     virtual void visit(ShiftArrayVarInst* inst) { fScalarVisitor->visit(inst); }
1806 
visit(FloatNumInst * inst)1807     virtual void visit(FloatNumInst* inst) { Dispatch2Visitor(inst); }
1808 
visit(FloatArrayNumInst * inst)1809     virtual void visit(FloatArrayNumInst* inst) { Dispatch2Visitor(inst); }
1810 
visit(Int32NumInst * inst)1811     virtual void visit(Int32NumInst* inst) { Dispatch2Visitor(inst); }
1812 
visit(Int64NumInst * inst)1813     virtual void visit(Int64NumInst* inst) { Dispatch2Visitor(inst); }
1814 
visit(BoolNumInst * inst)1815     virtual void visit(BoolNumInst* inst) { Dispatch2Visitor(inst); }
1816 
visit(DoubleNumInst * inst)1817     virtual void visit(DoubleNumInst* inst) { Dispatch2Visitor(inst); }
1818 
visit(DoubleArrayNumInst * inst)1819     virtual void visit(DoubleArrayNumInst* inst) { Dispatch2Visitor(inst); }
1820 
visit(FixedPointNumInst * inst)1821     virtual void visit(FixedPointNumInst* inst) { Dispatch2Visitor(inst); }
1822 
visit(FixedPointArrayNumInst * inst)1823     virtual void visit(FixedPointArrayNumInst* inst) { Dispatch2Visitor(inst); }
1824 
visit(BinopInst * inst)1825     virtual void visit(BinopInst* inst) { Dispatch2Visitor(inst); }
1826 
visit(CastInst * inst)1827     virtual void visit(CastInst* inst) { Dispatch2Visitor(inst); }
1828 
visit(BitcastInst * inst)1829     virtual void visit(BitcastInst* inst) { Dispatch2Visitor(inst); }
1830 
visit(FunCallInst * inst)1831     virtual void visit(FunCallInst* inst) { Dispatch2Visitor(inst); }
1832 
visit(Select2Inst * inst)1833     virtual void visit(Select2Inst* inst) { Dispatch2Visitor(inst); }
1834 
1835 };
1836 
1837 // ===================
1838 // Combining visitors
1839 // ===================
1840 
1841 class CombinerVisitor : public DispatchVisitor {
1842    protected:
1843     InstVisitor* fVisitor1;
1844     InstVisitor* fVisitor2;
1845     InstVisitor* fCurVisitor;
1846 
1847    public:
CombinerVisitor(InstVisitor * v1,InstVisitor * v2)1848     CombinerVisitor(InstVisitor* v1, InstVisitor* v2) : fVisitor1(v1), fVisitor2(v2) { fCurVisitor = v1; }
1849 
~CombinerVisitor()1850     virtual ~CombinerVisitor() {}
1851 };
1852 
1853 // ======================
1854 // Instruction generator
1855 // ======================
1856 
1857 struct InstBuilder {
1858     // User interface
genAddMetaDeclareInstInstBuilder1859     static AddMetaDeclareInst* genAddMetaDeclareInst(const string& zone, const string& key, const string& value)
1860     {
1861         return new AddMetaDeclareInst(zone, key, value);
1862     }
1863 
genOpenboxInstInstBuilder1864     static OpenboxInst* genOpenboxInst(const string& name, OpenboxInst::BoxType orient)
1865     {
1866         faustassert(orient >= OpenboxInst::kVerticalBox && orient <= OpenboxInst::kTabBox);
1867         return new OpenboxInst(name, orient);
1868     }
1869 
genCloseboxInstInstBuilder1870     static CloseboxInst* genCloseboxInst() { return new CloseboxInst(); }
1871 
genAddButtonInstInstBuilder1872     static AddButtonInst* genAddButtonInst(const string& label, const string& zone)
1873     {
1874         return new AddButtonInst(label, zone, AddButtonInst::kDefaultButton);
1875     }
1876 
genAddCheckbuttonInstInstBuilder1877     static AddButtonInst* genAddCheckbuttonInst(const string& label, const string& zone)
1878     {
1879         return new AddButtonInst(label, zone, AddButtonInst::kCheckButton);
1880     }
1881 
genAddHorizontalSliderInstInstBuilder1882     static AddSliderInst* genAddHorizontalSliderInst(const string& label, const string& zone, double init, double min,
1883                                                      double max, double step)
1884     {
1885         stringstream error;
1886         if (min > max) {
1887             error << "ERROR : horizontal slider \'"<< label << "\' min = " << min << " should be less than max = " << max << "\n";
1888             throw faustexception(error.str());
1889         } else if (init < min || init > max) {
1890             error << "ERROR : horizontal slider \'"<< label << "\' init = " << init << " outside of [" << min << " " << max << "] range\n";
1891             throw faustexception(error.str());
1892         }
1893         return new AddSliderInst(label, zone, init, min, max, step, AddSliderInst::kHorizontal);
1894     }
1895 
genAddVerticalSliderInstInstBuilder1896     static AddSliderInst* genAddVerticalSliderInst(const string& label, const string& zone, double init, double min,
1897                                                    double max, double step)
1898     {
1899         stringstream error;
1900         if (min > max) {
1901             error << "ERROR : vertical slider \'"<< label << "\' min = " << min << " should be less than max = " << max << "\n";
1902             throw faustexception(error.str());
1903         } else if (init < min || init > max) {
1904             error << "ERROR : vertical slider \'" << label << "\' init = " << init << " outside of [" << min << " " << max << "] range\n";
1905             throw faustexception(error.str());
1906         }
1907         return new AddSliderInst(label, zone, init, min, max, step, AddSliderInst::kVertical);
1908     }
1909 
genAddNumEntryInstInstBuilder1910     static AddSliderInst* genAddNumEntryInst(const string& label, const string& zone, double init, double min,
1911                                              double max, double step)
1912     {
1913         stringstream error;
1914         if (min > max) {
1915             error << "ERROR : num entry \'"<< label << "\' min = " << min << " should be less than max = " << max << "\n";
1916             throw faustexception(error.str());
1917         } else if (init < min || init > max) {
1918             error << "ERROR : num entry \'" << label << "\' init = " << init << " outside of [" << min << " " << max << "] range\n";
1919             throw faustexception(error.str());
1920         }
1921         return new AddSliderInst(label, zone, init, min, max, step, AddSliderInst::kNumEntry);
1922     }
1923 
genAddHorizontalBargraphInstInstBuilder1924     static AddBargraphInst* genAddHorizontalBargraphInst(const string& label, const string& zone, double min,
1925                                                          double max)
1926     {
1927         return new AddBargraphInst(label, zone, min, max, AddBargraphInst::kHorizontal);
1928     }
1929 
genAddVerticalBargraphInstInstBuilder1930     static AddBargraphInst* genAddVerticalBargraphInst(const string& label, const string& zone, double min, double max)
1931     {
1932         return new AddBargraphInst(label, zone, min, max, AddBargraphInst::kVertical);
1933     }
1934 
genAddSoundfileInstInstBuilder1935     static AddSoundfileInst* genAddSoundfileInst(const string& label, const string& url, const string& sf_zone)
1936     {
1937         return new AddSoundfileInst(label, url, sf_zone);
1938     }
1939 
genLabelInstInstBuilder1940     static LabelInst* genLabelInst(const string& label) { return new LabelInst(label); }
1941 
1942     // Null instruction
genNullValueInstInstBuilder1943     static NullValueInst*     genNullValueInst() { return new NullValueInst(); }
genNullStatementInstInstBuilder1944     static NullStatementInst* genNullStatementInst() { return new NullStatementInst(); }
1945 
1946     // Declarations
genDeclareVarInstInstBuilder1947     static DeclareVarInst* genDeclareVarInst(Address* address, Typed* typed, ValueInst* value = nullptr)
1948     {
1949         return new DeclareVarInst(address, typed, value);
1950     }
1951 
genDeclareFunInstInstBuilder1952     static DeclareFunInst* genDeclareFunInst(const string& name, FunTyped* typed, BlockInst* code)
1953     {
1954         return new DeclareFunInst(name, typed, code);
1955     }
genDeclareFunInstInstBuilder1956     static DeclareFunInst* genDeclareFunInst(const string& name, FunTyped* typed)
1957     {
1958         return new DeclareFunInst(name, typed);
1959     }
1960 
genDeclareStructTypeInstInstBuilder1961     static DeclareStructTypeInst* genDeclareStructTypeInst(StructTyped* type)
1962     {
1963         return new DeclareStructTypeInst(type);
1964     }
1965 
genDeclareBufferIteratorsInstBuilder1966     static DeclareBufferIterators* genDeclareBufferIterators(const std::string& name1, const std::string& name2, int num_channels, bool mut)
1967     {
1968         return new DeclareBufferIterators(name1, name2, num_channels, mut);
1969     }
1970 
1971     // Memory
genLoadVarInstInstBuilder1972     static LoadVarInst*        genLoadVarInst(Address* address) { return new LoadVarInst(address); }
genLoadVarAddressInstInstBuilder1973     static LoadVarAddressInst* genLoadVarAddressInst(Address* address) { return new LoadVarAddressInst(address); }
genTeeVarInstBuilder1974     static TeeVarInst*         genTeeVar(const string& vname, ValueInst* value)
1975     {
1976         return new TeeVarInst(InstBuilder::genNamedAddress(vname, Address::kStack), value);
1977     }
genStoreVarInstInstBuilder1978     static StoreVarInst* genStoreVarInst(Address* address, ValueInst* value)
1979     {
1980         return new StoreVarInst(address, value);
1981     }
genShiftArrayVarInstInstBuilder1982     static ShiftArrayVarInst* genShiftArrayVarInst(Address* address, int delay)
1983     {
1984         return new ShiftArrayVarInst(address, delay);
1985     }
1986 
1987     // Numbers
genFloatNumInstInstBuilder1988     static FloatNumInst*       genFloatNumInst(float num) { return new FloatNumInst(num); }
genFloatArrayNumInstInstBuilder1989     static FloatArrayNumInst*  genFloatArrayNumInst(int size) { return new FloatArrayNumInst(size); }
genDoubleNumInstInstBuilder1990     static DoubleNumInst*      genDoubleNumInst(double num) { return new DoubleNumInst(num); }
genDoubleArrayNumInstInstBuilder1991     static DoubleArrayNumInst* genDoubleArrayNumInst(int size) { return new DoubleArrayNumInst(size); }
genFixedPointNumInstInstBuilder1992     static FixedPointNumInst*       genFixedPointNumInst(double num) { return new FixedPointNumInst(num); }
genFixedPointArrayNumInstInstBuilder1993     static FixedPointArrayNumInst*  genFixedPointArrayNumInst(int size) { return new FixedPointArrayNumInst(size); }
genQuadNumInstInstBuilder1994     static DoubleNumInst*      genQuadNumInst(double num) { return new DoubleNumInst(num); }  // Use DoubleNumInst
1995 
1996     static ValueInst* genTypedZero(Typed::VarType type);
1997 
genRealNumInstInstBuilder1998     static ValueInst* genRealNumInst(Typed::VarType ctype, double num)
1999     {
2000         if (ctype == Typed::kFloat) {
2001             return new FloatNumInst(float(num));
2002         } else if (ctype == Typed::kFloatMacro) {
2003             return genCastInst(new DoubleNumInst(num), genBasicTyped(Typed::kFloatMacro));
2004         } else if (ctype == Typed::kDouble) {
2005             return new DoubleNumInst(num);
2006         } else if (ctype == Typed::kQuad) {
2007             return new DoubleNumInst(num);
2008         } else if (ctype == Typed::kFixedPoint) {
2009             return new FixedPointNumInst(num);
2010         } else {
2011             faustassert(false);
2012         }
2013         return nullptr;
2014     }
2015 
genArrayNumInstInstBuilder2016     static ValueInst* genArrayNumInst(Typed::VarType ctype, int size)
2017     {
2018         if (ctype == Typed::kInt32) {
2019             return new Int32ArrayNumInst(size);
2020         } else if (ctype == Typed::kFloat) {
2021             return new FloatArrayNumInst(size);
2022         } else if (ctype == Typed::kDouble) {
2023             return new DoubleArrayNumInst(size);
2024         } else if (ctype == Typed::kFixedPoint) {
2025             return new FixedPointArrayNumInst(size);
2026         } else {
2027             faustassert(false);
2028         }
2029         return nullptr;
2030     }
2031 
genInt32NumInstInstBuilder2032     static Int32NumInst* genInt32NumInst(int num) { return new Int32NumInst(num); }
genInt64NumInstInstBuilder2033     static Int64NumInst* genInt64NumInst(int64_t num) { return new Int64NumInst(num); }
genBoolNumInstInstBuilder2034     static BoolNumInst*  genBoolNumInst(bool num) { return new BoolNumInst(num); }
2035 
2036     // Numerical computation
genBinopInstInstBuilder2037     static BinopInst* genBinopInst(int opcode, ValueInst* inst1, ValueInst* inst2)
2038     {
2039         return new BinopInst(opcode, inst1, inst2);
2040     }
2041 
genCastInstInstBuilder2042     static ValueInst* genCastInst(ValueInst* inst, Typed* typed_ext)
2043     {
2044         Int32NumInst*  int_num    = dynamic_cast<Int32NumInst*>(inst);
2045         FloatNumInst*  float_num  = dynamic_cast<FloatNumInst*>(inst);
2046         DoubleNumInst* double_num = dynamic_cast<DoubleNumInst*>(inst);
2047         BasicTyped*    typed      = dynamic_cast<BasicTyped*>(typed_ext);
2048         CastInst*      cast       = dynamic_cast<CastInst*>(inst);
2049 
2050         if (!typed) {
2051             // Default case
2052             return new CastInst(inst, typed_ext);
2053         } else if (cast && (cast->fType == typed_ext)) {
2054             // Casting an already casted value with the same type
2055             return inst;
2056         } else if (typed->getType() == Typed::kFloat) {
2057             if (int_num) {
2058                 // Simple float cast of integer
2059                 return genFloatNumInst(float(int_num->fNum));
2060             } else if (float_num) {
2061                 // No cast needed
2062                 return inst;
2063             } else if (double_num) {
2064                 return genFloatNumInst(float(double_num->fNum));
2065             } else {
2066                 // Default case
2067                 return new CastInst(inst, typed);
2068             }
2069         } else if (typed->getType() == Typed::kDouble || typed->getType() == Typed::kQuad) {
2070             if (int_num) {
2071                 // Simple double cast of integer
2072                 return genDoubleNumInst(double(int_num->fNum));
2073             } else if (float_num) {
2074                 return genDoubleNumInst(double(float_num->fNum));
2075             } else if (double_num) {
2076                 // No cast needed
2077                 return inst;
2078             } else {
2079                 // Default case
2080                 return new CastInst(inst, typed);
2081             }
2082         } else if (typed->getType() == Typed::kInt32) {
2083             if (int_num) {
2084                 // No cast needed
2085                 return inst;
2086             } else if (float_num) {
2087                 // Simple int cast of float
2088                 return genInt32NumInst(int(float_num->fNum));
2089             } else if (double_num) {
2090                 // Simple int cast of double
2091                 return genInt32NumInst(int(double_num->fNum));
2092             } else {
2093                 // Default case
2094                 return new CastInst(inst, typed);
2095             }
2096         } else {
2097             // Default case
2098             return new CastInst(inst, typed);
2099         }
2100     }
2101 
genBitcastInstInstBuilder2102     static ValueInst* genBitcastInst(ValueInst* inst, Typed* typed) { return new BitcastInst(inst, typed); }
2103     static ValueInst* genCastFloatInst(ValueInst* inst);
2104     static ValueInst* genCastFloatMacroInst(ValueInst* inst);
2105     static ValueInst* genCastInt32Inst(ValueInst* inst);
2106 
2107     // Control flow
genRetInstInstBuilder2108     static RetInst*  genRetInst(ValueInst* result = nullptr) { return new RetInst(result); }
genDropInstInstBuilder2109     static DropInst* genDropInst(ValueInst* result = nullptr) { return new DropInst(result); }
2110 
2111     // Conditional
genSelect2InstInstBuilder2112     static Select2Inst* genSelect2Inst(ValueInst* cond_inst, ValueInst* then_inst, ValueInst* else_inst)
2113     {
2114         return new Select2Inst(cond_inst, then_inst, else_inst);
2115     }
2116 
genControlInstInstBuilder2117     static StatementInst* genControlInst(ValueInst* cond_inst, StatementInst* exp_inst)
2118     {
2119         // If called with a NullValueInst, then the exp_inst is going to be always computed
2120         return (dynamic_cast<NullValueInst*>(cond_inst)) ? exp_inst : new ControlInst(cond_inst, exp_inst);
2121     }
2122 
genIfInstInstBuilder2123     static IfInst* genIfInst(ValueInst* cond_inst, BlockInst* then_inst, BlockInst* else_inst)
2124     {
2125         return new IfInst(cond_inst, then_inst, else_inst);
2126     }
genIfInstInstBuilder2127     static IfInst* genIfInst(ValueInst* cond_inst, BlockInst* then_inst) { return new IfInst(cond_inst, then_inst); }
genSwitchInstInstBuilder2128     static SwitchInst* genSwitchInst(ValueInst* cond) { return new SwitchInst(cond); }
2129 
2130     // Function management
genFunCallInstInstBuilder2131     static FunCallInst* genFunCallInst(const string& name, const list<ValueInst*>& args)
2132     {
2133         return new FunCallInst(name, args, false);
2134     }
genFunCallInstInstBuilder2135     static FunCallInst* genFunCallInst(const string& name, const list<ValueInst*>& args, bool method)
2136     {
2137         return new FunCallInst(name, args, method);
2138     }
genVoidFunCallInstInstBuilder2139     static DropInst* genVoidFunCallInst(const string& name, const list<ValueInst*>& args)
2140     {
2141         return new DropInst(new FunCallInst(name, args, false));
2142     }
genVoidFunCallInstInstBuilder2143     static DropInst* genVoidFunCallInst(const string& name, const list<ValueInst*>& args, bool method)
2144     {
2145         return new DropInst(new FunCallInst(name, args, method));
2146     }
2147 
2148     // Loop
genForLoopInstInstBuilder2149     static ForLoopInst* genForLoopInst(StatementInst* init, ValueInst* end, StatementInst* increment,
2150                                        BlockInst* code = new BlockInst(), bool is_recursive = false)
2151     {
2152         faustassert(dynamic_cast<DeclareVarInst*>(init) || dynamic_cast<StoreVarInst*>(init));
2153         return new ForLoopInst(init, end, increment, code, is_recursive);
2154     }
2155 
2156     // TODO: add access to the loop variable, generate ascending/descending loops...
genForLoopInstInstBuilder2157     static ForLoopInst* genForLoopInst(const string& index, int init, int size, int step = 1)
2158     {
2159         DeclareVarInst* dec = genDecLoopVar(index, genInt32Typed(), genInt32NumInst(init));
2160         ValueInst*      end = genLessThan(dec->load(), genInt32NumInst(size));
2161         StoreVarInst*   inc = dec->store(genAdd(dec->load(), step));
2162         return genForLoopInst(dec, end, inc);
2163     }
2164 
2165     // Used for Rust backend
genSimpleForLoopInstInstBuilder2166     static SimpleForLoopInst* genSimpleForLoopInst(const string& name, ValueInst* upperBound,
2167                                                    ValueInst* lowerBound = new Int32NumInst(0), bool reverse = false,
2168                                                    BlockInst* code = new BlockInst())
2169     {
2170         faustassert(dynamic_cast<Int32NumInst*>(upperBound) || dynamic_cast<LoadVarInst*>(upperBound));
2171         faustassert(dynamic_cast<Int32NumInst*>(lowerBound) || dynamic_cast<LoadVarInst*>(lowerBound));
2172         return new SimpleForLoopInst(name, upperBound, lowerBound, reverse, code);
2173     }
genIteratorForLoopInstInstBuilder2174     static IteratorForLoopInst* genIteratorForLoopInst(const std::vector<NamedAddress*>& iterators, bool reverse = false,
2175                                                        BlockInst* code = new BlockInst())
2176     {
2177         return new IteratorForLoopInst(iterators, reverse, code);
2178     }
2179 
genWhileLoopInstInstBuilder2180     static WhileLoopInst* genWhileLoopInst(ValueInst* cond, BlockInst* code) { return new WhileLoopInst(cond, code); }
2181 
genBlockInstInstBuilder2182     static BlockInst* genBlockInst(const list<StatementInst*>& code) { return new BlockInst(code); }
genBlockInstInstBuilder2183     static BlockInst* genBlockInst() { return new BlockInst(); }
2184 
2185     // Types
2186     static BasicTyped* genBasicTyped(Typed::VarType type);  // moved in instructions.cpp
2187 
genInt32TypedInstBuilder2188     static BasicTyped* genInt32Typed() { return genBasicTyped(Typed::kInt32); }
genInt64TypedInstBuilder2189     static BasicTyped* genInt64Typed() { return genBasicTyped(Typed::kInt64); }
genVoidTypedInstBuilder2190     static BasicTyped* genVoidTyped() { return genBasicTyped(Typed::kVoid); }
genFloatTypedInstBuilder2191     static BasicTyped* genFloatTyped() { return genBasicTyped(Typed::kFloat); }
genDoubleTypedInstBuilder2192     static BasicTyped* genDoubleTyped() { return genBasicTyped(Typed::kDouble); }
genFloatMacroTypedInstBuilder2193     static BasicTyped* genFloatMacroTyped() { return genBasicTyped(Typed::kFloatMacro); }
2194 
2195     static NamedTyped* genNamedTyped(const string& name, Typed* type);
2196     static NamedTyped* genNamedTyped(const string& name, Typed::VarType type);
2197 
genFunTypedInstBuilder2198     static FunTyped* genFunTyped(const list<NamedTyped*>& args, BasicTyped* result,
2199                                  FunTyped::FunAttribute attribute = FunTyped::kDefault)
2200     {
2201         return new FunTyped(args, result, attribute);
2202     }
genVectorTypedInstBuilder2203     static VectorTyped* genVectorTyped(BasicTyped* type, int size) { return new VectorTyped(type, size); }
genArrayTypedInstBuilder2204     static ArrayTyped*  genArrayTyped(Typed* type, int size, bool is_ptr = false)
2205     {
2206         return new ArrayTyped(type, size, is_ptr);
2207     }
genStructTypedInstBuilder2208     static StructTyped* genStructTyped(const string& name, const vector<NamedTyped*>& fields)
2209     {
2210         return new StructTyped(name, fields);
2211     }
2212 
2213     // Addresses
genNamedAddressInstBuilder2214     static NamedAddress* genNamedAddress(const string& name, Address::AccessType access)
2215     {
2216         return new NamedAddress(name, access);
2217     }
genIndexedAddressInstBuilder2218     static IndexedAddress* genIndexedAddress(Address* address, ValueInst* index)
2219     {
2220         return new IndexedAddress(address, index);
2221     }
2222 
2223     // Helper build methods
genDecArrayVarInstBuilder2224     static DeclareVarInst* genDecArrayVar(const string& vname, Address::AccessType var_access, Typed* type, int size)
2225     {
2226         return genDeclareVarInst(genNamedAddress(vname, var_access), genArrayTyped(type, size));
2227     }
2228 
genLoadArrayVarInstBuilder2229     static LoadVarInst* genLoadArrayVar(const string& vname, Address::AccessType var_access, ValueInst* index)
2230     {
2231         return genLoadVarInst(genIndexedAddress(genNamedAddress(vname, var_access), index));
2232     }
2233     // Actually same as genLoadArrayVar
genLoadStructPtrVarInstBuilder2234     static LoadVarInst* genLoadStructPtrVar(const string& vname, Address::AccessType var_access, ValueInst* index)
2235     {
2236         return genLoadArrayVar(vname, var_access, index);
2237     }
2238 
genStoreArrayVarInstBuilder2239     static StoreVarInst* genStoreArrayVar(const string& vname, Address::AccessType var_access, ValueInst* index,
2240                                           ValueInst* exp)
2241     {
2242         return genStoreVarInst(genIndexedAddress(genNamedAddress(vname, var_access), index), exp);
2243     }
2244 
2245     // Struct variable
genDecStructVarInstBuilder2246     static DeclareVarInst* genDecStructVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2247     {
2248         return genDeclareVarInst(genNamedAddress(vname, Address::kStruct), type, exp);
2249     }
2250 
genDecVolatileStructVarInstBuilder2251     static DeclareVarInst* genDecVolatileStructVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2252     {
2253         return genDeclareVarInst(genNamedAddress(vname, (Address::AccessType)(Address::kStruct | Address::kVolatile)),
2254                                  type, exp);
2255     }
2256 
genDecArrayStructVarInstBuilder2257     static DeclareVarInst* genDecArrayStructVar(const string& vname, Typed* type, int size)
2258     {
2259         return genDecArrayVar(vname, Address::kStruct, type, size);
2260     }
2261 
genLoadStructVarInstBuilder2262     static LoadVarInst* genLoadStructVar(const string& vname)
2263     {
2264         return genLoadVarInst(genNamedAddress(vname, Address::kStruct));
2265     }
2266 
genLoadMutRefStructVarInstBuilder2267     static LoadVarInst* genLoadMutRefStructVar(const string& vname)
2268     {
2269         return genLoadVarInst(
2270             genNamedAddress(vname, (Address::AccessType)(Address::kStruct | Address::kReference | Address::kMutable)));
2271     }
2272 
genVolatileLoadStructVarInstBuilder2273     static LoadVarInst* genVolatileLoadStructVar(const string& vname)
2274     {
2275         return genLoadVarInst(genNamedAddress(vname, (Address::AccessType)(Address::kStruct | Address::kVolatile)));
2276     }
2277 
2278     template <typename Iterator>
genLoadArrayStructVarInstBuilder2279     static LoadVarInst* genLoadArrayStructVar(const string& vname, Iterator indexBegin, Iterator indexEnd)
2280     {
2281         typedef reverse_iterator<Iterator> Rit;
2282         Rit                                rbegin(indexEnd);
2283         Rit                                rend(indexBegin);
2284 
2285         Address* address = genNamedAddress(vname, Address::kStruct);
2286         for (Rit it = rbegin; it != rend; ++it) {
2287             address = genIndexedAddress(address, *it);
2288         }
2289 
2290         return genLoadVarInst(address);
2291     }
2292 
genLoadArrayStructVarInstBuilder2293     static LoadVarInst* genLoadArrayStructVar(const string& vname, ValueInst* index)
2294     {
2295         vector<ValueInst*> indices;
2296         indices.push_back(index);
2297         return genLoadArrayStructVar(vname, indices.begin(), indices.end());
2298     }
2299 
genLoadArrayStructVarInstBuilder2300     static LoadVarInst* genLoadArrayStructVar(const string& vname)
2301     {
2302         return genLoadVarInst(genNamedAddress(vname, Address::kStruct));
2303     }
2304 
genLoadArrayStructVarAddressInstBuilder2305     static LoadVarAddressInst* genLoadArrayStructVarAddress(const string& vname, ValueInst* index)
2306     {
2307         return genLoadVarAddressInst(genIndexedAddress(genNamedAddress(vname, Address::kStruct), index));
2308     }
2309 
genStoreStructVarInstBuilder2310     static StoreVarInst* genStoreStructVar(const string& vname, ValueInst* exp)
2311     {
2312         return genStoreVarInst(genNamedAddress(vname, Address::kStruct), exp);
2313     }
2314 
genVolatileStoreStructVarInstBuilder2315     static StoreVarInst* genVolatileStoreStructVar(const string& vname, ValueInst* exp)
2316     {
2317         return genStoreVarInst(genNamedAddress(vname, (Address::AccessType)(Address::kStruct | Address::kVolatile)),
2318                                exp);
2319     }
2320 
2321     template <typename Iterator>
genStoreArrayStructVarInstBuilder2322     static StoreVarInst* genStoreArrayStructVar(const string& vname, ValueInst* exp, Iterator indexBegin,
2323                                                 Iterator indexEnd)
2324     {
2325         typedef reverse_iterator<Iterator> Rit;
2326         Rit                                rbegin(indexEnd);
2327         Rit                                rend(indexBegin);
2328 
2329         Address* address = genNamedAddress(vname, Address::kStruct);
2330         for (Rit it = rbegin; it != rend; ++it) {
2331             address = genIndexedAddress(address, *it);
2332         }
2333 
2334         return genStoreVarInst(address, exp);
2335     }
2336 
genStoreArrayStructVarInstBuilder2337     static StoreVarInst* genStoreArrayStructVar(const string& vname, ValueInst* index, ValueInst* exp)
2338     {
2339         vector<ValueInst*> indices;
2340         indices.push_back(index);
2341         return genStoreArrayStructVar(vname, exp, indices.begin(), indices.end());
2342     }
2343 
genStoreArrayStructVarInstBuilder2344     static StoreVarInst* genStoreArrayStructVar(const string& vname, ValueInst* exp)
2345     {
2346         return genStoreVarInst(genNamedAddress(vname, Address::kStruct), exp);
2347     }
2348 
2349     // Static struct variable
genDecStaticStructVarInstBuilder2350     static DeclareVarInst* genDecStaticStructVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2351     {
2352         return genDeclareVarInst(genNamedAddress(vname, Address::kStaticStruct), type, exp);
2353     }
2354 
genDecConstStaticStructVarInstBuilder2355     static DeclareVarInst* genDecConstStaticStructVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2356     {
2357         return genDeclareVarInst(
2358             genNamedAddress(vname, (Address::AccessType)(Address::kStaticStruct | Address::kConst)), type, exp);
2359     }
2360 
genLoadStaticStructVarInstBuilder2361     static LoadVarInst* genLoadStaticStructVar(const string& vname)
2362     {
2363         return genLoadVarInst(genNamedAddress(vname, Address::kStaticStruct));
2364     }
2365 
genLoadStaticMutRefStructVarInstBuilder2366     static LoadVarInst* genLoadStaticMutRefStructVar(const string& vname)
2367     {
2368         return genLoadVarInst(genNamedAddress(
2369             vname, (Address::AccessType)(Address::kStaticStruct | Address::kReference | Address::kMutable)));
2370     }
2371 
genStoreStaticStructVarInstBuilder2372     static StoreVarInst* genStoreStaticStructVar(const string& vname, ValueInst* exp)
2373     {
2374         return genStoreVarInst(genNamedAddress(vname, Address::kStaticStruct), exp);
2375     }
2376 
2377     template <typename Iterator>
genLoadArrayStaticStructVarInstBuilder2378     static LoadVarInst* genLoadArrayStaticStructVar(const string& vname, Iterator indexBegin, Iterator indexEnd)
2379     {
2380         typedef reverse_iterator<Iterator> Rit;
2381         Rit                                rbegin(indexEnd);
2382         Rit                                rend(indexBegin);
2383 
2384         Address* address = genNamedAddress(vname, Address::kStaticStruct);
2385         for (Rit it = rbegin; it != rend; ++it) {
2386             address = genIndexedAddress(address, *it);
2387         }
2388 
2389         return genLoadVarInst(address);
2390     }
2391 
genLoadArrayStaticStructVarInstBuilder2392     static LoadVarInst* genLoadArrayStaticStructVar(const string& vname, ValueInst* index)
2393     {
2394         vector<ValueInst*> indices;
2395         indices.push_back(index);
2396         return genLoadArrayStaticStructVar(vname, indices.begin(), indices.end());
2397     }
2398 
2399     template <typename Iterator>
genStoreArrayStaticStructVarInstBuilder2400     static StoreVarInst* genStoreArrayStaticStructVar(const string& vname, ValueInst* exp, Iterator indexBegin,
2401                                                       Iterator indexEnd)
2402     {
2403         typedef reverse_iterator<Iterator> Rit;
2404         Rit                                rbegin(indexEnd);
2405         Rit                                rend(indexBegin);
2406 
2407         Address* address = genNamedAddress(vname, Address::kStaticStruct);
2408         for (Rit it = rbegin; it != rend; ++it) {
2409             address = genIndexedAddress(address, *it);
2410         }
2411 
2412         return genStoreVarInst(address, exp);
2413     }
2414 
genStoreArrayStaticStructVarInstBuilder2415     static StoreVarInst* genStoreArrayStaticStructVar(const string& vname, ValueInst* index, ValueInst* exp)
2416     {
2417         vector<ValueInst*> indices;
2418         indices.push_back(index);
2419         return genStoreArrayStructVar(vname, exp, indices.begin(), indices.end());
2420     }
2421 
2422     // Stack variable
genDecStackVarInstBuilder2423     static DeclareVarInst* genDecStackVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2424     {
2425         return genDeclareVarInst(genNamedAddress(vname, Address::kStack), type, exp);
2426     }
2427 
genDecArrayStackVarInstBuilder2428     static DeclareVarInst* genDecArrayStackVar(const string& vname, Typed* type, int size)
2429     {
2430         return genDecArrayVar(vname, Address::kStack, type, size);
2431     }
2432 
genLoadStackVarInstBuilder2433     static LoadVarInst* genLoadStackVar(const string& vname)
2434     {
2435         return genLoadVarInst(genNamedAddress(vname, Address::kStack));
2436     }
2437 
genLoadStackVarAddressInstBuilder2438     static LoadVarAddressInst* genLoadStackVarAddress(const string& vname)
2439     {
2440         return genLoadVarAddressInst(genNamedAddress(vname, Address::kStack));
2441     }
2442 
genLoadArrayStackVarInstBuilder2443     static LoadVarInst* genLoadArrayStackVar(const string& vname, ValueInst* index)
2444     {
2445         return genLoadVarInst(genIndexedAddress(genNamedAddress(vname, Address::kStack), index));
2446     }
2447 
genLoadArrayStackVarAddressInstBuilder2448     static LoadVarAddressInst* genLoadArrayStackVarAddress(const string& vname, ValueInst* index)
2449     {
2450         return genLoadVarAddressInst(genIndexedAddress(genNamedAddress(vname, Address::kStack), index));
2451     }
2452 
genStoreStackVarInstBuilder2453     static StoreVarInst* genStoreStackVar(const string& vname, ValueInst* exp)
2454     {
2455         return genStoreVarInst(genNamedAddress(vname, Address::kStack), exp);
2456     }
2457 
genStoreArrayStackVarInstBuilder2458     static StoreVarInst* genStoreArrayStackVar(const string& vname, ValueInst* index, ValueInst* exp)
2459     {
2460         return genStoreVarInst(genIndexedAddress(genNamedAddress(vname, Address::kStack), index), exp);
2461     }
2462 
2463     // Loop variable
genDecLoopVarInstBuilder2464     static DeclareVarInst* genDecLoopVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2465     {
2466         return genDeclareVarInst(genNamedAddress(vname, Address::kLoop), type, exp);
2467     }
2468 
genLoadLoopVarInstBuilder2469     static LoadVarInst* genLoadLoopVar(const string& vname)
2470     {
2471         return genLoadVarInst(genNamedAddress(vname, Address::kLoop));
2472     }
2473 
genStoreLoopVarInstBuilder2474     static StoreVarInst* genStoreLoopVar(const string& vname, ValueInst* exp)
2475     {
2476         return genStoreVarInst(genNamedAddress(vname, Address::kLoop), exp);
2477     }
2478 
2479     // FunArgs variable
genLoadFunArgsVarInstBuilder2480     static LoadVarInst* genLoadFunArgsVar(const string& vname)
2481     {
2482         return genLoadVarInst(genNamedAddress(vname, Address::kFunArgs));
2483     }
2484 
genLoadArrayFunArgsVarInstBuilder2485     static LoadVarInst* genLoadArrayFunArgsVar(const string& vname, ValueInst* index)
2486     {
2487         return genLoadVarInst(genIndexedAddress(genNamedAddress(vname, Address::kFunArgs), index));
2488     }
2489 
genStoreArrayFunArgsVarInstBuilder2490     static StoreVarInst* genStoreArrayFunArgsVar(const string& vname, ValueInst* index, ValueInst* exp)
2491     {
2492         return genStoreVarInst(genIndexedAddress(genNamedAddress(vname, Address::kFunArgs), index), exp);
2493     }
2494 
2495     // Global variable
genDecGlobalVarInstBuilder2496     static DeclareVarInst* genDecGlobalVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2497     {
2498         return genDeclareVarInst(genNamedAddress(vname, Address::kGlobal), type, exp);
2499     }
2500 
genDecConstGlobalVarInstBuilder2501     static DeclareVarInst* genDecConstGlobalVar(const string& vname, Typed* type, ValueInst* exp = nullptr)
2502     {
2503         return genDeclareVarInst(genNamedAddress(vname, (Address::AccessType)(Address::kGlobal | Address::kConst)),
2504                                  type, exp);
2505     }
2506 
genLoadGlobalVarInstBuilder2507     static LoadVarInst* genLoadGlobalVar(const string& vname)
2508     {
2509         return genLoadVarInst(genNamedAddress(vname, Address::kGlobal));
2510     }
2511 
genStoreGlobalVarInstBuilder2512     static StoreVarInst* genStoreGlobalVar(const string& vname, ValueInst* exp)
2513     {
2514         return genStoreVarInst(genNamedAddress(vname, Address::kGlobal), exp);
2515     }
2516 
2517     // Binop operations
genAddInstBuilder2518     static BinopInst* genAdd(ValueInst* a1, ValueInst* a2) { return genBinopInst(kAdd, a1, a2); }
2519 
genAddInstBuilder2520     static BinopInst* genAdd(ValueInst* a1, int a2) { return genBinopInst(kAdd, a1, genInt32NumInst(a2)); }
2521 
genSubInstBuilder2522     static BinopInst* genSub(ValueInst* a1, ValueInst* a2) { return genBinopInst(kSub, a1, a2); }
2523 
genSubInstBuilder2524     static BinopInst* genSub(ValueInst* a1, int a2) { return genBinopInst(kSub, a1, genInt32NumInst(a2)); }
2525 
genMulInstBuilder2526     static BinopInst* genMul(ValueInst* a1, ValueInst* a2) { return genBinopInst(kMul, a1, a2); }
2527 
genDivInstBuilder2528     static BinopInst* genDiv(ValueInst* a1, ValueInst* a2) { return genBinopInst(kDiv, a1, a2); }
2529 
genRemInstBuilder2530     static BinopInst* genRem(ValueInst* a1, ValueInst* a2) { return genBinopInst(kRem, a1, a2); }
2531 
genGreaterThanInstBuilder2532     static BinopInst* genGreaterThan(ValueInst* a1, ValueInst* a2) { return genBinopInst(kGT, a1, a2); }
2533 
genLessThanInstBuilder2534     static BinopInst* genLessThan(ValueInst* a1, ValueInst* a2) { return genBinopInst(kLT, a1, a2); }
2535 
genGreaterEqualInstBuilder2536     static BinopInst* genGreaterEqual(ValueInst* a1, ValueInst* a2) { return genBinopInst(kGE, a1, a2); }
2537 
genLessEqualInstBuilder2538     static BinopInst* genLessEqual(ValueInst* a1, ValueInst* a2) { return genBinopInst(kLE, a1, a2); }
2539 
genEqualInstBuilder2540     static BinopInst* genEqual(ValueInst* a1, ValueInst* a2) { return genBinopInst(kEQ, a1, a2); }
2541 
genNotEqualInstBuilder2542     static BinopInst* genNotEqual(ValueInst* a1, ValueInst* a2) { return genBinopInst(kNE, a1, a2); }
2543 
genAndInstBuilder2544     static BinopInst* genAnd(ValueInst* a1, ValueInst* a2) { return genBinopInst(kAND, a1, a2); }
2545 
genOrInstBuilder2546     static BinopInst* genOr(ValueInst* a1, ValueInst* a2) { return genBinopInst(kOR, a1, a2); }
2547 
genXOrInstBuilder2548     static BinopInst* genXOr(ValueInst* a1, ValueInst* a2) { return genBinopInst(kXOR, a1, a2); }
2549 
2550     // Functions
2551     static DeclareFunInst* genVoidFunction(const string& name, BlockInst* code = new BlockInst());
2552     static DeclareFunInst* genVoidFunction(const string& name, list<NamedTyped*>& args, BlockInst* code,
2553                                            bool isvirtual = false);
2554     static DeclareFunInst* genFunction0(const string& name, Typed::VarType res, BlockInst* code = new BlockInst());
2555     static DeclareFunInst* genFunction1(const string& name, Typed::VarType res, const string& arg1,
2556                                         Typed::VarType arg1_ty, BlockInst* code = new BlockInst());
2557     static DeclareFunInst* genFunction2(const string& name, Typed::VarType res, const string& arg1,
2558                                         Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
2559                                         BlockInst* code = new BlockInst());
2560     static DeclareFunInst* genFunction3(const string& name, Typed::VarType res, const string& arg1,
2561                                         Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
2562                                         const string& arg3, Typed::VarType arg3_ty, BlockInst* code = new BlockInst());
2563     static DeclareFunInst* genFunction4(const string& name, Typed::VarType res, const string& arg1,
2564                                         Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
2565                                         const string& arg3, Typed::VarType arg3_ty, const string& arg4,
2566                                         Typed::VarType arg4_ty, BlockInst* code = new BlockInst());
2567     static DeclareFunInst* genFunction5(const string& name, Typed::VarType res, const string& arg1,
2568                                         Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
2569                                         const string& arg3, Typed::VarType arg3_ty, const string& arg4,
2570                                         Typed::VarType arg4_ty, const string& arg5, Typed::VarType arg5_ty,
2571                                         BlockInst* code = new BlockInst());
2572     static DeclareFunInst* genFunction6(const string& name, Typed::VarType res, const string& arg1,
2573                                         Typed::VarType arg1_ty, const string& arg2, Typed::VarType arg2_ty,
2574                                         const string& arg3, Typed::VarType arg3_ty, const string& arg4,
2575                                         Typed::VarType arg4_ty, const string& arg5, Typed::VarType arg5_ty,
2576                                         const string& arg6, Typed::VarType arg6_ty, BlockInst* code = new BlockInst());
2577 
2578     // Convert a signal type in a Fir type by using an intermediate Tree based implementation to assure type creation
2579     // unicity. HACK : 09/12/11
2580     // static DeclareTypeInst* genType(AudioType* type);
2581 
2582     // HACK : 09/12/11
2583     // static Typed* mapFIRType(AudioType* type);
2584 };
2585 
2586 /* syntactic sugar for index computations
2587  *
2588  * wrapper for ValueInst* with support for basic arithmetics
2589  *
2590  */
2591 struct FIRIndex {
2592     /* explicit constructors in order to avoid the generation of implicit conversions */
FIRIndexFIRIndex2593     explicit FIRIndex(ValueInst* inst) : fValue(inst) {}
2594 
FIRIndexFIRIndex2595     explicit FIRIndex(int num) : fValue(InstBuilder::genInt32NumInst(num)) {}
2596 
FIRIndexFIRIndex2597     FIRIndex(FIRIndex const& rhs) : fValue(rhs.fValue) {}
2598 
2599     /* implicitly convert to ValueInst* in order to simplify the usage */
operator ValueInst*FIRIndex2600     operator ValueInst*(void)const { return fValue; }
2601 
2602     // Add
operator +(FIRIndex const & lhs,ValueInst * rhs)2603     friend FIRIndex operator+(FIRIndex const& lhs, ValueInst* rhs)
2604     {
2605         return FIRIndex(InstBuilder::genAdd(lhs.fValue, rhs));
2606     }
2607 
operator +(FIRIndex const & lhs,FIRIndex const & rhs)2608     friend FIRIndex operator+(FIRIndex const& lhs, FIRIndex const& rhs) { return operator+(lhs, rhs.fValue); }
2609 
operator +(FIRIndex const & lhs,int rhs)2610     friend FIRIndex operator+(FIRIndex const& lhs, int rhs)
2611     {
2612         return operator+(lhs, InstBuilder::genInt32NumInst(rhs));
2613     }
2614 
2615     // Sub
operator -(FIRIndex const & lhs,ValueInst * rhs)2616     friend FIRIndex operator-(FIRIndex const& lhs, ValueInst* rhs)
2617     {
2618         return FIRIndex(InstBuilder::genSub(lhs.fValue, rhs));
2619     }
2620 
operator -(FIRIndex const & lhs,FIRIndex const & rhs)2621     friend FIRIndex operator-(FIRIndex const& lhs, FIRIndex const& rhs) { return operator-(lhs, rhs.fValue); }
2622 
operator -(FIRIndex const & lhs,int rhs)2623     friend FIRIndex operator-(FIRIndex const& lhs, int rhs)
2624     {
2625         return operator-(lhs, InstBuilder::genInt32NumInst(rhs));
2626     }
2627 
2628     // Mult
operator *(FIRIndex const & lhs,ValueInst * rhs)2629     friend FIRIndex operator*(FIRIndex const& lhs, ValueInst* rhs)
2630     {
2631         return FIRIndex(InstBuilder::genMul(lhs.fValue, rhs));
2632     }
2633 
operator *(FIRIndex const & lhs,FIRIndex const & rhs)2634     friend FIRIndex operator*(FIRIndex const& lhs, FIRIndex const& rhs) { return operator*(lhs, rhs.fValue); }
2635 
operator *(FIRIndex const & lhs,int rhs)2636     friend FIRIndex operator*(FIRIndex const& lhs, int rhs)
2637     {
2638         return operator*(lhs, InstBuilder::genInt32NumInst(rhs));
2639     }
2640 
2641     // Div
operator /(FIRIndex const & lhs,ValueInst * rhs)2642     friend FIRIndex operator/(FIRIndex const& lhs, ValueInst* rhs)
2643     {
2644         return FIRIndex(InstBuilder::genDiv(lhs.fValue, rhs));
2645     }
2646 
operator /(FIRIndex const & lhs,FIRIndex const & rhs)2647     friend FIRIndex operator/(FIRIndex const& lhs, FIRIndex const& rhs) { return operator/(lhs, rhs.fValue); }
2648 
operator /(FIRIndex const & lhs,int rhs)2649     friend FIRIndex operator/(FIRIndex const& lhs, int rhs)
2650     {
2651         return operator/(lhs, InstBuilder::genInt32NumInst(rhs));
2652     }
2653 
2654     // And
operator &(FIRIndex const & lhs,ValueInst * rhs)2655     friend FIRIndex operator&(FIRIndex const& lhs, ValueInst* rhs)
2656     {
2657         return FIRIndex(InstBuilder::genAnd(lhs.fValue, rhs));
2658     }
2659 
operator &(FIRIndex const & lhs,FIRIndex const & rhs)2660     friend FIRIndex operator&(FIRIndex const& lhs, FIRIndex const& rhs) { return operator&(lhs, rhs.fValue); }
2661 
operator &(FIRIndex const & lhs,int rhs)2662     friend FIRIndex operator&(FIRIndex const& lhs, int rhs)
2663     {
2664         return operator&(lhs, InstBuilder::genInt32NumInst(rhs));
2665     }
2666 
2667     // Modulo
operator %(FIRIndex const & lhs,ValueInst * rhs)2668     friend FIRIndex operator%(FIRIndex const& lhs, ValueInst* rhs)
2669     {
2670         return FIRIndex(InstBuilder::genRem(lhs.fValue, rhs));
2671     }
2672 
operator %(FIRIndex const & lhs,FIRIndex const & rhs)2673     friend FIRIndex operator%(FIRIndex const& lhs, FIRIndex const& rhs) { return operator%(lhs, rhs.fValue); }
2674 
operator %(FIRIndex const & lhs,int rhs)2675     friend FIRIndex operator%(FIRIndex const& lhs, int rhs)
2676     {
2677         return operator%(lhs, InstBuilder::genInt32NumInst(rhs));
2678     }
2679 
2680     // Equal
operator ==(FIRIndex const & lhs,ValueInst * rhs)2681     friend FIRIndex operator==(FIRIndex const& lhs, ValueInst* rhs)
2682     {
2683         return FIRIndex(InstBuilder::genEqual(lhs.fValue, rhs));
2684     }
2685 
operator ==(FIRIndex const & lhs,FIRIndex const & rhs)2686     friend FIRIndex operator==(FIRIndex const& lhs, FIRIndex const& rhs) { return operator==(lhs, rhs.fValue); }
2687 
operator ==(FIRIndex const & lhs,int rhs)2688     friend FIRIndex operator==(FIRIndex const& lhs, int rhs)
2689     {
2690         return operator==(lhs, InstBuilder::genInt32NumInst(rhs));
2691     }
2692 
2693     // Inf
operator <(FIRIndex const & lhs,ValueInst * rhs)2694     friend FIRIndex operator<(FIRIndex const& lhs, ValueInst* rhs)
2695     {
2696         return FIRIndex(InstBuilder::genLessThan(lhs.fValue, rhs));
2697     }
2698 
operator <(FIRIndex const & lhs,FIRIndex const & rhs)2699     friend FIRIndex operator<(FIRIndex const& lhs, FIRIndex const& rhs) { return operator<(lhs, rhs.fValue); }
2700 
operator <(FIRIndex const & lhs,int rhs)2701     friend FIRIndex operator<(FIRIndex const& lhs, int rhs)
2702     {
2703         return operator<(lhs, InstBuilder::genInt32NumInst(rhs));
2704     }
2705 
2706    private:
2707     ValueInst* fValue;
2708 };
2709 
2710 #endif
2711 
2712 /*
2713 
2714 Name := sequence of char
2715 
2716 Size := digits
2717 
2718 Opcode := + | - | * | / |...etc...
2719 
2720 Access := kGlobal | kStruct | kStaticStruct | kFunArgs | kStack | kLoop
2721 
2722 Type := kFloat | kInt32 | kDouble | kVoid | Type* --> Type | Vector (Type) | Array (Type) if size = 0, then
2723 equivalent to a pointer on the considered type
2724 
2725 Address := Access name | Address index
2726 
2727 Statement   := DeclareVar (Address, Type, Value)
2728             | DeclareFun (Name, Type, Block)
2729             | ForLoop (Statement, Value, Statement, Block)
2730             | SimpleForLoop (string, Value, Block)
2731             | WhileLoop (Value, Block)
2732             | StoreVar (Address, Value)
2733             | Drop (Value)
2734             | Return (Value)
2735             | BlockInst (Statement*)
2736             | If (Value, BlockInst, BlockInst)
2737             | Switch (Value, <int>, BlockInst>*)
2738 
2739 Value       := LoadVar (Address)
2740             | Float | Int | Double | Bool
2741             | Select (Value1, Value2, Value3)
2742             | Binop (Opcode, Value1, Value2)
2743             | Cast (Type, Value)
2744             | Null ()
2745 
2746 Code rewritting :
2747 
2748 For WSS:
2749 
2750 1) change access of variable of type kStack in kStruct
2751 
2752 Loop to function rewritting (faster compilation ?):
2753 
2754 2 methods
2755 
2756 I)
2757 
2758 1) change kStack variables in kStruct
2759 2) transform Loop (Name, Value, Statement*) in DeclareFun (Name, Type, Statement*) : function type kVoid --> kVoid
2760 3) in Compute, replace each loop with a call to the created function
2761 
2762 II)
2763 
2764 1) in each loop, transform in put vector access from kStack in kFunArgs
2765 2) transform Loop (Name, Value, Statement*) in DeclareFun (Name, Type, Statement*) : all input variables become function
2766 parameters 3) in Compute, replace each loop with a call to the created function giving it the good parameters
2767 
2768 Scalarisation (some ideas, possibly not correct or not complete...):
2769 
2770 1) transform all vectors *without delay* on the stack (used in loops) in scalar
2771 2) in each loop, transform input vector accessing scalar access (Load/Store)
2772 3) regroup all "postcode" of all loop at the end
2773 4) rename loop variable into the Compute variable name
2774 5) extract code and put it in Compute, suppress Loop statements
2775 
2776 Vision des boucles (count, liste de vecteurs d'entrée, liste de vecteurs de sorties) différente du prototype externe
2777 compute(count, float**, float**) ou veut homogenéiser
2778 
2779 D'ou:
2780 
2781 DAG de boucles au format (count, liste de vecteurs d'entrée, liste de vecteurs de sorties)
2782 compute(count, float**, float**)
2783 
2784 1) générer le header qui prépare les tableaux d'entrée et de sortie séparés
2785 2) compiler les boucles
2786 
2787 Comment différencier les vecteurs sans retard (qu'on peut transformer en scalaire) des vecteurs avec retard ? Avec un
2788 nommage spécifique ?
2789 
2790 TODO : gestion des indices de boucles:
2791 
2792  - dans IndexedAddress, mettre un ValueInst à la place de fIndex, mettre à jour les visiteurs
2793 
2794  - dans InstructionsCompiler, générer des accès avec "LoadVar" (loop-index)
2795 
2796  - dans ForLoopInst, fName devient un "DeclareVarInst" (permet de nommer et d'initialiser l'indice), ajout d'une
2797 expression test, ajout de ValueInst fNext, calcul qui utilise fName.
2798 
2799  - nouveau type d'accès kLoop pour les variables de loop
2800 
2801  - lors des transformations sur les loops, Loop2FunctionBuider, SeqLoopBuilderVisitor, "désactiver" les statements qui
2802 manipulent les indices de la boucle ?? (pas besoin, ils n'apparaissent pas dans le corps de le boucle, par contre
2803 l'indice de la boucle est utilisé dans le corps de la boucle, il faut le faire correspondre au nouvel indice de boucle,
2804 renommage nécessaire ?)
2805 
2806  - utiliser le *même* nom d'index dans ForLoopInst et dans le code interne de la loop
2807 
2808 */
2809