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