ç®æ¬¡ïŒ
ããŒã1ïŒã¯ããã«ãšåå¥è§£æããŒã2ïŒããŒãµãŒãšASTã®å®è£
ããŒã3ïŒLLVM IRã³ãŒãçæããŒã4ïŒJITããã³ãªããã£ãã€ã¶ãŒãµããŒãã®è¿œå ããŒã5ïŒèšèªæ¡åŒµïŒå¶åŸ¡ãããŒããŒã6ïŒèšèªæ¡åŒµïŒãŠãŒã¶ãŒå®çŸ©æŒç®åããŒã7ïŒèšèªæ¡åŒµïŒå¯å€å€æ°ããŒã8ïŒãªããžã§ã¯ãã³ãŒããžã®ã³ã³ãã€ã«ããŒã9ïŒãããã°æ
å ±ã®è¿œå ããŒã10ïŒçµè«ãšãã®ä»ã®LLVMã®å©ç¹
6.1ã ã¯ããã«
ã¬ã€ããLLVMã䜿çšããããã°ã©ãã³ã°èšèªã®äœæãã®ç¬¬6ç« ã«ããããã ãã®æç¹ã§ãæå°éã§ã¯ãããŸãããããã§ã䟿å©ãªå®å
šã«æ©èœããèšèªãã§ããŸããã ãããããŸã 1ã€ã®åé¡ããããŸããã ãã®èšèªã«ã¯æçšãªæŒç®åã¯ã»ãšãã©ãããŸããïŒããšãã°ããããå°ãããæ¯èŒæŒç®åãé€ããŠãé€ç®ãè«çåŠå®ãããã³æ¯èŒãããããŸããïŒã
ç§ãã¡ã®èšèªã§ããäžè¯é¡ã¯ã·ã³ãã«ã§çŸãããã®ã§ããããã®ç« ã§ã¯ãããã®ååããéžè±ããŠããŸãã ãªããªãŒãã¯ãã·ã³ãã«ã§ããããããªãããã®æ¹æ³ã§ãããã匷åãªèšèªãååŸããããšã§ãã ç¬èªã®èšèªãäœæããããšã®çŽ æŽãããç¹ã®1ã€ã¯ãäœãè¯ãããäœãæªãããæ±ºããããšã§ãã ãã®ã¬ã€ãã§ã¯ãããã¯æ£åžžã§ãããããã€ãã®è峿·±ãè§£æææ³ã瀺ãããšã決å®ããŸããã
ãã®ç« ã®æåŸã§ã¯ãå€ãã®ãã³ãã«ããã衚瀺ããäžè¯é¡ã®ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ãèŠãŠãããŸãã ããã¯ãäžè¯é¡èšèªãšãã®æ©èœã»ããã§ã§ããããšã®äŸã§ãã
6.2ã ãŠãŒã¶ãŒå®çŸ©ã®æŒç®åïŒéèŠãªèãæ¹
Kaleidoscopeã§å°å
¥ãããæŒç®åã®ãªãŒããŒããŒããã¯ãC ++ãªã©ã®èšèªãããäžè¬åãããŠããŸãã C ++ã§ã¯ãæ¢åã®æŒç®åã®ã¿ãåå®çŸ©ã§ããŸããããã°ã©ã ã§æ§æã倿Žããããæ°ããæŒç®åãå°å
¥ããããåªå
床ã¬ãã«ã倿Žãããããããšã¯ã§ããŸããã ãã®ç« ã§ã¯ãããããã¹ãŠã®æ©èœãKaleidoscopeã«è¿œå ããŸããããã«ããããŠãŒã¶ãŒã¯ãµããŒããããŠãããªãã¬ãŒã¿ãŒã®ã»ãããèªåã§æ±ºå®ã§ããŸãã
ãã®ã¬ã€ãã§ãŠãŒã¶ãŒå®çŸ©æŒç®åãèŠãç®çã¯ãããã€ãã£ããããŒãµãŒã䜿çšããããšã®èœåãšæè»æ§ã瀺ãããšã§ãã ç§ãã¡ãè¡ã£ãããŒãµãŒã¯ãã»ãšãã©ã®ææ³ã§ååž°äžéã䜿çšããåŒã®åªå
é äœãæã€æ§æè§£ææŒç®åã䜿çšããŸãïŒ
ããŒã2ãåç
§ïŒã åªå
é äœä»ãã®æ§æè§£ææŒç®åã䜿çšãããšãããã°ã©ããŒãæ°ããæŒç®åãææ³ã«ç°¡åã«å°å
¥ã§ããŸããJITãå®è¡ãããšãææ³ãåçã«æ¡åŒµãããŸãã
远å ãã2ã€ã®ç¹å®ã®æ©èœã¯ãåé
æŒç®åïŒçŸåšãKaleidoscopeã«ã¯åé
æŒç®åããããŸããïŒãšäºé
æŒç®åã§ãã äŸïŒ
# . def unary!(v) if v then 0 else 1; # > , <. def binary> 10 (LHS RHS) RHS < LHS; # " " def binary| 5 (LHS RHS) if LHS then 1 else if RHS then 1 else 0; # = , . def binary= 9 (LHS RHS) !(LHS < RHS | LHS > RHS);
å€ãã®èšèªã¯ãèšèªèªäœã«æšæºã©ã€ãã©ãªã®æ©èœãå®è£
ããããšããŠããŸãã ã«ã¬ã€ãã¹ã³ãŒãèšèªã§ã¯ãã©ã€ãã©ãªã®åœ¢ã§èšèªã®éèŠãªéšåãå®è£
ã§ããŸãïŒ
ãããã®æ©èœã®å®è£
ã¯ãã«ã¹ã¿ã ãã€ããªæŒç®åãšåé
æŒç®åã®ãµããŒãã®å®è£
ãšãã2ã€ã®éšåã«åå²ããŸãã
6.3ã ãŠãŒã¶ãŒå®çŸ©ã®äºé
æŒç®å
ãã¬ãŒã ã¯ãŒã¯ã«ãŠãŒã¶ãŒå®çŸ©ã®ãã€ããªæŒç®åã®ãµããŒãã远å ããã®ã¯éåžžã«ç°¡åã§ãã ãŸããããŒã¯ãŒããåé
ãããã³ããã€ããªãã®ãµããŒãã远å ããŸãã
enum Token { ...
ãã®ã³ãŒãã¯ãåã®éšåã§è¡ã£ãæ¹æ³ãšåæ§ã«ããåé
ãããã³ããã€ããªãããŒã¯ãŒãã®ãµããŒããåå¥ã¢ãã©ã€ã¶ã«è¿œå ããŸãã ASTå®è£
ã®è¯ãç¹ã®1ã€ã¯ãASCIIã³ãŒãããªãã³ãŒããšããŠäœ¿çšããŠããã€ããªæŒç®åãå®å
šã«äžè¬åãããã®ãšããŠæç€ºããããšã§ãã 远å ã®æŒç®åã«ã€ããŠã¯ãåã衚çŸã䜿çšããŸããASTãããŒãµãŒããã®è¿œå ãµããŒãã¯å¿
èŠãããŸããã
äžæ¹ããããã®æ°ããæŒç®åã®å®çŸ©ã颿°å®çŸ©ãšããŠè¡šãããšãã§ããŸãã ææ³ã§ã¯ã颿°ã®å®çŸ©ã®ãååãã¯é¢æ°ãããã¿ã€ãã®åºåãšããŠè§£æãããPrototypeASTåã®ASTããŒãã«ãªããŸãã æ°ãããŠãŒã¶ãŒå®çŸ©æŒç®åããããã¿ã€ããšããŠæç€ºããã«ã¯ãPrototypeASTããŒããæ¬¡ã®ããã«æ¡åŒµããå¿
èŠããããŸãã
äžçªäžã®è¡ã¯ãããç¥ããããããã¿ã€ãã®ååã«å ããŠããããæŒç®åã§ãã£ããã©ããããããããªãããããã©ã®åªå
床ã¬ãã«ã§ãããã«é¢ããæ
å ±ãä¿åãããšããããšã§ãã åªå
床ã¬ãã«ã¯äºé
æŒç®åã«ã®ã¿äœ¿çšãããŸãïŒåŸã§èª¬æããŸãããåé
æŒç®åã«ã¯é©çšãããŸããïŒã ããã§ããŠãŒã¶ãŒãªãã¬ãŒã¿ãŒã®ãããã¿ã€ããè¡šãæ¹æ³ãã§ããŸããããããè§£æã§ããããã«ããå¿
èŠããããŸãã
ããªãç°¡åãªæ§æè§£æã³ãŒãã§ã以åã«ãåæ§ã®ã³ãŒããããããèŠãŸããã ãã®ã³ãŒãã®è峿·±ãéšåã®1ã€ã¯ãFnNameã2é
æŒç®åã«å²ãåœãŠãããŠãã2ã3è¡ã§ãã ãŠãŒã¶ãŒæŒç®åã@ãã®å Žåããããã¿ã€ãã«ã¯ãbinary @ããšããååãä»ããããŸãã LLVMã·ã³ãã«ããŒãã«ã®ã·ã³ãã«åã«ãã«ãå«ãä»»æã®æåã䜿çšã§ãããšããäºå®ã®å©ç¹ãããã«ç€ºããŸãã
次ã«è¿œå ããè峿·±ãããšã¯ããã€ããªæŒç®åã®ã³ãŒãçæãµããŒãã§ãã æ¢åã®æ§é ã§ã¯ãããã¯åã«æ¢åã®ãã€ããªæŒç®åããŒãã«ãããã©ã«ããã远å ããã ãã§ãã
Value *BinaryExprAST::codegen() { Value *L = LHS->codegen(); Value *R = RHS->codegen(); if (!L || !R) return nullptr; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp");
äžèšã§ãããããã«ãæ°ããã³ãŒãã¯éåžžã«åçŽã§ãã ã·ã³ãã«ããŒãã«ã§é©åãªã¹ããŒãã¡ã³ããèŠã€ããŠãããã«å¯Ÿãã颿°åŒã³åºããçæããŸãã ãŠãŒã¶ãŒæã¯éåžžã®é¢æ°ãšåæ§ã«å®è£
ãããããããã¹ãŠãé©åã«é
眮ãããŸãã
å¿
èŠãªæåŸã®ã³ãŒãã¯ãé«ã¬ãã«ã®éæ³ã§ãã
Function *FunctionAST::codegen() {
颿°ã³ãŒããçæããåã«ãããããŠãŒã¶ãŒå®çŸ©ã®æŒç®åã§ããå Žåãåªå
床ããŒãã«ã«ç»é²ããŸãã ããã«ããããã§ã«ãããã€ããªæŒç®åã®è§£æããžãã¯ãæŒç®åãåŠçã§ããŸãã æŒç®åã®åªå
é äœãæã€å®å
šã«äžè¬åãããããŒãµãŒãéçºããŠãããããææ³ãæ¡åŒµããå¿
èŠããããŸãã
ãŠãŒã¶ãŒå®çŸ©ã®äºé
æŒç®åãã§ããŸããã ãããã¯äž»ã«ãä»ã®ãªãã¬ãŒã¿ãŒåãã«äœæãããã¬ãŒã ã¯ãŒã¯ã«åºã¥ããŠæ§ç¯ãããŠããŸãã åé
æŒç®åã®è¿œå ã¯ããå°ãè€éã«ãªããŸããããã«ã¯ãŸã ãã¬ãŒã ã¯ãŒã¯ããªãããã§ãã æ¹æ³ãèŠãŠã¿ãŸãããã
6.4ã ãŠãŒã¶ãŒå®çŸ©ã®åé
æŒç®å
Kaleidoscopeèšèªã®åé
æŒç®åã¯ãŸã ãµããŒããããŠããªãããããµããŒãã远å ããå¿
èŠããããŸãã äžèšã§ã¯ãåå¥ã¢ãã©ã€ã¶ã«ãåé
ãããŒã¯ãŒãã®ç°¡åãªãµããŒãã远å ããŸããã æ¬¡ã«ãASTããŒããå¿
èŠã§ãã
ASTããŒãã¯éåžžã«ã·ã³ãã«ã§æçœã§ãã åã1ã€ããããšãé€ãã°ã2é
æŒç®åã®ASTããŒãã«äŒŒãŠããŸãã æ¬¡ã«ãè§£æããžãã¯ã远å ããå¿
èŠããããŸãã åé
æŒç®åã®è§£æã¯éåžžã«ç°¡åã§ãããããè¡ã颿°ã远å ããŸãã
ããã§è¿œå ããææ³ã¯éåžžã«åçŽã§ãã ãã©ã€ããªæŒç®åãè§£æãããšãã«åé
æŒç®åãèŠã€ãã£ãå Žåããã®æŒç®åããã¬ãã£ãã¯ã¹ãšããŠäœ¿çšããæ®ãã®éšåãå¥ã®åé
æŒç®åãšããŠè§£æããŸãã ããã«ãããè€æ°ã®åé
æŒç®åïŒã!! xããªã©ïŒãåŠçã§ããŸãã åé
æŒç®åã¯ãäºé
æŒç®åã®ããã«ææ§ãªè§£æãè¡ãããšãã§ãããåªå
床æ
å ±ãå¿
èŠãšããªãããšã«æ³šæããŠãã ããã
ãã®é¢æ°ã®åé¡ã¯ãã©ãããã§ãParseUnaryãåŒã³åºãå¿
èŠãããå Žåãããããšã§ãã ãããè¡ãã«ã¯ãParsePrimaryã®ä»¥åã®åŒã³åºããParseUnaryã«çœ®ãæããŸãã
ããã2ã€ã®ç°¡åãªå€æŽã«ãããåé
æŒç®åãè§£æãããããã®ASTãæ§ç¯ã§ããããã«ãªããŸããã æ¬¡ã«ããããã¿ã€ãã®ããŒãµãŒãµããŒãã远å ããŠãåé
æŒç®åã®ãããã¿ã€ããè§£æããå¿
èŠããããŸãã äžèšã®ãã€ããªæŒç®åã³ãŒããæ¬¡ã®ããã«æ¡åŒµããŸãã
äºé
æŒç®åãšåæ§ã«ãåé
æŒç®åãæŒç®åèšå·ãå«ãååãšåŒã³ãŸãã ããã¯ãã³ãŒããçæãããšãã«åœ¹ç«ã¡ãŸãã æ¬¡ã«ãåé
æŒç®åã®ã³ãŒãçæãµããŒãã远å ããå¿
èŠããããŸãã æ¬¡ã®ããã«ãªããŸãã
Value *UnaryExprAST::codegen() { Value *OperandV = Operand->codegen(); if (!OperandV) return nullptr; Function *F = getFunction(std::string("unary") + Opcode); if (!F) return LogErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); }
ã³ãŒãã¯ãã€ããªæŒç®åã®å®è£
ã«äŒŒãŠããŸãããäž»ã«åªå
床ã®ãµããŒããå¿
èŠãšããªããããããã·ã³ãã«ã§ãã
6.5ã ã¿ã€ã€ã蹎ã
ä¿¡ããããã§ãããæåŸã®éšåã§èª¬æããããã€ãã®ç°¡åãªæ¡åŒµæ©èœãå°å
¥ããããšã§ãå®éã®èšèªãæé·ãããŸããã I / Oãæ°åŠããã®ä»å€ãã®ããšãå«ããå€ãã®è峿·±ãããšãã§ããŸãã ããšãã°ãã·ãŒã±ã³ã¹æŒç®åãå
¥åã§ããŸãïŒprintd颿°ã¯åŒæ°ã®å€ã衚瀺ããæååã翻蚳ããŸãïŒïŒ
ready> extern printd(x); Read extern: declare double @printd(double) ready> def binary : 1 (xy) 0; # , ... ready> printd(123) : printd(456) : printd(789); 123.000000 456.000000 789.000000 Evaluated to 0.000000
ãŸããæ¬¡ã®ãããªå€ãã®ãåçŽãªãæŒç®åãå®çŸ©ããããšãã§ããŸãã
# def unary!(v) if v then 0 else 1; # . def unary-(v) 0-v; # > , <. def binary> 10 (LHS RHS) RHS < LHS; # "" def binary| 5 (LHS RHS) if LHS then 1 else if RHS then 1 else 0; # "" def binary& 6 (LHS RHS) if !LHS then 0 else !!RHS; # = , def binary = 9 (LHS RHS) !(LHS < RHS | LHS > RHS); # ':' : , # RHS. def binary : 1 (xy) y;
if / then / elseãµããŒããå©çšããŠãè峿·±ãI / O颿°ãå®çŸ©ã§ããŸãã ããšãã°ã次ã®ã³ãŒãã¯ãæž¡ãããå€ããå¯åºŠããåæ ããæåã衚瀺ããŸããå€ãå°ããã»ã©ãæåã¯æ¿ããªããŸãã
ready> extern putchard(char); ... ready> def printdensity(d) if d > 8 then putchard(32) # ' ' else if d > 4 then putchard(46) # '.' else if d > 2 then putchard(43) # '+' else putchard(42); # '*' ... ready> printdensity(1): printdensity(2): printdensity(3): printdensity(4): printdensity(5): printdensity(9): putchard(10); **++. Evaluated to 0.000000
ãããã®ç°¡åãªæäœã«åºã¥ããŠãããè峿·±ããã®ãå®çŸ©ãå§ããããšãã§ããŸãã ããšãã°ã颿°ãè€çŽ å¹³é¢ã§çºæ£ããååŸ©åæ°ãæ±ºå®ããå°ããªé¢æ°ã¯æ¬¡ã®ãšããã§ãã
# , # z = z^2 + c def mandelconverger(real imag iters creal cimag) if iters > 255 | (real*real + imag*imag > 4) then iters else mandelconverger(real*real - imag*imag + creal, 2*real*imag + cimag, iters+1, creal, cimag); # def mandelconverge(real imag) mandelconverger(real, imag, 0, real, imag);
ãã®é¢æ°ïŒz = z2 + cïŒã¯çŸããå°ããªçãç©ã§ã
ãã³ãã«ããéåãèšç®ããããã®åºç€ã§ãã ç§ãã¡ã®mandelconverge颿°ã¯ãè€éãªè»éãç¡éã«è¡ãå¿
èŠãããååŸ©åæ°ãè¿ããŸãã ãã®é¢æ°ã¯255ã®å€ã§ã飜åãããŸãããã®é¢æ°èªäœã¯ããŸãæçšã§ã¯ãããŸãããããã®å€ã2次å
å¹³é¢ã«ãããããããšãå€ãã®ãã³ãã«ããã衚瀺ãããŸãã ããã§ã¯putchard颿°ã®äœ¿çšã«å¶éãããŠããããããã°ãããã°ã©ãã£ãã¯åºåãå¶éãããŠããŸãããäžèšã®ãå¯åºŠãåºå颿°ã䜿çšã§ããŸãã
# # def mandelhelp(xmin xmax xstep ymin ymax ystep) for y = ymin, y < ymax, ystep in ( (for x = xmin, x < xmax, xstep in printdensity(mandelconverge(x,y))) : putchard(10) ) # mandel - # def mandel(realstart imagstart realmag imagmag) mandelhelp(realstart, realstart+realmag*78, realmag, imagstart, imagstart+imagmag*40, imagmag);
ããã§ãå€ãã®ãã³ãã«ããã®æ§ç¯ã詊ã¿ãããšãã§ããŸãã
å±éããready> mandel(-2.3, -1.3, 0.05, 0.07);
*******************************+++++++++++*************************************
*************************+++++++++++++++++++++++*******************************
**********************+++++++++++++++++++++++++++++****************************
*******************+++++++++++++++++++++.. ...++++++++*************************
*****************++++++++++++++++++++++.... ...+++++++++***********************
***************+++++++++++++++++++++++..... ...+++++++++*********************
**************+++++++++++++++++++++++.... ....+++++++++********************
*************++++++++++++++++++++++...... .....++++++++*******************
************+++++++++++++++++++++....... .......+++++++******************
***********+++++++++++++++++++.... ... .+++++++*****************
**********+++++++++++++++++....... .+++++++****************
*********++++++++++++++........... ...+++++++***************
********++++++++++++............ ...++++++++**************
********++++++++++... .......... .++++++++**************
*******+++++++++..... .+++++++++*************
*******++++++++...... ..+++++++++*************
*******++++++....... ..+++++++++*************
*******+++++...... ..+++++++++*************
*******.... .... ...+++++++++*************
*******.... . ...+++++++++*************
*******+++++...... ...+++++++++*************
*******++++++....... ..+++++++++*************
*******++++++++...... .+++++++++*************
*******+++++++++..... ..+++++++++*************
********++++++++++... .......... .++++++++**************
********++++++++++++............ ...++++++++**************
*********++++++++++++++.......... ...+++++++***************
**********++++++++++++++++........ .+++++++****************
**********++++++++++++++++++++.... ... ..+++++++****************
***********++++++++++++++++++++++....... .......++++++++*****************
************+++++++++++++++++++++++...... ......++++++++******************
**************+++++++++++++++++++++++.... ....++++++++********************
***************+++++++++++++++++++++++..... ...+++++++++*********************
*****************++++++++++++++++++++++.... ...++++++++***********************
*******************+++++++++++++++++++++......++++++++*************************
*********************++++++++++++++++++++++.++++++++***************************
*************************+++++++++++++++++++++++*******************************
******************************+++++++++++++************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
Evaluated to 0.000000
ready> mandel(-2, -1, 0.02, 0.04);
**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
***********++++++++++++++++++++++++++++++++++++++++++++++++++........ .
**********++++++++++++++++++++++++++++++++++++++++++++++.............
********+++++++++++++++++++++++++++++++++++++++++++..................
*******+++++++++++++++++++++++++++++++++++++++.......................
******+++++++++++++++++++++++++++++++++++...........................
*****++++++++++++++++++++++++++++++++............................
*****++++++++++++++++++++++++++++...............................
****++++++++++++++++++++++++++...... .........................
***++++++++++++++++++++++++......... ...... ...........
***++++++++++++++++++++++............
**+++++++++++++++++++++..............
**+++++++++++++++++++................
*++++++++++++++++++.................
*++++++++++++++++............ ...
*++++++++++++++..............
*+++....++++................
*.......... ...........
*
*.......... ...........
*+++....++++................
*++++++++++++++..............
*++++++++++++++++............ ...
*++++++++++++++++++.................
**+++++++++++++++++++................
**+++++++++++++++++++++..............
***++++++++++++++++++++++............
***++++++++++++++++++++++++......... ...... ...........
****++++++++++++++++++++++++++...... .........................
*****++++++++++++++++++++++++++++...............................
*****++++++++++++++++++++++++++++++++............................
******+++++++++++++++++++++++++++++++++++...........................
*******+++++++++++++++++++++++++++++++++++++++.......................
********+++++++++++++++++++++++++++++++++++++++++++..................
Evaluated to 0.000000
ready> mandel(-0.9, -1.4, 0.02, 0.03);
*******************************************************************************
*******************************************************************************
*******************************************************************************
**********+++++++++++++++++++++************************************************
*+++++++++++++++++++++++++++++++++++++++***************************************
+++++++++++++++++++++++++++++++++++++++++++++**********************************
++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
+++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
+++++++++++++++++++++++++++++++.... ......+++++++++++++++++++****************
+++++++++++++++++++++++++++++....... ........+++++++++++++++++++**************
++++++++++++++++++++++++++++........ ........++++++++++++++++++++************
+++++++++++++++++++++++++++......... .. ...+++++++++++++++++++++**********
++++++++++++++++++++++++++........... ....++++++++++++++++++++++********
++++++++++++++++++++++++............. .......++++++++++++++++++++++******
+++++++++++++++++++++++............. ........+++++++++++++++++++++++****
++++++++++++++++++++++........... ..........++++++++++++++++++++++***
++++++++++++++++++++........... .........++++++++++++++++++++++*
++++++++++++++++++............ ...........++++++++++++++++++++
++++++++++++++++............... .............++++++++++++++++++
++++++++++++++................. ...............++++++++++++++++
++++++++++++.................. .................++++++++++++++
+++++++++.................. .................+++++++++++++
++++++........ . ......... ..++++++++++++
++............ ...... ....++++++++++
.............. ...++++++++++
.............. ....+++++++++
.............. .....++++++++
............. ......++++++++
........... .......++++++++
......... ........+++++++
......... ........+++++++
......... ....+++++++
........ ...+++++++
....... ...+++++++
....+++++++
.....+++++++
....+++++++
....+++++++
....+++++++
Evaluated to 0.000000
ready> ^D
ãã®æ®µéã§ã¯ãäžè¯é¡ãå®éã®åŒ·åãªèšèªãšèŠãªãããšãã§ããŸãã èªå·±çžäŒŒã§ã¯ãããŸãã:)ãããã®ãããªãã®ãæãããã«äœ¿çšã§ããŸãïŒ
ããã§ãã¬ã€ãã®ããŠãŒã¶ãŒå®çŸ©ã¹ããŒãã¡ã³ãã®è¿œå ãã®éšåã¯çµããã§ãã ã©ã€ãã©ãªã䜿çšããŠèšèªãæ¡åŒµããæ©èœã远å ããããšã§èšèªãæ£åžžã«è£å®ããããã䜿çšããŠã«ã¬ã€ãã¹ã³ãŒãèšèªã§ã·ã³ãã«ã ãè峿·±ããŠãŒã¶ãŒã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããæ¹æ³ã瀺ããŸããã ãã®æ®µéã§ã¯ãäžè¯é¡ã§ãå¯äœçšã®ãã颿°ãåŒã³åºãããšã¯ã§ããŸããã倿°èªäœãå®çŸ©ããã³å€æŽããããšã¯ã§ããŸããããŸããŸãªã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã
å³å¯ã«èšãã°ãå¯å€å€æ°ã¯äžéšã®èšèªã®éèŠãªæ©èœã§ãããSSAèšè𿮵éãããã³ããšã³ãã«å°å
¥ããã«ãããã®ãµããŒãã远å ããæ¹æ³ã¯æããã§ã¯ãããŸããã æ¬¡ã®ããŒãã§ã¯ãSSAãæ§ç¯ããã«å¯å€å€æ°ãããã³ããšã³ãã«è¿œå ããæ¹æ³ã«ã€ããŠèª¬æããŸãã
6.6ã å®å
šãªã³ãŒããªã¹ã
以äžã¯ããŠãŒã¶ãŒå®çŸ©ã¹ããŒãã¡ã³ãã®ãµããŒãã§æ¡åŒµããããäœæ¥äŸã®ã³ãŒãã®å®å
šãªãªã¹ãã§ãã
çµã¿ç«ãŠäŸïŒ
äžéšã®ãã©ãããã©ãŒã ã§ã¯ã-rdynamicãŸãã¯-Wlã-export-dynamicãšãªã³ã¯ããå¿
èŠããããŸãã æ¬¡ã«ãå®è¡å¯èœãã¡ã€ã«ã§å®çŸ©ãããæåãåçãªã³ã«ãŒã«ãšã¯ã¹ããŒããããå®è¡æã«äœ¿çšå¯èœã«ãªããŸãã ãµããŒãã³ãŒããå
±æã©ã€ãã©ãªã«ã³ã³ãã€ã«ããå Žåãããã¯å¿
èŠãããŸããããããã¯Windowsã§åé¡ãåŒãèµ·ããå¯èœæ§ããããŸãã
ã³ãŒãïŒ
ãã£ãã¿ãŒã³ãŒã #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" #include "../include/KaleidoscopeJIT.h" #include <algorithm> #include <cassert> #include <cctype> #include <cstdint> #include <cstdio> #include <cstdlib> #include <map> #include <memory> #include <string> #include <vector> using namespace llvm; using namespace llvm::orc; //===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// // [0-255] , // enum Token { tok_eof = -1, // tok_def = -2, tok_extern = -3, // tok_identifier = -4, tok_number = -5, // tok_if = -6, tok_then = -7, tok_else = -8, tok_for = -9, tok_in = -10, // tok_binary = -11, tok_unary = -12 }; static std::string IdentifierStr; // tok_identifier static double NumVal; // tok_number /// gettok - static int gettok() { static int LastChar = ' '; // while (isspace(LastChar)) LastChar = getchar(); if (isalpha(LastChar)) { // : [a-zA-Z][a-zA-Z0-9]* IdentifierStr = LastChar; while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; if (IdentifierStr == "def") return tok_def; if (IdentifierStr == "extern") return tok_extern; if (IdentifierStr == "if") return tok_if; if (IdentifierStr == "then") return tok_then; if (IdentifierStr == "else") return tok_else; if (IdentifierStr == "for") return tok_for; if (IdentifierStr == "in") return tok_in; if (IdentifierStr == "binary") return tok_binary; if (IdentifierStr == "unary") return tok_unary; return tok_identifier; } if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; LastChar = getchar(); } while (isdigit(LastChar) || LastChar == '.'); NumVal = strtod(NumStr.c_str(), nullptr); return tok_number; } if (LastChar == '#') { // do LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); if (LastChar != EOF) return gettok(); } // . EOF. if (LastChar == EOF) return tok_eof; // , ascii-. int ThisChar = LastChar; LastChar = getchar(); return ThisChar; } //===----------------------------------------------------------------------===// // ( ) //===----------------------------------------------------------------------===// namespace { /// ExprAST - . class ExprAST { public: virtual ~ExprAST() = default; virtual Value *codegen() = 0; }; /// NumberExprAST - "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} Value *codegen() override; }; /// VariableExprAST - , , "a". class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(const std::string &Name) : Name(Name) {} Value *codegen() override; }; /// UnaryExprAST - class UnaryExprAST : public ExprAST { char Opcode; std::unique_ptr<ExprAST> Operand; public: UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand) : Opcode(Opcode), Operand(std::move(Operand)) {} Value *codegen() override; }; /// BinaryExprAST - class BinaryExprAST : public ExprAST { char Op; std::unique_ptr<ExprAST> LHS, RHS; public: BinaryExprAST(char Op, std::unique_ptr<ExprAST> LHS, std::unique_ptr<ExprAST> RHS) : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} Value *codegen() override; }; /// CallExprAST - class CallExprAST : public ExprAST { std::string Callee; std::vector<std::unique_ptr<ExprAST>> Args; public: CallExprAST(const std::string &Callee, std::vector<std::unique_ptr<ExprAST>> Args) : Callee(Callee), Args(std::move(Args)) {} Value *codegen() override; }; /// IfExprAST - if/then/else. class IfExprAST : public ExprAST { std::unique_ptr<ExprAST> Cond, Then, Else; public: IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then, std::unique_ptr<ExprAST> Else) : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} Value *codegen() override; }; /// ForExprAST - for/in. class ForExprAST : public ExprAST { std::string VarName; std::unique_ptr<ExprAST> Start, End, Step, Body; public: ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start, std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step, std::unique_ptr<ExprAST> Body) : VarName(VarName), Start(std::move(Start)), End(std::move(End)), Step(std::move(Step)), Body(std::move(Body)) {} Value *codegen() override; }; /// PrototypeAST - "" , /// , (, , /// , ), . class PrototypeAST { std::string Name; std::vector<std::string> Args; bool IsOperator; unsigned Precedence; // Precedence if a binary op. public: PrototypeAST(const std::string &Name, std::vector<std::string> Args, bool IsOperator = false, unsigned Prec = 0) : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), Precedence(Prec) {} Function *codegen(); const std::string &getName() const { return Name; } bool isUnaryOp() const { return IsOperator && Args.size() == 1; } bool isBinaryOp() const { return IsOperator && Args.size() == 2; } char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); return Name[Name.size() - 1]; } unsigned getBinaryPrecedence() const { return Precedence; } }; /// FunctionAST - class FunctionAST { std::unique_ptr<PrototypeAST> Proto; std::unique_ptr<ExprAST> Body; public: FunctionAST(std::unique_ptr<PrototypeAST> Proto, std::unique_ptr<ExprAST> Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} Function *codegen(); }; } // //===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// /// CurTok/getNextToken - . CurTok - /// , . getNextToken /// CurTok . static int CurTok; static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - , /// static std::map<char, int> BinopPrecedence; /// GetTokPrecedence - . static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; // , int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; } /// Error* - . std::unique_ptr<ExprAST> LogError(const char *Str) { fprintf(stderr, "Error: %s\n", Str); return nullptr; } std::unique_ptr<PrototypeAST> LogErrorP(const char *Str) { LogError(Str); return nullptr; } static std::unique_ptr<ExprAST> ParseExpression(); /// numberexpr ::= number static std::unique_ptr<ExprAST> ParseNumberExpr() { auto Result = llvm::make_unique<NumberExprAST>(NumVal); getNextToken(); // return std::move(Result); } /// parenexpr ::= '(' expression ')' static std::unique_ptr<ExprAST> ParseParenExpr() { getNextToken(); // (. auto V = ParseExpression(); if (!V) return nullptr; if (CurTok != ')') return LogError("expected ')'"); getNextToken(); // ). return V; } /// identifierexpr /// ::= identifier /// ::= identifier '(' expression* ')' static std::unique_ptr<ExprAST> ParseIdentifierExpr() { std::string IdName = IdentifierStr; getNextToken(); // . if (CurTok != '(') // return llvm::make_unique<VariableExprAST>(IdName); // Call. getNextToken(); // ( std::vector<std::unique_ptr<ExprAST>> Args; if (CurTok != ')') { while (true) { if (auto Arg = ParseExpression()) Args.push_back(std::move(Arg)); else return nullptr; if (CurTok == ')') break; if (CurTok != ',') return LogError("Expected ')' or ',' in argument list"); getNextToken(); } } // ')'. getNextToken(); return llvm::make_unique<CallExprAST>(IdName, std::move(Args)); } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static std::unique_ptr<ExprAST> ParseIfExpr() { getNextToken(); // eat the if. // auto Cond = ParseExpression(); if (!Cond) return nullptr; if (CurTok != tok_then) return LogError("expected then"); getNextToken(); // then auto Then = ParseExpression(); if (!Then) return nullptr; if (CurTok != tok_else) return LogError("expected else"); getNextToken(); auto Else = ParseExpression(); if (!Else) return nullptr; return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then), std::move(Else)); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static std::unique_ptr<ExprAST> ParseForExpr() { getNextToken(); // for. if (CurTok != tok_identifier) return LogError("expected identifier after for"); std::string IdName = IdentifierStr; getNextToken(); // if (CurTok != '=') return LogError("expected '=' after for"); getNextToken(); // '='. auto Start = ParseExpression(); if (!Start) return nullptr; if (CurTok != ',') return LogError("expected ',' after for start value"); getNextToken(); auto End = ParseExpression(); if (!End) return nullptr; // std::unique_ptr<ExprAST> Step; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); if (!Step) return nullptr; } if (CurTok != tok_in) return LogError("expected 'in' after for"); getNextToken(); // eat 'in'. auto Body = ParseExpression(); if (!Body) return nullptr; return llvm::make_unique<ForExprAST>(IdName, std::move(Start), std::move(End), std::move(Step), std::move(Body)); } /// primary /// ::= identifierexpr /// ::= numberexpr /// ::= parenexpr /// ::= ifexpr /// ::= forexpr static std::unique_ptr<ExprAST> ParsePrimary() { switch (CurTok) { default: return LogError("unknown token when expecting an expression"); case tok_identifier: return ParseIdentifierExpr(); case tok_number: return ParseNumberExpr(); case '(': return ParseParenExpr(); case tok_if: return ParseIfExpr(); case tok_for: return ParseForExpr(); } } /// unary /// ::= primary /// ::= '!' unary static std::unique_ptr<ExprAST> ParseUnary() { // , . if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); // , int Opc = CurTok; getNextToken(); if (auto Operand = ParseUnary()) return llvm::make_unique<UnaryExprAST>(Opc, std::move(Operand)); return nullptr; } /// binoprhs /// ::= ('+' unary)* static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS) { // , while (true) { int TokPrec = GetTokPrecedence(); // , // , if (TokPrec < ExprPrec) return LHS; // , int BinOp = CurTok; getNextToken(); // eat binop // auto RHS = ParseUnary(); if (!RHS) return nullptr; // BinOp RHS, RHS, // RHS LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { RHS = ParseBinOpRHS(TokPrec + 1, std::move(RHS)); if (!RHS) return nullptr; } // LHS/RHS. LHS = llvm::make_unique<BinaryExprAST>(BinOp, std::move(LHS), std::move(RHS)); } } /// expression /// ::= unary binoprhs /// static std::unique_ptr<ExprAST> ParseExpression() { auto LHS = ParseUnary(); if (!LHS) return nullptr; return ParseBinOpRHS(0, std::move(LHS)); } /// prototype /// ::= id '(' id* ')' /// ::= binary LETTER number? (id, id) /// ::= unary LETTER (id) static std::unique_ptr<PrototypeAST> ParsePrototype() { std::string FnName; unsigned Kind = 0; // 0 = , 1 = , 2 = . unsigned BinaryPrecedence = 30; switch (CurTok) { default: return LogErrorP("Expected function name in prototype"); case tok_identifier: FnName = IdentifierStr; Kind = 0; getNextToken(); break; case tok_unary: getNextToken(); if (!isascii(CurTok)) return LogErrorP("Expected unary operator"); FnName = "unary"; FnName += (char)CurTok; Kind = 1; getNextToken(); break; case tok_binary: getNextToken(); if (!isascii(CurTok)) return LogErrorP("Expected binary operator"); FnName = "binary"; FnName += (char)CurTok; Kind = 2; getNextToken(); // , if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) return LogErrorP("Invalid precedence: must be 1..100"); BinaryPrecedence = (unsigned)NumVal; getNextToken(); } break; } if (CurTok != '(') return LogErrorP("Expected '(' in prototype"); std::vector<std::string> ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return LogErrorP("Expected ')' in prototype"); // . getNextToken(); // eat ')'. // , if (Kind && ArgNames.size() != Kind) return LogErrorP("Invalid number of operands for operator"); return llvm::make_unique<PrototypeAST>(FnName, ArgNames, Kind != 0, BinaryPrecedence); } /// definition ::= 'def' prototype expression static std::unique_ptr<FunctionAST> ParseDefinition() { getNextToken(); // eat def. auto Proto = ParsePrototype(); if (!Proto) return nullptr; if (auto E = ParseExpression()) return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); return nullptr; } /// toplevelexpr ::= expression static std::unique_ptr<FunctionAST> ParseTopLevelExpr() { if (auto E = ParseExpression()) { // auto Proto = llvm::make_unique<PrototypeAST>("__anon_expr", std::vector<std::string>()); return llvm::make_unique<FunctionAST>(std::move(Proto), std::move(E)); } return nullptr; } /// external ::= 'extern' prototype static std::unique_ptr<PrototypeAST> ParseExtern() { getNextToken(); // eat extern. return ParsePrototype(); } //===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// static LLVMContext TheContext; static IRBuilder<> Builder(TheContext); static std::unique_ptr<Module> TheModule; static std::map<std::string, Value *> NamedValues; static std::unique_ptr<legacy::FunctionPassManager> TheFPM; static std::unique_ptr<KaleidoscopeJIT> TheJIT; static std::map<std::string, std::unique_ptr<PrototypeAST>> FunctionProtos; Value *LogErrorV(const char *Str) { LogError(Str); return nullptr; } Function *getFunction(std::string Name) { // , , . if (auto *F = TheModule->getFunction(Name)) return F; // I , // . auto FI = FunctionProtos.find(Name); if (FI != FunctionProtos.end()) return FI->second->codegen(); // , null. return nullptr; } Value *NumberExprAST::codegen() { return ConstantFP::get(TheContext, APFloat(Val)); } Value *VariableExprAST::codegen() { // , Value *V = NamedValues[Name]; if (!V) return LogErrorV("Unknown variable name"); return V; } Value *UnaryExprAST::codegen() { Value *OperandV = Operand->codegen(); if (!OperandV) return nullptr; Function *F = getFunction(std::string("unary") + Opcode); if (!F) return LogErrorV("Unknown unary operator"); return Builder.CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::codegen() { Value *L = LHS->codegen(); Value *R = RHS->codegen(); if (!L || !R) return nullptr; switch (Op) { case '+': return Builder.CreateFAdd(L, R, "addtmp"); case '-': return Builder.CreateFSub(L, R, "subtmp"); case '*': return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // bool 0/1 double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: break; } // , . // . Function *F = getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); Value *Ops[] = {L, R}; return Builder.CreateCall(F, Ops, "binop"); } Value *CallExprAST::codegen() { // Function *CalleeF = getFunction(Callee); if (!CalleeF) return LogErrorV("Unknown function referenced"); // , . if (CalleeF->arg_size() != Args.size()) return LogErrorV("Incorrect # arguments passed"); std::vector<Value *> ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->codegen()); if (!ArgsV.back()) return nullptr; } return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::codegen() { Value *CondV = Cond->codegen(); if (!CondV) return nullptr; // 0.0. CondV = Builder.CreateFCmpONE( CondV, ConstantFP::get(TheContext, APFloat(0.0)), "ifcond"); Function *TheFunction = Builder.GetInsertBlock()->getParent(); // then else. 'then' // BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else"); BasicBlock *MergeBB = BasicBlock::Create(TheContext, "ifcont"); Builder.CreateCondBr(CondV, ThenBB, ElseBB); // . Builder.SetInsertPoint(ThenBB); Value *ThenV = Then->codegen(); if (!ThenV) return nullptr; Builder.CreateBr(MergeBB); // 'Then' , ThenBB PHI. ThenBB = Builder.GetInsertBlock(); // "else" TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); if (!ElseV) return nullptr; Builder.CreateBr(MergeBB); // 'Else' , ElseBB PHI. ElseBB = Builder.GetInsertBlock(); // TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, "iftmp"); PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; } // for-loop : // ... // start = startexpr // goto loop // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr // ... // loopend: // step = stepexpr // nextvariable = variable + step // endcond = endexpr // br endcond, loop, endloop // outloop: Value *ForExprAST::codegen() { // , . Value *StartVal = Start->codegen(); if (!StartVal) return nullptr; // , // Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); BasicBlock *LoopBB = BasicBlock::Create(TheContext, "loop", TheFunction); // LoopBB. Builder.CreateBr(LoopBB); // LoopBB. Builder.SetInsertPoint(LoopBB); // PHI . PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(TheContext), 2, VarName); Variable->addIncoming(StartVal, PreheaderBB); // , PHI. // , , . Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; // . , , // BB. , , , // . if (!Body->codegen()) return nullptr; // Value *StepVal = nullptr; if (Step) { StepVal = Step->codegen(); if (!StepVal) return nullptr; } else { // , 1.0. StepVal = ConstantFP::get(TheContext, APFloat(1.0)); } Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); // Value *EndCond = End->codegen(); if (!EndCond) return nullptr; // 0.0. EndCond = Builder.CreateFCmpONE( EndCond, ConstantFP::get(TheContext, APFloat(0.0)), "loopcond"); // " " BasicBlock *LoopEndBB = Builder.GetInsertBlock(); BasicBlock *AfterBB = BasicBlock::Create(TheContext, "afterloop", TheFunction); // LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); // AfterBB. Builder.SetInsertPoint(AfterBB); // PHI. Variable->addIncoming(NextVar, LoopEndBB); // . if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); // 0.0. return Constant::getNullValue(Type::getDoubleTy(TheContext)); } Function *PrototypeAST::codegen() { // : double(double,double) etc. std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule.get()); // unsigned Idx = 0; for (auto &Arg : F->args()) Arg.setName(Args[Idx++]); return F; } Function *FunctionAST::codegen() { // FunctionProtos, // . auto &P = *Proto; FunctionProtos[Proto->getName()] = std::move(Proto); Function *TheFunction = getFunction(P.getName()); if (!TheFunction) return nullptr; // , if (P.isBinaryOp()) BinopPrecedence[P.getOperatorName()] = P.getBinaryPrecedence(); // BasicBlock *BB = BasicBlock::Create(TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB); // NamedValues. NamedValues.clear(); for (auto &Arg : TheFunction->args()) NamedValues[Arg.getName()] = &Arg; if (Value *RetVal = Body->codegen()) { // Builder.CreateRet(RetVal); // verifyFunction(*TheFunction); // TheFPM->run(*TheFunction); return TheFunction; } // , TheFunction->eraseFromParent(); if (P.isBinaryOp()) BinopPrecedence.erase(P.getOperatorName()); return nullptr; } //===----------------------------------------------------------------------===// // JIT //===----------------------------------------------------------------------===// static void InitializeModuleAndPassManager() { // TheModule = llvm::make_unique<Module>("my cool jit", TheContext); TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout()); // TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get()); // "peephole"-. TheFPM->add(createInstructionCombiningPass()); // TheFPM->add(createReassociatePass()); // TheFPM->add(createGVNPass()); // ( ..). TheFPM->add(createCFGSimplificationPass()); TheFPM->doInitialization(); } static void HandleDefinition() { if (auto FnAST = ParseDefinition()) { if (auto *FnIR = FnAST->codegen()) { fprintf(stderr, "Read function definition:"); FnIR->print(errs()); fprintf(stderr, "\n"); TheJIT->addModule(std::move(TheModule)); InitializeModuleAndPassManager(); } } else { // getNextToken(); } } static void HandleExtern() { if (auto ProtoAST = ParseExtern()) { if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); FnIR->print(errs()); fprintf(stderr, "\n"); FunctionProtos[ProtoAST->getName()] = std::move(ProtoAST); } } else { // getNextToken(); } } static void HandleTopLevelExpression() { // if (auto FnAST = ParseTopLevelExpr()) { if (FnAST->codegen()) { // JIT , // auto H = TheJIT->addModule(std::move(TheModule)); InitializeModuleAndPassManager(); // JIT __anon_expr auto ExprSymbol = TheJIT->findSymbol("__anon_expr"); assert(ExprSymbol && "Function not found"); // ( // , double) . double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress()); fprintf(stderr, "Evaluated to %f\n", FP()); // JIT. TheJIT->removeModule(H); } } else { // getNextToken(); } } /// top ::= definition | external | expression | ';' static void MainLoop() { while (true) { fprintf(stderr, "ready> "); switch (CurTok) { case tok_eof: return; case ';': // getNextToken(); break; case tok_def: HandleDefinition(); break; case tok_extern: HandleExtern(); break; default: HandleTopLevelExpression(); break; } } } //===----------------------------------------------------------------------===// // "" , //===----------------------------------------------------------------------===// #ifdef LLVM_ON_WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif /// putchard - putchar, double, 0. extern "C" DLLEXPORT double putchard(double X) { fputc((char)X, stderr); return 0; } /// printd - printf, double "%f\n", 0. extern "C" DLLEXPORT double printd(double X) { fprintf(stderr, "%f\n", X); return 0; } //===----------------------------------------------------------------------===// // main //===----------------------------------------------------------------------===// int main() { InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); // // 1 - BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; BinopPrecedence['*'] = 40; // highest. // fprintf(stderr, "ready> "); getNextToken(); TheJIT = llvm::make_unique<KaleidoscopeJIT>(); InitializeModuleAndPassManager(); // MainLoop(); return 0; }