1 /************************************************************************ 2 ************************************************************************ 3 FAUST compiler 4 Copyright (C) 2019-2020 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 _FBC_LLVM_COMPILER_H 23 #define _FBC_LLVM_COMPILER_H 24 25 #include <map> 26 #include <string> 27 #include <vector> 28 29 #include <llvm-c/Core.h> 30 #include <llvm-c/ExecutionEngine.h> 31 #include <llvm-c/Initialization.h> 32 #include <llvm-c/Target.h> 33 #include <llvm-c/Transforms/PassManagerBuilder.h> 34 #include <llvm-c/Transforms/Vectorize.h> 35 36 #include "interpreter_bytecode.hh" 37 #include "fbc_executor.hh" 38 39 // FBC LLVM compiler 40 template <class REAL> 41 class FBCLLVMCompiler : public FBCExecuteFun<REAL> { 42 43 typedef void (*compiledFun)(int* int_heap, REAL* real_heap, REAL** inputs, REAL** outputs); 44 45 protected: 46 LLVMExecutionEngineRef fJIT; 47 LLVMModuleRef fModule; 48 LLVMBuilderRef fBuilder; 49 LLVMBuilderRef fAllocaBuilder; 50 compiledFun fCompiledFun; 51 52 LLVMValueRef fLLVMStack[512]; 53 InstructionIT fAddressStack[64]; 54 55 int fLLVMStackIndex; 56 int fAddrStackIndex; 57 58 LLVMValueRef fLLVMIntHeap; 59 LLVMValueRef fLLVMRealHeap; 60 LLVMValueRef fLLVMInputs; 61 LLVMValueRef fLLVMOutputs; 62 genFloat(float num)63 LLVMValueRef genFloat(float num) { return LLVMConstReal(LLVMFloatType(), num); } genDouble(double num)64 LLVMValueRef genDouble(double num) { return LLVMConstReal(LLVMDoubleType(), num); } genReal(double num)65 LLVMValueRef genReal(double num) { return (sizeof(REAL) == sizeof(double)) ? genDouble(num) : genFloat(num); } genInt32(int num)66 LLVMValueRef genInt32(int num) { return LLVMConstInt(LLVMInt32Type(), num, true); } genInt64(int64_t num)67 LLVMValueRef genInt64(int64_t num) { return LLVMConstInt(LLVMInt64Type(), num, true); } 68 getFloatTy()69 LLVMTypeRef getFloatTy() { return LLVMFloatType(); } getDoubleTy()70 LLVMTypeRef getDoubleTy() { return LLVMDoubleType(); } getRealTy()71 LLVMTypeRef getRealTy() { return (sizeof(REAL) == sizeof(double)) ? getDoubleTy() : getFloatTy(); } getInt32Ty()72 LLVMTypeRef getInt32Ty() { return LLVMInt32Type(); } getInt64Ty()73 LLVMTypeRef getInt64Ty() { return LLVMInt64Type(); } getInt1Ty()74 LLVMTypeRef getInt1Ty() { return LLVMInt1Type(); } 75 getMathName(const std::string & name)76 std::string getMathName(const std::string& name) { return (sizeof(REAL) == sizeof(float)) ? (name + "f") : name; } 77 pushValue(LLVMValueRef val)78 void pushValue(LLVMValueRef val) { fLLVMStack[fLLVMStackIndex++] = val; } popValue()79 LLVMValueRef popValue() { return fLLVMStack[--fLLVMStackIndex]; } 80 pushBinop(LLVMOpcode op)81 void pushBinop(LLVMOpcode op) 82 { 83 LLVMValueRef v1 = popValue(); 84 LLVMValueRef v2 = popValue(); 85 pushValue(LLVMBuildBinOp(fBuilder, op, v1, v2, "")); 86 } 87 pushRealComp(LLVMRealPredicate op)88 void pushRealComp(LLVMRealPredicate op) 89 { 90 LLVMValueRef v1 = popValue(); 91 LLVMValueRef v2 = popValue(); 92 LLVMValueRef cond_value = LLVMBuildFCmp(fBuilder, op, v1, v2, ""); 93 pushValue(LLVMBuildSelect(fBuilder, cond_value, genInt32(1), genInt32(0), "")); 94 } 95 pushIntComp(LLVMIntPredicate op)96 void pushIntComp(LLVMIntPredicate op) 97 { 98 LLVMValueRef v1 = popValue(); 99 LLVMValueRef v2 = popValue(); 100 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, op, v1, v2, ""); 101 pushValue(LLVMBuildSelect(fBuilder, cond_value, genInt32(1), genInt32(0), "")); 102 } 103 104 // Min/max pushIntMax()105 void pushIntMax() 106 { 107 LLVMValueRef v1 = popValue(); 108 LLVMValueRef v2 = popValue(); 109 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntSLT, v1, v2, ""); 110 pushValue(LLVMBuildSelect(fBuilder, cond_value, v2, v1, "")); 111 } 112 pushIntMin()113 void pushIntMin() 114 { 115 LLVMValueRef v1 = popValue(); 116 LLVMValueRef v2 = popValue(); 117 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntSLT, v1, v2, ""); 118 pushValue(LLVMBuildSelect(fBuilder, cond_value, v1, v2, "")); 119 } 120 pushRealMax()121 void pushRealMax() 122 { 123 LLVMValueRef v1 = popValue(); 124 LLVMValueRef v2 = popValue(); 125 LLVMValueRef cond_value = LLVMBuildFCmp(fBuilder, LLVMRealOLT, v1, v2, ""); 126 pushValue(LLVMBuildSelect(fBuilder, cond_value, v2, v1, "")); 127 } 128 pushRealMin()129 void pushRealMin() 130 { 131 LLVMValueRef v1 = popValue(); 132 LLVMValueRef v2 = popValue(); 133 LLVMValueRef cond_value = LLVMBuildFCmp(fBuilder, LLVMRealOLT, v1, v2, ""); 134 pushValue(LLVMBuildSelect(fBuilder, cond_value, v1, v2, "")); 135 } 136 pushUnaryCall(const std::string & name_aux,LLVMTypeRef res_type,LLVMTypeRef arg_type,bool rename)137 void pushUnaryCall(const std::string& name_aux, LLVMTypeRef res_type, LLVMTypeRef arg_type, bool rename) 138 { 139 std::string name = (rename) ? getMathName(name_aux) : name_aux; 140 LLVMValueRef function = LLVMGetNamedFunction(fModule, name.c_str()); 141 if (!function) { 142 // Define it 143 LLVMTypeRef param_types[] = { arg_type }; 144 LLVMTypeRef ret_type = LLVMFunctionType(res_type, param_types, 1, false); 145 function = LLVMAddFunction(fModule, name.c_str(), ret_type); 146 } 147 // Create the function call 148 LLVMValueRef fun_args[] = { popValue() }; 149 pushValue(LLVMBuildCall(fBuilder, function, fun_args, 1, "")); 150 } 151 pushUnaryIntCall(const std::string & name,bool rename=true)152 void pushUnaryIntCall(const std::string& name, bool rename = true) 153 { 154 return pushUnaryCall(name, getInt32Ty(), getInt32Ty(), rename); 155 } pushUnaryRealCall(const std::string & name,bool rename=true)156 void pushUnaryRealCall(const std::string& name, bool rename = true) 157 { 158 return pushUnaryCall(name, getRealTy(), getRealTy(), rename); 159 } 160 pushBinaryCall(const std::string & name_aux,LLVMTypeRef res_type,LLVMTypeRef arg1_type,LLVMTypeRef arg2_type)161 void pushBinaryCall(const std::string& name_aux, LLVMTypeRef res_type, LLVMTypeRef arg1_type, LLVMTypeRef arg2_type) 162 { 163 std::string name = getMathName(name_aux); 164 LLVMValueRef function = LLVMGetNamedFunction(fModule, name.c_str()); 165 if (!function) { 166 // Define it 167 LLVMTypeRef param_types[] = { arg1_type, arg2_type }; 168 LLVMTypeRef ret_type = LLVMFunctionType(res_type, param_types, 2, false); 169 function = LLVMAddFunction(fModule, name.c_str(), ret_type); 170 } 171 // Create the function call 172 LLVMValueRef fun_args[] = { popValue(), popValue() }; 173 pushValue(LLVMBuildCall(fBuilder, function, fun_args, 2, "")); 174 } 175 pushBinaryIntCall(const std::string & name)176 void pushBinaryIntCall(const std::string& name) { pushBinaryCall(name, getInt32Ty(), getInt32Ty(), getInt32Ty()); } 177 pushBinaryRealCall(const std::string & name)178 void pushBinaryRealCall(const std::string& name) { pushBinaryCall(name, getRealTy(), getRealTy(), getRealTy()); } 179 pushLoadArray(LLVMValueRef array,int index)180 void pushLoadArray(LLVMValueRef array, int index) { pushLoadArray(array, genInt32(index)); } 181 pushStoreArray(LLVMValueRef array,int index)182 void pushStoreArray(LLVMValueRef array, int index) { pushStoreArray(array, genInt32(index)); } 183 pushLoadArray(LLVMValueRef array,LLVMValueRef index)184 void pushLoadArray(LLVMValueRef array, LLVMValueRef index) 185 { 186 LLVMValueRef idx[] = {index}; 187 LLVMValueRef load_ptr = LLVMBuildInBoundsGEP(fBuilder, array, idx, 1, ""); 188 pushValue(LLVMBuildLoad(fBuilder, load_ptr, "")); 189 } 190 pushStoreArray(LLVMValueRef array,LLVMValueRef index)191 void pushStoreArray(LLVMValueRef array, LLVMValueRef index) 192 { 193 LLVMValueRef idx[] = {index}; 194 LLVMValueRef store_ptr = LLVMBuildInBoundsGEP(fBuilder, array, idx, 1, ""); 195 LLVMBuildStore(fBuilder, popValue(), store_ptr); 196 } 197 pushLoadInput(int index)198 void pushLoadInput(int index) 199 { 200 LLVMValueRef idx1[] = {genInt32(index)}; 201 LLVMValueRef input_ptr_ptr = LLVMBuildInBoundsGEP(fBuilder, fLLVMInputs, idx1, 1, ""); 202 LLVMValueRef input_ptr = LLVMBuildLoad(fBuilder, input_ptr_ptr, ""); 203 LLVMValueRef idx2[] = {popValue()}; 204 LLVMValueRef input = LLVMBuildInBoundsGEP(fBuilder, input_ptr, idx2, 1, ""); 205 pushValue(LLVMBuildLoad(fBuilder, input, "")); 206 } 207 pushStoreOutput(int index)208 void pushStoreOutput(int index) 209 { 210 LLVMValueRef idx1[] = {genInt32(index)}; 211 LLVMValueRef output_ptr_ptr = LLVMBuildInBoundsGEP(fBuilder, fLLVMOutputs, idx1, 1, ""); 212 LLVMValueRef output_ptr = LLVMBuildLoad(fBuilder, output_ptr_ptr, ""); 213 LLVMValueRef idx2[] = {popValue()}; 214 LLVMValueRef output = LLVMBuildInBoundsGEP(fBuilder, output_ptr, idx2, 1, ""); 215 LLVMBuildStore(fBuilder, popValue(), output); 216 } 217 218 // Select that computes both branches createSelectBlock0(InstructionIT it,LLVMBasicBlockRef code_block)219 void createSelectBlock0(InstructionIT it, LLVMBasicBlockRef code_block) 220 { 221 // Prepare condition: compare condition to 0 222 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntNE, popValue(), genInt32(0), "select_cond"); 223 224 // Compile then branch (= branch1) 225 CompileBlock((*it)->fBranch1, code_block); 226 227 // Compile else branch (= branch2) 228 CompileBlock((*it)->fBranch2, code_block); 229 230 // Create the result (= branch2) 231 LLVMValueRef then_value = popValue(); 232 LLVMValueRef else_value = popValue(); 233 // Inverted here 234 pushValue(LLVMBuildSelect(fBuilder, cond_value, else_value, then_value, "")); 235 } 236 237 // Select that only computes one branch createSelectBlock1(InstructionIT it,LLVMValueRef typed_res)238 void createSelectBlock1(InstructionIT it, LLVMValueRef typed_res) 239 { 240 // Prepare condition: compare condition to 0 241 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntNE, popValue(), genInt32(0), "select_cond"); 242 243 // Get enclosing function 244 LLVMValueRef function = LLVMGetBasicBlockParent(LLVMGetInsertBlock(fBuilder)); 245 246 // Create blocks for the then and else cases. Insert the 'then' block at the end of the function 247 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(function, "select_then_block"); 248 LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(function, "select_else_block"); 249 LLVMBasicBlockRef merge_block = LLVMAppendBasicBlock(function, "select_merge_block"); 250 251 LLVMBuildCondBr(fBuilder, cond_value, then_block, else_block); 252 253 // Compile then branch (= branch1) 254 CompileBlock((*it)->fBranch1, then_block); 255 256 // Store the result 257 LLVMBuildStore(fBuilder, popValue(), typed_res); 258 259 // Branch in merge_block 260 LLVMBuildBr(fBuilder, merge_block); 261 262 // Compile else branch (= branch2) 263 CompileBlock((*it)->fBranch2, else_block); 264 265 // Store the result 266 LLVMBuildStore(fBuilder, popValue(), typed_res); 267 268 // Branch in merge_block 269 LLVMBuildBr(fBuilder, merge_block); 270 271 // Insert in merge_block 272 LLVMPositionBuilderAtEnd(fBuilder, merge_block); 273 274 // Load the result 275 pushValue(LLVMBuildLoad(fBuilder, typed_res, "")); 276 } 277 CompileBlock(FBCBlockInstruction<REAL> * block,LLVMBasicBlockRef code_block)278 void CompileBlock(FBCBlockInstruction<REAL>* block, LLVMBasicBlockRef code_block) 279 { 280 InstructionIT it = block->fInstructions.begin(); 281 bool end = false; 282 283 // Insert in the current block 284 LLVMPositionBuilderAtEnd(fBuilder, code_block); 285 286 while ((it != block->fInstructions.end()) && !end) { 287 //(*it)->write(&std::cout); 288 289 switch ((*it)->fOpcode) { 290 // Numbers 291 case FBCInstruction::kRealValue: 292 pushValue(genReal((*it)->fRealValue)); 293 it++; 294 break; 295 296 case FBCInstruction::kInt32Value: 297 pushValue(genInt32((*it)->fIntValue)); 298 it++; 299 break; 300 301 // Memory load/store 302 case FBCInstruction::kLoadReal: 303 pushLoadArray(fLLVMRealHeap, (*it)->fOffset1); 304 it++; 305 break; 306 307 case FBCInstruction::kLoadInt: 308 pushLoadArray(fLLVMIntHeap, (*it)->fOffset1); 309 it++; 310 break; 311 312 case FBCInstruction::kStoreReal: 313 pushStoreArray(fLLVMRealHeap, (*it)->fOffset1); 314 it++; 315 break; 316 317 case FBCInstruction::kStoreInt: 318 pushStoreArray(fLLVMIntHeap, (*it)->fOffset1); 319 it++; 320 break; 321 322 // Indexed memory load/store: constant values are added at generation time by CreateBinOp... 323 case FBCInstruction::kLoadIndexedReal: { 324 LLVMValueRef offset = LLVMBuildAdd(fBuilder, genInt32((*it)->fOffset1), popValue(), ""); 325 pushLoadArray(fLLVMRealHeap, offset); 326 it++; 327 break; 328 } 329 330 case FBCInstruction::kLoadIndexedInt: { 331 LLVMValueRef offset = LLVMBuildAdd(fBuilder, genInt32((*it)->fOffset1), popValue(), ""); 332 pushLoadArray(fLLVMIntHeap, offset); 333 it++; 334 break; 335 } 336 337 case FBCInstruction::kStoreIndexedReal: { 338 LLVMValueRef offset = LLVMBuildAdd(fBuilder, genInt32((*it)->fOffset1), popValue(), ""); 339 pushStoreArray(fLLVMRealHeap, offset); 340 it++; 341 break; 342 } 343 344 case FBCInstruction::kStoreIndexedInt: { 345 LLVMValueRef offset = LLVMBuildAdd(fBuilder, genInt32((*it)->fOffset1), popValue(), ""); 346 pushStoreArray(fLLVMIntHeap, offset); 347 it++; 348 break; 349 } 350 351 // Memory shift 352 case FBCInstruction::kBlockShiftReal: { 353 for (int i = (*it)->fOffset1; i > (*it)->fOffset2; i -= 1) { 354 pushLoadArray(fLLVMRealHeap, i - 1); 355 pushStoreArray(fLLVMRealHeap, i); 356 } 357 it++; 358 break; 359 } 360 361 case FBCInstruction::kBlockShiftInt: { 362 for (int i = (*it)->fOffset1; i > (*it)->fOffset2; i -= 1) { 363 pushLoadArray(fLLVMIntHeap, i - 1); 364 pushStoreArray(fLLVMIntHeap, i); 365 } 366 it++; 367 break; 368 } 369 370 // Input/output 371 case FBCInstruction::kLoadInput: 372 pushLoadInput((*it)->fOffset1); 373 it++; 374 break; 375 376 case FBCInstruction::kStoreOutput: 377 pushStoreOutput((*it)->fOffset1); 378 it++; 379 break; 380 381 // Cast 382 case FBCInstruction::kCastReal: { 383 LLVMValueRef val = popValue(); 384 pushValue(LLVMBuildSIToFP(fBuilder, val, getRealTy(), "")); 385 it++; 386 break; 387 } 388 389 case FBCInstruction::kCastInt: { 390 LLVMValueRef val = popValue(); 391 pushValue(LLVMBuildFPToSI(fBuilder, val, getInt32Ty(), "")); 392 it++; 393 break; 394 } 395 396 case FBCInstruction::kBitcastInt: { 397 LLVMValueRef val = popValue(); 398 pushValue(LLVMBuildBitCast(fBuilder, val, getInt32Ty(), "")); 399 it++; 400 break; 401 } 402 403 case FBCInstruction::kBitcastReal: { 404 LLVMValueRef val = popValue(); 405 pushValue(LLVMBuildBitCast(fBuilder, val, getRealTy(), "")); 406 it++; 407 break; 408 } 409 410 // Binary math 411 case FBCInstruction::kAddReal: 412 pushBinop(LLVMFAdd); 413 it++; 414 break; 415 416 case FBCInstruction::kAddInt: 417 pushBinop(LLVMAdd); 418 it++; 419 break; 420 421 case FBCInstruction::kSubReal: 422 pushBinop(LLVMFSub); 423 it++; 424 break; 425 426 case FBCInstruction::kSubInt: 427 pushBinop(LLVMSub); 428 it++; 429 break; 430 431 case FBCInstruction::kMultReal: 432 pushBinop(LLVMFMul); 433 it++; 434 break; 435 436 case FBCInstruction::kMultInt: 437 pushBinop(LLVMMul); 438 it++; 439 break; 440 441 case FBCInstruction::kDivReal: 442 pushBinop(LLVMFDiv); 443 it++; 444 break; 445 446 case FBCInstruction::kDivInt: 447 pushBinop(LLVMSDiv); 448 it++; 449 break; 450 451 case FBCInstruction::kRemReal: 452 pushBinaryRealCall("remainder"); 453 it++; 454 break; 455 456 case FBCInstruction::kRemInt: 457 pushBinop(LLVMSRem); 458 it++; 459 break; 460 461 case FBCInstruction::kLshInt: 462 pushBinop(LLVMShl); 463 it++; 464 break; 465 466 case FBCInstruction::kARshInt: 467 pushBinop(LLVMLShr); 468 it++; 469 break; 470 471 case FBCInstruction::kGTInt: 472 pushIntComp(LLVMIntSGT); 473 it++; 474 break; 475 476 case FBCInstruction::kLTInt: 477 pushIntComp(LLVMIntSLT); 478 it++; 479 break; 480 481 case FBCInstruction::kGEInt: 482 pushIntComp(LLVMIntSGE); 483 it++; 484 break; 485 486 case FBCInstruction::kLEInt: 487 pushIntComp(LLVMIntSLE); 488 it++; 489 break; 490 491 case FBCInstruction::kEQInt: 492 pushIntComp(LLVMIntEQ); 493 it++; 494 break; 495 496 case FBCInstruction::kNEInt: 497 pushIntComp(LLVMIntNE); 498 it++; 499 break; 500 501 case FBCInstruction::kGTReal: 502 pushRealComp(LLVMRealOGT); 503 it++; 504 break; 505 506 case FBCInstruction::kLTReal: 507 pushRealComp(LLVMRealOLT); 508 it++; 509 break; 510 511 case FBCInstruction::kGEReal: 512 pushRealComp(LLVMRealOGE); 513 it++; 514 break; 515 516 case FBCInstruction::kLEReal: 517 pushRealComp(LLVMRealOLE); 518 it++; 519 break; 520 521 case FBCInstruction::kEQReal: 522 pushRealComp(LLVMRealOEQ); 523 it++; 524 break; 525 526 case FBCInstruction::kNEReal: 527 pushRealComp(LLVMRealONE); 528 it++; 529 break; 530 531 case FBCInstruction::kANDInt: 532 pushBinop(LLVMAnd); 533 it++; 534 break; 535 536 case FBCInstruction::kORInt: 537 pushBinop(LLVMOr); 538 it++; 539 break; 540 541 case FBCInstruction::kXORInt: 542 pushBinop(LLVMXor); 543 it++; 544 break; 545 546 // Extended unary math 547 case FBCInstruction::kAbs: 548 pushUnaryIntCall("abs", false); 549 it++; 550 break; 551 552 case FBCInstruction::kAbsf: 553 pushUnaryRealCall("fabs"); 554 it++; 555 break; 556 557 case FBCInstruction::kAcosf: 558 pushUnaryRealCall("acos"); 559 it++; 560 break; 561 562 case FBCInstruction::kAcoshf: 563 pushUnaryRealCall("acosh"); 564 it++; 565 break; 566 567 case FBCInstruction::kAsinf: 568 pushUnaryRealCall("asin"); 569 it++; 570 break; 571 572 case FBCInstruction::kAsinhf: 573 pushUnaryRealCall("asinh"); 574 it++; 575 break; 576 577 case FBCInstruction::kAtanf: 578 pushUnaryRealCall("atan"); 579 it++; 580 break; 581 582 case FBCInstruction::kAtanhf: 583 pushUnaryRealCall("atanh"); 584 it++; 585 break; 586 587 case FBCInstruction::kCeilf: 588 pushUnaryRealCall("ceil"); 589 it++; 590 break; 591 592 case FBCInstruction::kCosf: 593 pushUnaryRealCall("cos"); 594 it++; 595 break; 596 597 case FBCInstruction::kCoshf: 598 pushUnaryRealCall("cosh"); 599 it++; 600 break; 601 602 case FBCInstruction::kExpf: 603 pushUnaryRealCall("exp"); 604 it++; 605 break; 606 607 case FBCInstruction::kFloorf: 608 pushUnaryRealCall("floor"); 609 it++; 610 break; 611 612 case FBCInstruction::kLogf: 613 pushUnaryRealCall("log"); 614 it++; 615 break; 616 617 case FBCInstruction::kLog10f: 618 pushUnaryRealCall("log10"); 619 it++; 620 break; 621 622 case FBCInstruction::kRintf: 623 pushUnaryRealCall("rint"); 624 it++; 625 break; 626 627 case FBCInstruction::kRoundf: 628 pushUnaryRealCall("round"); 629 it++; 630 break; 631 632 case FBCInstruction::kSinf: 633 pushUnaryRealCall("sin"); 634 it++; 635 break; 636 637 case FBCInstruction::kSinhf: 638 pushUnaryRealCall("sinh"); 639 it++; 640 break; 641 642 case FBCInstruction::kSqrtf: 643 pushUnaryRealCall("sqrt"); 644 it++; 645 break; 646 647 case FBCInstruction::kTanf: 648 pushUnaryRealCall("tan"); 649 it++; 650 break; 651 652 case FBCInstruction::kTanhf: 653 pushUnaryRealCall("tanh"); 654 it++; 655 break; 656 657 case FBCInstruction::kIsnanf: 658 pushUnaryCall("isnan", getInt32Ty(), getRealTy(), true); 659 it++; 660 break; 661 662 case FBCInstruction::kIsinff: 663 pushUnaryCall("isinf", getInt32Ty(), getRealTy(), true); 664 it++; 665 break; 666 667 case FBCInstruction::kCopysignf: 668 pushBinaryRealCall("copysign"); 669 it++; 670 break; 671 672 // Extended binary math 673 case FBCInstruction::kAtan2f: 674 pushBinaryRealCall("atan2"); 675 it++; 676 break; 677 678 case FBCInstruction::kFmodf: 679 pushBinaryRealCall("fmod"); 680 it++; 681 break; 682 683 case FBCInstruction::kPowf: 684 pushBinaryRealCall("pow"); 685 it++; 686 break; 687 688 case FBCInstruction::kMax: { 689 pushIntMax(); 690 it++; 691 break; 692 } 693 694 case FBCInstruction::kMaxf: { 695 pushRealMax(); 696 it++; 697 break; 698 } 699 700 case FBCInstruction::kMin: { 701 pushIntMin(); 702 it++; 703 break; 704 } 705 706 case FBCInstruction::kMinf: { 707 pushRealMin(); 708 it++; 709 break; 710 } 711 712 // Control 713 case FBCInstruction::kReturn: 714 end = true; 715 break; 716 717 case FBCInstruction::kIf: { 718 719 // Prepare condition: compare condition to 0 720 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntNE, popValue(), genInt32(0), "if_cond"); 721 722 // Get enclosing function 723 LLVMValueRef function = LLVMGetBasicBlockParent(LLVMGetInsertBlock(fBuilder)); 724 725 // Create blocks for the then and else cases. Insert the 'then' block at the end of the function 726 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(function, "if_then_block"); 727 LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(function, "if_else_block"); 728 LLVMBasicBlockRef merge_block = LLVMAppendBasicBlock(function, "if_merge_block"); 729 730 LLVMBuildCondBr(fBuilder, cond_value, then_block, else_block); 731 732 // Compile then branch (= branch1) 733 CompileBlock((*it)->fBranch1, then_block); 734 LLVMBuildBr(fBuilder, merge_block); 735 736 // Compile else branch (= branch2) 737 CompileBlock((*it)->fBranch2, else_block); 738 LLVMBuildBr(fBuilder, merge_block); 739 740 // Insert in merge_block 741 LLVMPositionBuilderAtEnd(fBuilder, merge_block); 742 743 it++; 744 break; 745 } 746 747 /* 748 This could be implemented using a PHY node (to group the result of the 'then' and 'else' blocks) 749 but is more complicated to do when hierarchical 'select' are compiled. 750 751 Thus we create a local variable that is written in 'then' and 'else' blocks, 752 and loaded in the 'merge' block. 753 754 LLVM passes will later one create a unique PHY node that groups all results, 755 especially when hierarchical 'select' are compiled. 756 */ 757 case FBCInstruction::kSelectInt: { 758 // Create typed local variable 759 createSelectBlock1(it, LLVMBuildAlloca(fAllocaBuilder, getInt32Ty(), "select_int")); 760 it++; 761 break; 762 } 763 764 case FBCInstruction::kSelectReal: { 765 // Create typed local variable 766 createSelectBlock1(it, LLVMBuildAlloca(fAllocaBuilder, getRealTy(), "select_real")); 767 it++; 768 break; 769 } 770 771 case FBCInstruction::kCondBranch: { 772 // Prepare condition: compare condition to 0 773 LLVMValueRef cond_value = LLVMBuildICmp(fBuilder, LLVMIntNE, popValue(), genInt32(0), ""); 774 775 LLVMValueRef function = LLVMGetBasicBlockParent(LLVMGetInsertBlock(fBuilder)); 776 LLVMBasicBlockRef next_block = LLVMAppendBasicBlock(function, "next_block"); 777 778 // Branch to current block 779 LLVMBuildCondBr(fBuilder, cond_value, code_block, next_block); 780 781 // Insert in next_block 782 LLVMPositionBuilderAtEnd(fBuilder, next_block); 783 784 it++; 785 break; 786 } 787 788 case FBCInstruction::kLoop: { 789 790 // Get enclosing function 791 LLVMValueRef function = LLVMGetBasicBlockParent(LLVMGetInsertBlock(fBuilder)); 792 793 LLVMBasicBlockRef init_block = LLVMAppendBasicBlock(function, "init_block"); 794 LLVMBasicBlockRef loop_body_block = LLVMAppendBasicBlock(function, "loop_body_block"); 795 796 // Link previous_block and init_block 797 LLVMBuildBr(fBuilder, init_block); 798 799 // Compile init branch (= branch1) 800 CompileBlock((*it)->fBranch1, init_block); 801 802 // Link previous_block and loop_body_block 803 LLVMBuildBr(fBuilder, loop_body_block); 804 805 // Compile loop branch (= branch2) 806 CompileBlock((*it)->fBranch2, loop_body_block); 807 808 it++; 809 break; 810 } 811 812 default: 813 (*it)->write(&std::cout); 814 faustassert(false); 815 break; 816 } 817 } 818 } 819 820 public: FBCLLVMCompiler(FBCBlockInstruction<REAL> * fbc_block)821 FBCLLVMCompiler(FBCBlockInstruction<REAL>* fbc_block) 822 { 823 fLLVMStackIndex = 0; 824 fAddrStackIndex = 0; 825 826 LLVMInitializeCore(LLVMGetGlobalPassRegistry()); 827 828 /* 829 LLVMInitializeTransformUtils(LLVMGetGlobalPassRegistry()); 830 LLVMInitializeScalarOpts(LLVMGetGlobalPassRegistry()); 831 LLVMInitializeObjCARCOpts(LLVMGetGlobalPassRegistry()); 832 LLVMInitializeVectorization(LLVMGetGlobalPassRegistry()); 833 LLVMInitializeInstCombine(LLVMGetGlobalPassRegistry()); 834 LLVMInitializeIPO(LLVMGetGlobalPassRegistry()); 835 LLVMInitializeInstrumentation(LLVMGetGlobalPassRegistry()); 836 LLVMInitializeAnalysis(LLVMGetGlobalPassRegistry()); 837 LLVMInitializeIPA(LLVMGetGlobalPassRegistry()); 838 LLVMInitializeCodeGen(LLVMGetGlobalPassRegistry()); 839 LLVMInitializeTarget(LLVMGetGlobalPassRegistry()); 840 */ 841 842 fBuilder = LLVMCreateBuilder(); 843 fAllocaBuilder = LLVMCreateBuilder(); 844 845 fModule = LLVMModuleCreateWithName(FAUSTVERSION); 846 char* triple = LLVMGetDefaultTargetTriple(); 847 LLVMSetTarget(fModule, triple); 848 849 // Compile compute function 850 LLVMTypeRef param_types[] = {LLVMPointerType(getInt32Ty(), 0), LLVMPointerType(getRealTy(), 0), 851 LLVMPointerType(LLVMPointerType(getRealTy(), 0), 0), 852 LLVMPointerType(LLVMPointerType(getRealTy(), 0), 0)}; 853 854 LLVMTypeRef execute_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false); 855 LLVMValueRef execute = LLVMAddFunction(fModule, "execute", execute_type); 856 857 LLVMBasicBlockRef alloca_block = LLVMAppendBasicBlock(execute, "alloca_block"); 858 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(execute, "entry_block"); 859 860 // Always insert alloca in the alloca_block 861 LLVMPositionBuilderAtEnd(fAllocaBuilder, alloca_block); 862 863 fLLVMIntHeap = LLVMGetParam(execute, 0); 864 fLLVMRealHeap = LLVMGetParam(execute, 1); 865 fLLVMInputs = LLVMGetParam(execute, 2); 866 fLLVMOutputs = LLVMGetParam(execute, 3); 867 868 #if defined(LLVM_50) || defined(LLVM_60) 869 LLVMSetValueName(fLLVMIntHeap, "int_heap"); 870 LLVMSetValueName(fLLVMRealHeap, "real_heap"); 871 LLVMSetValueName(fLLVMInputs, "inputs"); 872 LLVMSetValueName(fLLVMOutputs, "outputs"); 873 #else 874 LLVMSetValueName2(fLLVMIntHeap, "int_heap", 8); 875 LLVMSetValueName2(fLLVMRealHeap, "real_heap", 9); 876 LLVMSetValueName2(fLLVMInputs, "inputs", 6); 877 LLVMSetValueName2(fLLVMOutputs, "outputs", 7); 878 #endif 879 880 // fbc_block->write(&std::cout); 881 882 // Compile compute body 883 CompileBlock(fbc_block, entry_block); 884 885 // Add return 886 LLVMBuildRetVoid(fBuilder); 887 888 // Link alloca_block and entry_block 889 LLVMPositionBuilderAtEnd(fBuilder, alloca_block); 890 LLVMBuildBr(fBuilder, entry_block); 891 892 // LLVMDumpModule(fModule); 893 894 // For host target support 895 LLVMLinkInMCJIT(); 896 LLVMInitializeNativeTarget(); 897 LLVMInitializeNativeAsmPrinter(); 898 LLVMInitializeNativeAsmParser(); 899 900 char* error; 901 LLVMCreateJITCompilerForModule(&fJIT, fModule, LLVMCodeGenLevelAggressive, &error); 902 903 /* 904 // Setup optimizations 905 LLVMPassManagerBuilderRef pass_buider = LLVMPassManagerBuilderCreate(); 906 LLVMPassManagerBuilderSetOptLevel(pass_buider, 3); 907 LLVMPassManagerBuilderSetSizeLevel(pass_buider, 0); 908 909 LLVMPassManagerRef function_passes = LLVMCreateFunctionPassManagerForModule(fModule); 910 911 LLVMPassManagerBuilderPopulateFunctionPassManager(pass_buider, function_passes); 912 913 LLVMAddSLPVectorizePass(function_passes); 914 LLVMAddSLPVectorizePass(function_passes); 915 916 LLVMPassManagerRef module_passes = LLVMCreatePassManager(); 917 LLVMPassManagerBuilderPopulateModulePassManager(pass_buider, module_passes); 918 919 LLVMInitializeFunctionPassManager(function_passes); 920 LLVMRunFunctionPassManager(function_passes, execute); 921 LLVMFinalizeFunctionPassManager(function_passes); 922 923 LLVMRunPassManager(module_passes, fModule); 924 925 LLVMDisposePassManager(function_passes); 926 LLVMDisposePassManager(module_passes); 927 LLVMPassManagerBuilderDispose(pass_buider); 928 */ 929 930 //LLVMDumpModule(fModule); 931 932 // Get 'execute' entry point 933 fCompiledFun = (compiledFun)LLVMGetFunctionAddress(fJIT, "execute"); 934 935 LLVMDisposeMessage(triple); 936 } 937 ~FBCLLVMCompiler()938 virtual ~FBCLLVMCompiler() 939 { 940 LLVMDisposeBuilder(fBuilder); 941 LLVMDisposeBuilder(fAllocaBuilder); 942 // fModule is deallocated by fJIT 943 LLVMDisposeExecutionEngine(fJIT); 944 LLVMShutdown(); 945 } 946 Execute(int * int_heap,REAL * real_heap,REAL ** inputs,REAL ** outputs)947 void Execute(int* int_heap, REAL* real_heap, REAL** inputs, REAL** outputs) 948 { 949 fCompiledFun(int_heap, real_heap, inputs, outputs); 950 } 951 }; 952 953 #endif 954