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 _TYPING_INSTRUCTIONS_H
23 #define _TYPING_INSTRUCTIONS_H
24 
25 #include "instructions.hh"
26 
27 using namespace std;
28 
29 /*
30  Typing visitor: to be used when knowing the exact type of the currenty compiled value is needed.
31  */
32 
33 struct TypingVisitor : public InstVisitor {
34     Typed::VarType fCurType;
35 
TypingVisitorTypingVisitor36     TypingVisitor() : fCurType(Typed::kNoType) {}
37 
~TypingVisitorTypingVisitor38     virtual ~TypingVisitor() {}
39 
visitTypingVisitor40     virtual void visit(LoadVarInst* inst)
41     {
42         // Stack or struct variables
43         if (gGlobal->hasVarType(inst->getName())) {
44             fCurType                = gGlobal->getVarType(inst->getName());
45             IndexedAddress* indexed = dynamic_cast<IndexedAddress*>(inst->fAddress);
46             if (indexed) {
47                 // IndexedAddress is also used for struct type
48                 DeclareStructTypeInst* struct_type = isStructType(indexed->getName());
49                 if (struct_type) {
50                     Int32NumInst* field_index = static_cast<Int32NumInst*>(indexed->fIndex);
51                     fCurType                  = struct_type->fType->getType(field_index->fNum);
52                 } else {
53                     fCurType = Typed::getTypeFromPtr(fCurType);
54                 }
55             }
56             // Specific cases for FunArgs
57         } else if (startWith(inst->getName(), "count") || startWith(inst->getName(), "sample_rate")) {
58             fCurType = Typed::kInt32;
59         } else {
60             fCurType = Typed::kNoType;
61             throw faustexception("ERROR in TypingVisitor : variable '" + inst->getName() + "' has Typed::kNoType\n");
62         }
63     }
64 
visitTypingVisitor65     virtual void visit(TeeVarInst* inst)
66     {
67         if (gGlobal->hasVarType(inst->getName())) {
68             fCurType = gGlobal->getVarType(inst->getName());
69         } else {
70             fCurType = Typed::kNoType;
71         }
72     }
73 
visitTypingVisitor74     virtual void visit(LoadVarAddressInst* inst)
75     {
76         // Not implemented
77         faustassert(false);
78     }
79 
visitTypingVisitor80     virtual void visit(FloatNumInst* inst) { fCurType = Typed::kFloat; }
81 
visitTypingVisitor82     virtual void visit(Int32NumInst* inst) { fCurType = Typed::kInt32; }
83 
visitTypingVisitor84     virtual void visit(Int64NumInst* inst) { fCurType = Typed::kInt64; }
85 
visitTypingVisitor86     virtual void visit(BoolNumInst* inst) { fCurType = Typed::kBool; }
87 
visitTypingVisitor88     virtual void visit(DoubleNumInst* inst) { fCurType = Typed::kDouble; }
89 
visitTypingVisitor90     virtual void visit(BinopInst* inst)
91     {
92         if (isBoolOpcode(inst->fOpcode)) {
93             fCurType = Typed::kBool;
94         } else {
95             inst->fInst1->accept(this);
96             Typed::VarType type1 = fCurType;
97             if (isRealType(type1)) {
98                 fCurType = type1;
99             } else {
100                 inst->fInst2->accept(this);
101                 Typed::VarType type2 = fCurType;
102                 if (isRealType(type2)) {
103                     fCurType = type2;
104                 } else if (isInt32Type(type1) || isInt32Type(type2)) {
105                     fCurType = Typed::kInt32;
106                 } else if (isInt64Type(type1) || isInt64Type(type2)) {
107                     fCurType = Typed::kInt64;
108                 } else if (isBoolType(type1) && isBoolType(type2)) {
109                     fCurType = Typed::kInt32;
110                 } else {
111                     // Should never happen...
112                     faustassert(false);
113                 }
114             }
115         }
116     }
117 
visitTypingVisitor118     virtual void visit(::CastInst* inst) { fCurType = inst->fType->getType(); }
119 
visitTypingVisitor120     virtual void visit(BitcastInst* inst) { fCurType = inst->fType->getType(); }
121 
visitTypingVisitor122     virtual void visit(Select2Inst* inst)
123     {
124         inst->fThen->accept(this);
125         Typed::VarType type1 = fCurType;
126         if (isRealType(type1)) {
127             fCurType = type1;
128         } else {
129             inst->fElse->accept(this);
130             Typed::VarType type2 = fCurType;
131             if (isRealType(type2)) {
132                 fCurType = type2;
133             } else if (isInt32Type(type1) || isInt32Type(type2)) {
134                 fCurType = Typed::kInt32;
135             } else if (isInt64Type(type1) || isInt64Type(type2)) {
136                 fCurType = Typed::kInt64;
137             } else if (isBoolType(type1) && isBoolType(type2)) {
138                 fCurType = Typed::kBool;
139             } else {
140                 // Should never happen...
141                 faustassert(false);
142             }
143         }
144     }
145 
visitTypingVisitor146     virtual void visit(IfInst* inst)
147     {
148         // Type in the one of 'then' or 'else'
149         inst->fThen->accept(this);
150     }
151 
visitTypingVisitor152     virtual void visit(FunCallInst* inst)
153     {
154         if (gGlobal->hasVarType(inst->fName)) {
155             fCurType = gGlobal->getVarType(inst->fName);
156         } else {
157             // Should never happen...
158             cerr << "TypingVisitor::visit(FunCallInst* inst) name " << inst->fName << std::endl;
159             faustassert(false);
160         }
161     }
162 };
163 
164 struct BasicTypingCloneVisitor : public BasicCloneVisitor {
165     TypingVisitor fTypingVisitor;
166 
BasicTypingCloneVisitorBasicTypingCloneVisitor167     BasicTypingCloneVisitor() {}
168 
169     // Memory
visitBasicTypingCloneVisitor170     virtual ValueInst* visit(LoadVarInst* inst)
171     {
172         fTypingVisitor.visit(inst);
173         return BasicCloneVisitor::visit(inst);
174     }
175 
176     // Numbers
visitBasicTypingCloneVisitor177     virtual ValueInst* visit(FloatNumInst* inst)
178     {
179         fTypingVisitor.visit(inst);
180         return BasicCloneVisitor::visit(inst);
181     }
visitBasicTypingCloneVisitor182     virtual ValueInst* visit(Int32NumInst* inst)
183     {
184         fTypingVisitor.visit(inst);
185         return BasicCloneVisitor::visit(inst);
186     }
visitBasicTypingCloneVisitor187     virtual ValueInst* visit(Int64NumInst* inst)
188     {
189         fTypingVisitor.visit(inst);
190         return BasicCloneVisitor::visit(inst);
191     }
visitBasicTypingCloneVisitor192     virtual ValueInst* visit(BoolNumInst* inst)
193     {
194         fTypingVisitor.visit(inst);
195         return BasicCloneVisitor::visit(inst);
196     }
visitBasicTypingCloneVisitor197     virtual ValueInst* visit(DoubleNumInst* inst)
198     {
199         fTypingVisitor.visit(inst);
200         return BasicCloneVisitor::visit(inst);
201     }
202 
203     // Numerical computation
visitBasicTypingCloneVisitor204     virtual ValueInst* visit(BinopInst* inst)
205     {
206         fTypingVisitor.visit(inst);
207         return BasicCloneVisitor::visit(inst);
208     }
209 
210     // Cast
visitBasicTypingCloneVisitor211     virtual ValueInst* visit(::CastInst* inst)
212     {
213         fTypingVisitor.visit(inst);
214         return BasicCloneVisitor::visit(inst);
215     }
visitBasicTypingCloneVisitor216     virtual ValueInst* visit(BitcastInst* inst)
217     {
218         fTypingVisitor.visit(inst);
219         return BasicCloneVisitor::visit(inst);
220     }
221 
222     // Function call
visitBasicTypingCloneVisitor223     virtual ValueInst* visit(FunCallInst* inst)
224     {
225         fTypingVisitor.visit(inst);
226         return BasicCloneVisitor::visit(inst);
227     }
228 
229     // Conditionnal
visitBasicTypingCloneVisitor230     virtual ValueInst* visit(Select2Inst* inst)
231     {
232         fTypingVisitor.visit(inst);
233         return BasicCloneVisitor::visit(inst);
234     }
visitBasicTypingCloneVisitor235     virtual StatementInst* visit(IfInst* inst)
236     {
237         fTypingVisitor.visit(inst);
238         return BasicCloneVisitor::visit(inst);
239     }
240 };
241 
242 #endif
243