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 _TEXT_INSTRUCTIONS_H 23 #define _TEXT_INSTRUCTIONS_H 24 25 #include <fstream> 26 #include <iostream> 27 #include <sstream> 28 #include <string> 29 #include <map> 30 31 #include "Text.hh" 32 #include "fir_to_fir.hh" 33 #include "instructions.hh" 34 #include "type_manager.hh" 35 36 class TextInstVisitor : public InstVisitor { 37 protected: 38 int fTab; 39 std::ostream* fOut; 40 bool fFinishLine; 41 std::string fObjectAccess; 42 StringTypeManager* fTypeManager; 43 EndLine(char end_line=';')44 virtual void EndLine(char end_line = ';') 45 { 46 if (fFinishLine) { 47 *fOut << end_line; 48 tab(fTab, *fOut); 49 } 50 } 51 52 // To be adapted in subclasses visitCond(ValueInst * cond)53 virtual void visitCond(ValueInst* cond) 54 { 55 cond->accept(this); 56 } 57 58 public: 59 using InstVisitor::visit; 60 TextInstVisitor(std::ostream * out,const std::string & object_access,int tab=0)61 TextInstVisitor(std::ostream* out, const std::string& object_access, int tab = 0) 62 : fTab(tab), fOut(out), fFinishLine(true), fObjectAccess(object_access) 63 { 64 fTypeManager = new CStringTypeManager(xfloat(), "*"); 65 } 66 TextInstVisitor(std::ostream * out,const std::string & object_access,const std::string & float_macro_name,const std::string & ptr_postfix,int tab=0)67 TextInstVisitor(std::ostream* out, const std::string& object_access, const std::string& float_macro_name, 68 const std::string& ptr_postfix, int tab = 0) 69 : fTab(tab), fOut(out), fFinishLine(true), fObjectAccess(object_access) 70 { 71 fTypeManager = new CStringTypeManager(float_macro_name, ptr_postfix); 72 } 73 TextInstVisitor(std::ostream * out,const std::string & object_access,StringTypeManager * manager,int tab=0)74 TextInstVisitor(std::ostream* out, const std::string& object_access, StringTypeManager* manager, int tab = 0) 75 : fTab(tab), fOut(out), fFinishLine(true), fObjectAccess(object_access), fTypeManager(manager) 76 { 77 } 78 ~TextInstVisitor()79 virtual ~TextInstVisitor() { delete fTypeManager; } 80 Tab(int n)81 void Tab(int n) { fTab = n; } 82 visit(LabelInst * inst)83 virtual void visit(LabelInst* inst) 84 { 85 *fOut << inst->fLabel; 86 tab(fTab, *fOut); 87 } 88 visit(DeclareVarInst * inst)89 virtual void visit(DeclareVarInst* inst) { faustassert(false); } 90 visit(RetInst * inst)91 virtual void visit(RetInst* inst) { visitAux(inst, true); } 92 visitAux(RetInst * inst,bool gen_empty)93 virtual void visitAux(RetInst* inst, bool gen_empty) 94 { 95 if (inst->fResult) { 96 *fOut << "return "; 97 inst->fResult->accept(this); 98 EndLine(); 99 } else if (gen_empty) { 100 *fOut << "return"; 101 EndLine(); 102 } 103 } 104 visit(DropInst * inst)105 virtual void visit(DropInst* inst) 106 { 107 if (inst->fResult) { 108 inst->fResult->accept(this); 109 EndLine(); 110 } 111 } 112 visit(DeclareFunInst * inst)113 virtual void visit(DeclareFunInst* inst) { faustassert(false); } 114 visit(NamedAddress * named)115 virtual void visit(NamedAddress* named) { *fOut << named->fName; } 116 117 /* 118 Indexed address can actually be values in an array or fields in a struct type 119 */ visit(IndexedAddress * indexed)120 virtual void visit(IndexedAddress* indexed) 121 { 122 indexed->fAddress->accept(this); 123 DeclareStructTypeInst* struct_type = isStructType(indexed->getName()); 124 if (struct_type) { 125 Int32NumInst* field_index = static_cast<Int32NumInst*>(indexed->fIndex); 126 *fOut << "->" << struct_type->fType->getName(field_index->fNum); 127 } else { 128 *fOut << "["; 129 indexed->fIndex->accept(this); 130 *fOut << "]"; 131 } 132 } 133 visit(LoadVarInst * inst)134 virtual void visit(LoadVarInst* inst) { inst->fAddress->accept(this); } 135 visit(LoadVarAddressInst * inst)136 virtual void visit(LoadVarAddressInst* inst) { faustassert(false); } 137 visit(StoreVarInst * inst)138 virtual void visit(StoreVarInst* inst) 139 { 140 inst->fAddress->accept(this); 141 *fOut << " = "; 142 inst->fValue->accept(this); 143 EndLine(); 144 } 145 visit(FloatNumInst * inst)146 virtual void visit(FloatNumInst* inst) { *fOut << checkFloat(inst->fNum); } 147 visit(FloatArrayNumInst * inst)148 virtual void visit(FloatArrayNumInst* inst) 149 { 150 char sep = '{'; 151 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 152 *fOut << sep << checkFloat(inst->fNumTable[i]); 153 sep = ','; 154 } 155 *fOut << '}'; 156 } 157 visit(Int32NumInst * inst)158 virtual void visit(Int32NumInst* inst) { *fOut << inst->fNum; } 159 visit(Int64NumInst * inst)160 virtual void visit(Int64NumInst* inst) { *fOut << inst->fNum; } 161 visit(Int32ArrayNumInst * inst)162 virtual void visit(Int32ArrayNumInst* inst) 163 { 164 char sep = '{'; 165 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 166 *fOut << sep << inst->fNumTable[i]; 167 sep = ','; 168 } 169 *fOut << '}'; 170 } 171 visit(BoolNumInst * inst)172 virtual void visit(BoolNumInst* inst) { *fOut << ((inst->fNum) ? "true" : "false"); } 173 visit(DoubleNumInst * inst)174 virtual void visit(DoubleNumInst* inst) { *fOut << checkDouble(inst->fNum); } 175 visit(DoubleArrayNumInst * inst)176 virtual void visit(DoubleArrayNumInst* inst) 177 { 178 char sep = '{'; 179 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 180 *fOut << sep << checkDouble(inst->fNumTable[i]); 181 sep = ','; 182 } 183 *fOut << '}'; 184 } 185 visit(BinopInst * inst)186 virtual void visit(BinopInst* inst) 187 { 188 *fOut << "("; 189 inst->fInst1->accept(this); 190 *fOut << " "; 191 *fOut << gBinOpTable[inst->fOpcode]->fName; 192 *fOut << " "; 193 inst->fInst2->accept(this); 194 *fOut << ")"; 195 } 196 visit(::CastInst * inst)197 virtual void visit(::CastInst* inst) { faustassert(false); } 198 generateFunName(const std::string & name)199 virtual std::string generateFunName(const std::string& name) 200 { 201 // If function is actually a method (that is "xx::name"), then keep "xx::name" in gGlobalTable but print "name" 202 size_t pos; 203 if ((pos = name.find("::")) != std::string::npos) { 204 return name.substr(pos + 2); // After the "::" 205 } else { 206 return name; 207 } 208 } 209 generateFunCallArgs(list<ValueInst * >::const_iterator beg,list<ValueInst * >::const_iterator end,size_t size)210 virtual void generateFunCallArgs(list<ValueInst*>::const_iterator beg, 211 list<ValueInst*>::const_iterator end, 212 size_t size) 213 { 214 list<ValueInst*>::const_iterator it = beg; 215 size_t i = 0; 216 for (it = beg; it != end; it++, i++) { 217 // Compile argument 218 (*it)->accept(this); 219 if (i < size - 1) *fOut << ", "; 220 } 221 } 222 generateFunDefArgs(DeclareFunInst * inst)223 virtual void generateFunDefArgs(DeclareFunInst* inst) 224 { 225 *fOut << "("; 226 227 list<NamedTyped*>::const_iterator it; 228 229 size_t size = inst->fType->fArgsTypes.size(), i = 0; 230 for (it = inst->fType->fArgsTypes.begin(); it != inst->fType->fArgsTypes.end(); it++, i++) { 231 *fOut << fTypeManager->generateType((*it)); 232 if (i < size - 1) *fOut << ", "; 233 } 234 } 235 generateFunDefBody(DeclareFunInst * inst)236 virtual void generateFunDefBody(DeclareFunInst* inst) 237 { 238 if (inst->fCode->fCode.size() == 0) { 239 *fOut << ");" << endl; // Pure prototype 240 } else { 241 // Function body 242 *fOut << ") {"; 243 fTab++; 244 tab(fTab, *fOut); 245 inst->fCode->accept(this); 246 fTab--; 247 back(1, *fOut); 248 *fOut << "}"; 249 tab(fTab, *fOut); 250 } 251 } 252 generateFunCall(FunCallInst * inst,const std::string & fun_name)253 virtual void generateFunCall(FunCallInst* inst, const std::string& fun_name) 254 { 255 if (inst->fMethod) { 256 list<ValueInst*>::const_iterator it = inst->fArgs.begin(); 257 // Compile object arg 258 (*it)->accept(this); 259 // Compile parameters 260 *fOut << fObjectAccess << fun_name << "("; 261 generateFunCallArgs(++it, inst->fArgs.end(), int(inst->fArgs.size()) - 1); 262 } else { 263 *fOut << fun_name << "("; 264 // Compile parameters 265 generateFunCallArgs(inst->fArgs.begin(), inst->fArgs.end(), int(inst->fArgs.size())); 266 } 267 *fOut << ")"; 268 } 269 visit(FunCallInst * inst)270 virtual void visit(FunCallInst* inst) { faustassert(false); } 271 visit(Select2Inst * inst)272 virtual void visit(Select2Inst* inst) 273 { 274 *fOut << "("; 275 visitCond(inst->fCond); 276 *fOut << " ? "; 277 inst->fThen->accept(this); 278 *fOut << " : "; 279 inst->fElse->accept(this); 280 *fOut << ")"; 281 } 282 visit(IfInst * inst)283 virtual void visit(IfInst* inst) 284 { 285 *fOut << "if ("; 286 visitCond(inst->fCond); 287 *fOut << ") {"; 288 fTab++; 289 tab(fTab, *fOut); 290 inst->fThen->accept(this); 291 fTab--; 292 back(1, *fOut); 293 if (inst->fElse->fCode.size() > 0) { 294 *fOut << "} else {"; 295 fTab++; 296 tab(fTab, *fOut); 297 inst->fElse->accept(this); 298 fTab--; 299 back(1, *fOut); 300 *fOut << "}"; 301 } else { 302 *fOut << "}"; 303 } 304 tab(fTab, *fOut); 305 } 306 visit(ForLoopInst * inst)307 virtual void visit(ForLoopInst* inst) 308 { 309 // Don't generate empty loops... 310 if (inst->fCode->size() == 0) return; 311 312 *fOut << "for ("; 313 fFinishLine = false; 314 inst->fInit->accept(this); 315 *fOut << "; "; 316 inst->fEnd->accept(this); 317 *fOut << "; "; 318 inst->fIncrement->accept(this); 319 fFinishLine = true; 320 *fOut << ") {"; 321 fTab++; 322 tab(fTab, *fOut); 323 inst->fCode->accept(this); 324 fTab--; 325 back(1, *fOut); 326 *fOut << "}"; 327 tab(fTab, *fOut); 328 } 329 visit(WhileLoopInst * inst)330 virtual void visit(WhileLoopInst* inst) 331 { 332 *fOut << "while ("; 333 visitCond(inst->fCond); 334 *fOut << ") {"; 335 fTab++; 336 tab(fTab, *fOut); 337 inst->fCode->accept(this); 338 fTab--; 339 back(1, *fOut); 340 *fOut << "}"; 341 tab(fTab, *fOut); 342 } 343 visit(BlockInst * inst)344 virtual void visit(BlockInst* inst) 345 { 346 if (inst->fIndent) { 347 *fOut << "{"; 348 fTab++; 349 tab(fTab, *fOut); 350 } 351 RetInst* ret_inst = nullptr; 352 for (const auto& it : inst->fCode) { 353 // Special case for "return" as last instruction 354 if ((it == *inst->fCode.rbegin()) && (ret_inst = dynamic_cast<RetInst*>(it))) { 355 visitAux(ret_inst, false); 356 } else { 357 it->accept(this); 358 } 359 } 360 if (inst->fIndent) { 361 fTab--; 362 back(1, *fOut); 363 *fOut << "}"; 364 tab(fTab, *fOut); 365 } 366 } 367 visit(::SwitchInst * inst)368 virtual void visit(::SwitchInst* inst) 369 { 370 *fOut << "switch ("; 371 inst->fCond->accept(this); 372 *fOut << ") {"; 373 fTab++; 374 tab(fTab, *fOut); 375 list<pair<int, BlockInst*> >::const_iterator it; 376 for (it = inst->fCode.begin(); it != inst->fCode.end(); it++) { 377 if ((*it).first == -1) { // -1 used to code "default" case 378 *fOut << "default: {"; 379 } else { 380 *fOut << "case " << (*it).first << ": {"; 381 } 382 fTab++; 383 tab(fTab, *fOut); 384 ((*it).second)->accept(this); 385 if (!((*it).second)->hasReturn()) { 386 *fOut << "break;"; 387 } 388 fTab--; 389 tab(fTab, *fOut); 390 *fOut << "}"; 391 tab(fTab, *fOut); 392 } 393 fTab--; 394 back(1, *fOut); 395 *fOut << "}"; 396 tab(fTab, *fOut); 397 } 398 getTypeManager()399 StringTypeManager* getTypeManager() { return fTypeManager; } 400 401 }; 402 403 // Mathematical functions are declared as variables, they have to be generated before any other function (like 404 // 'faustpower') 405 struct sortDeclareFunctions { 406 std::map<std::string, std::string> fMathLibTable; 407 sortDeclareFunctionssortDeclareFunctions408 sortDeclareFunctions(const std::map<std::string, std::string>& table) : fMathLibTable(table) {} 409 operator ()sortDeclareFunctions410 bool operator()(StatementInst* a, StatementInst* b) 411 { 412 DeclareFunInst* inst1 = dynamic_cast<DeclareFunInst*>(a); 413 DeclareFunInst* inst2 = dynamic_cast<DeclareFunInst*>(b); 414 415 if (inst1) { 416 if (inst2) { 417 if (fMathLibTable.find(inst1->fName) != fMathLibTable.end()) { 418 if (fMathLibTable.find(inst2->fName) != fMathLibTable.end()) { 419 return inst1->fName < inst2->fName; 420 } else { 421 return true; 422 } 423 } 424 } 425 } 426 return false; 427 } 428 }; 429 430 #endif 431