
LLVMãšã¯
LLVMã¯ãCãC ++ãªã©ã®åŸæ¥ã®ããã°ã©ãã³ã°èšèªã®éã¢ã»ã³ãã«ãšã¢ã»ã³ãã«ã®ããã®æ¬åœã«ãåæã®ãã³ã³ãã€ã©ã§ãã
LLVMã¯éåžžã«åªããŠããããããåãªãã³ã³ãã€ã©ä»¥äžã®ãã®ããšèŠãªãããŸãïŒåçã³ã³ãã€ã©ã§ãããCãã¡ããªã«å±ããªãèšèªã§åäœããApp Storeãªã©ã®æ°ããé 信圢åŒãè¡šããŸã ïŒã äžèšã¯ãã¹ãŠçå®ã§ããããã®èšäºã§ã¯ãäžèšã®å®çŸ©ã®ã¿ãéèŠã§ãã
LLVMã«ã¯ãä»ã®ã³ã³ãã€ã©ãšããã€ãã®éèŠãªéãããããŸãã
- äž»ãªé©æ°ã¯ãäžéãã¬ãŒã³ããŒã·ã§ã³ïŒPPïŒã§ãã LLVMã¯ãå®éã«èªã¿åãããšãã§ãããœãããŠã§ã¢ã§åäœããŸãïŒã¢ã»ã³ããªã³ãŒããèªã¿åãããšãã§ããå ŽåïŒã 誰ã«ãšã£ãŠãããã»ã©å€§ããªå瀺ã®ããã«æããªããããããŸãããããã®ç¹æ§ã¯éåžžã«éèŠã§ãã ä»ã®ã³ã³ãã€ã©ã®ãœãããŠã§ã¢ã¯éåžžãè€éãªæ§é ãæã£ãŠãããããæåã§äœæããããšã¯ã§ãããç解ããŠäœ¿çšããããšã¯å°é£ã§ãã
- LLVMã¯éåžžã«ãšã¬ã¬ã³ãã«æžãããŠããŸãããã®ã¢ãŒããã¯ãã£ã¯ä»ã®ã³ã³ãã€ã©ãããã¢ãžã¥ãŒã«åãããŠããŸãã ãã®ç¶äºã®çç±ã®1ã€ã¯ããªãªãžãã«ããŒãžã§ã³ã®éçºè ãç§ãã¡ã®1人ã ã£ãããšã§ãã
- LLVMã¯ãç§ãã¡ã®ãããªã¢ã«ãããã¯ããã«ãŒã«ãšã£ãŠå¥œãŸããç 究ããŒã«ã§ããã ãã§ãªããäžçæ倧ã®äŒæ¥ã®èåŸã«ããæ¥çã¬ãã«ã®ã³ã³ãã€ã©ãŒã§ããããŸãã ããã¯ãåªããã³ã³ãã€ã©ãŒãšã«ã¹ã¿ã ã³ã³ãã€ã©ãŒã®éã§åŠ¥åããå¿ èŠããªãããšãæå³ããŸãïŒJavaã©ã³ãã§HotSpotãšJikesãéžæããå Žåã«çºçããŸãïŒã
ãªãLLVMç 究è ãªã®ãïŒ
LLVMã¯çŽ æŽãããããŒã«ã§ãã ããããããªãã®ç 究ãã³ã³ãã€ã©ã«é¢ãããã®ã§ã¯ãªãå Žåãäœãæ°ã«ããŸããïŒ
ã³ã³ãã€ã©ã€ã³ãã©ã¹ãã©ã¯ãã£ã«ãããããã°ã©ã ã§å€ãã®èå³æ·±ãããšãã§ããŸãã ããšãã°ãããã°ã©ã ãåæããŠãç¹å®ã®ã¢ã¯ã·ã§ã³ãå®è¡ããé »åºŠãææ¡ã§ããŸãã ç¹å®ã®ã·ã¹ãã ã§åäœããããã«ããã°ã©ã ãå€æã§ããŸãã ãŸããããã°ã©ã ãå€æŽããŠãæ°ãããããããŸã äœæãããŠããªãããã«ãŒãã«ã¢ãžã¥ãŒã«ãæžã蟌ãŸããŠããªãä»®æ³ã®æ°ããã¢ãŒããã¯ãã£ãŸãã¯OSã䜿çšããæ¹æ³ãæ³åããããšãã§ããŸãã ã³ã³ãã€ã©ã€ã³ãã©ã¹ãã©ã¯ãã£ã¯ãå€ãã®äººãèãããããã¯ããã«é »ç¹ã«ç 究è ã«åœ¹ç«ã€ããšããããŸãã ãããã®ããŒã«ã®ããããããã¡ã€ã«ããããšããåã«ãLLVMã«æåã«é£çµ¡ããããšããå§ãããŸãïŒç¹å¥ãªçç±ããªãéãïŒã
- 建ç¯ã·ãã¥ã¬ãŒã¿ ;
- åçãªãã€ããªã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ã¯ãããšãã°ã Pinãæå³ããŸãã
- ãœãŒã¹ã³ãŒãã¬ãã«ã§ã®å€æïŒsedãªã©ã®åçŽãªããŒã«ãããASDã®åæãšã·ãªã¢ã«åãå«ãé«åºŠãªããŒã«ããããžïŒ;
- ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããã«ãŒãã«ããã¡ã€ã«ããŸãã
- ãã€ããŒãã€ã¶ãŒã®ããã«èŠããããŒã«ã
ã³ã³ãã€ã©ãããªãã®ã¿ã¹ã¯ã«å®ç§ãªãœãªã¥ãŒã·ã§ã³ã®ããã«èŠããªããŠããããšãã°ããããœãŒã¹ã³ãŒããå¥ã®ãœãŒã¹ã³ãŒãã«å€æãããšããªã©ãäœæ¥ã®90ïŒ ãä¿é²ããããšããããããŸãã
以äžã¯ãã³ã³ãã€ã©ã«ããŸã䌌ãŠããªãç 究ãããžã§ã¯ãã®è¯ãäŸã§ãã
- ã€ãªãã€å€§åŠã¢ãŒããã·ã£ã³ããŒã³æ ¡ïŒç±³åœïŒ ã®ããŒãã£ã«ãŽãŒã¹ã㯠ãã³ã³ãã€ã©ãã¹ã䜿çšããŠããããã³ã°ãããOSã«ãŒãã«ããããã»ã¹ãä¿è·ããæ¹æ³ã瀺ããŠããŸãã
- ã¯ã·ã³ãã³å€§åŠïŒç±³åœïŒã®CoreDetã¯ããã«ãã¹ã¬ããããã°ã©ã ã決å®è«çã«ããŸãã
- æŠç®ã§ã¯ãLLVMãã¹ã䜿çšããŠããã°ã©ã ã«ãã°ãè¿œå ããé害ãçºçããããããŒããŠã§ã¢ã®ããã©ãŒãã³ã¹ãã·ãã¥ã¬ãŒãããŸãã
LLVMã¯ãã³ã³ãã€ã©ã§æ°ããæé©åãéçºããããã«èšèšãããŠããã ãã§ã¯ãããŸããã
詳现
次ã®å³ã¯ãLLVMã¢ãŒããã¯ãã£ã®äž»èŠã³ã³ããŒãã³ãïŒããã³ææ°ã®ã³ã³ãã€ã©ã®äžè¬çãªã¢ãŒããã¯ãã£ïŒã瀺ããŠããŸãã
- ããã³ããšã³ãã¯ãœãŒã¹ã³ãŒãã解æããäžéè¡šçŸïŒPPïŒã«å€æããŸãã ããã«ãããéåžžã«è€éãªC ++ãœãŒã¹ã³ãŒããããã€ãžã§ã¹ããããã®ãé£ãããæ®ãã®ã³ã³ãã€ã©ã®äœæ¥ãç°¡çŽ åãããŸãã ããªãã®ãããªå€§èäžæµãªç 究è ã¯ããããããã®éšåã§äœãçµããå¿ èŠã¯ãªãã®ã§ãå€æŽããã«Clangã䜿çšã§ããŸãã
- éè·¯ã¯1ã€ã®PPãå¥ã®PPã«å€æããŸãã éåžžã®ç¶æ³ã§ã¯ãããã»ãŒãžã¯ã³ãŒããæé©åããŸããã€ãŸããåºåã§ãå ¥åã«æäŸããããœãããŠã§ã¢ãšåããœãããŠã§ã¢ãå®è¡ããŸãããããé«éã«ãªããŸãã äœããçµãããããã®ã¯ããã§ãã ãªããžã§ã³ã¯ãããšãã°ãã³ã³ãã€ã©ãééãããœãããŠã§ã¢ãèªã¿åã£ãŠå€æŽã§ããŸãã
- ããã¯ãšã³ãã¯ãã·ã³ã³ãŒããçŽæ¥çæããŸãã ã»ãšãã©ã®å Žåãã·ã¹ãã ã®ãã®éšåã§äœãå€æŽããå¿ èŠã¯ãããŸããã
- LLVMã®ã¢ãŒããã¯ãã£ã¯ãã»ãšãã©ã®ææ°ã®ã³ã³ãã€ã©ã®ã¢ãŒããã¯ãã£ã«å¯Ÿå¿ããŠããŸããã1ã€ã®ã€ãããŒã·ã§ã³ã«æ³šæããŠãã ãããåãã¹ã§ç¬èªã®åœ¢åŒã®ããã°ã©ã ã³ãŒããäœæãããä»ã®ã³ã³ãã€ã©ãšã¯ç°ãªããLLVMã§ã¯ããã»ã¹å šäœã§åããœãããŠã§ã¢ã䜿çšãããŸãã ããã¯ãããã«ãŒã«ãšã£ãŠçæ³çã§ããããã³ããšã³ããšããã¯ãšã³ãã®éã§ã³ãŒããå®è¡ãããå Žåãããã»ã¹ã®ã©ã®æ®µéã§ã³ãŒããå®è¡ãããããå¿é ããå¿ èŠã¯ãããŸããã
ä»äºã®æºå
ããã§ã¯ãäœããåãäžããŸãããã
LLVMãã€ã³ã¹ããŒã«ãã
ãŸããLLVMãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã Linuxãã£ã¹ããªãã¥ãŒã·ã§ã³ã«ã¯ãå€ãã®å Žåãå®å šã«äœ¿çšã§ããLLVMããã³Clangããã±ãŒãžãå«ãŸããŠããŸãã çµæã®ããŒãžã§ã³ã«ãã³ã³ãã€ã©ãŒã䜿çšããŠããã°ã©ã ãçµäºããããã«å¿ èŠãªããããŒããã¹ãŠå«ãŸããŠããããšã確èªããŠãã ããã ããšãã°ã Xcodeã«å梱ãããŠããOS Xãã«ãã¯å®å šã§ã¯ãããŸããã ãããããCMakeã䜿çšããŠãœãŒã¹ããLLVMãã³ã³ãã€ã«ããã®ã¯ç°¡åã§ãã éåžžãLLVMèªäœãæ§ç¯ããã ãã§ãã OSã«ä»å±ã®Clangã¯ã察å¿ããããŒãžã§ã³ãäžèŽããå Žåã«ãã®ã¿ã¹ã¯ã«å¯ŸåŠããŸãïŒãã ãã Clangã®ãã«ãæé ããããŸãïŒã
ç¹ã«ãBrandon Holtã¯OS Xåãã®è¯ãæ瀺ãæžããŠãããHomebrewã·ã¹ãã ã®ã¬ã·ãããããŸã ã
ææãåŠã¶
ããã¥ã¡ã³ãã泚ææ·±ã調ã¹ãå¿ èŠããããŸãã ç§ã®æèŠã§ã¯ã次ã®è³æãç¹ã«åœ¹ç«ã¡ãŸãã
- éåžžã«éèŠãªæ å ±ã¯ã èªåçæãããDoxygenããŒãžã«å«ãŸããŠããŸã ã LLVMã䜿çšããŠããã°ã©ã ãæ£åžžã«éžæããæ¹æ³ãåŠç¿ããã«ã¯ããããã®ããã¥ã¡ã³ãã®äžã§APIã«ãã£ãŠé·ãé解決ããå¿ èŠããããŸãã ãã ããããŒãžéã移åããè€éããèãããšãæ å ±ããã°ãŒã°ã«æ€çŽ¢ãããããšããå§ãããŸãã é¢æ°ãŸãã¯ã¯ã©ã¹åã«ãLLVMããè¿œå ãããšã éåžž ãGoogle ã¯å¿ èŠãªDoxygenããŒãžãæ€çŽ¢ããŸã ïŒè©ŠããŠã¿ããšããLLVMããšããååãå ¥åããªããŠããã³ã³ãã€ã©ã«é¢ããæ å ±ãæ€çŽ¢ããããGoogleããã¬ãŒãã³ã°ã§ããŸãïŒïŒ ããã¯ã°ãããŠããããã«èãããŸãããçãæ®ãããã«ã¯ãLLVM APIããã¥ã¡ã³ããäžå¿ã«ã¿ã³ããªã³ãšäžç·ã«èžããªããã°ãªããŸããã APIããã¥ã¡ã³ããããã²ãŒããããã䟿å©ãªæ¹æ³ããããããããŸããããèããããšã¯ãããŸããã
- LLVMãã«ã㯠ãPPã®æ§æã«ã€ããŠç解ããŠããªãå Žåã«åœ¹ç«ã¡ãŸãã
- ããã°ã©ããŒãºã¬ã€ãã§ã¯ãLLVMåºæã®ããŒã¿æ§é ïŒæå¹ãªæååããããã®ä»£æ¿STLããã¯ãã«ãªã©ïŒãæäœããããŒã«ãšã䜿çšããåïŒisaãcastãdyn_castïŒãæäœããããŒã«ã«ã€ããŠèª¬æããŠããŸããã©ãã§ãã
- ã·ã³ã°ã«ãã¹ã®å¯èœæ§ã«ã€ããŠè³ªåãããå Žåã¯ã LLVM Pass Writing Guideãåç §ããŠãã ããã ããªããã³ã³ãã€ã©ãéžã¶ã ãã§ãªãç 究è ã§ããããšãèãããšããã®èšäºã®èè ã¯ãã®ãã¥ãŒããªã¢ã«ã®ç¹å®ã®ãã€ã³ãã«åæããªãããšã«æ³šæããããšæããŸãã ïŒãŸããMakefileã䜿çšããŠã·ã¹ãã ãæ§ç¯ããããã®æ瀺ãç¡èŠãããœãŒã¹ããªãŒå€ã®æ§ç¯æ瀺ã«çŽæ¥ç§»åããŸããïŒãã ããäžè¬çã«ãããã¥ã¢ã«ã¯ãã¹æ å ±ã®æšæºçãªãœãŒã¹ã§ãã
- å Žåã«ãã£ãŠã¯ãLLVMãœãŒã¹ã³ãŒãã衚瀺ããããã®WebãªãœãŒã¹ã§ããGitHub mirrorã䜿çšãããšäŸ¿å©ã§ãã
éè·¯æžã
éåžžãLLVMã䜿çšããç 究ã®çµæã¯ãæ°ããæç« ãæžãããšã§ãã ãã®ã»ã¯ã·ã§ã³ã«ã¯ããªã³ã¶ãã©ã€ããã°ã©ã ãå€æããç°¡åãªãŠã©ãŒã¯ã¹ã«ãŒãçµã¿ç«ãŠãŠå®è¡ããããã®æé ãå«ãŸããŠããŸãã
ãã¹ã±ã«ãã³ã
ç¡é§ãªLLVMãã¹ã1ã€ãããã³ãã¬ãŒããªããžããªãäœæããŸãã ã ãã³ãã¬ãŒãããå§ããããšããå§ãããŸããæåããäœæããå Žåãã¢ã»ã³ããªã®æ§æã«åé¡ãããå¯èœæ§ãããããã§ãã
GitHubã§llvm-pass-skeletonãªããžããªãè€è£œããŸãã
$ git clone git@github.com:sampsyo/llvm-pass-skeleton.git
å®è³ªçãªäœæ¥ã¯skeleton / Skeleton.cppãã¡ã€ã«ã§è¡ããããããéããŠãã ããã ããã¯ãã¹ãŠãèµ·ããå Žæã§ãïŒ
virtual bool runOnFunction(Function &F) { errs() << "I saw a function called " << F.getName() << "!\n"; return false; }
LLVMãã¹ã«ã¯ããã€ãã®ã¿ã€ãããããŸãã ãã®ãã¡ã®1ã€ã䜿çšããŸã- é¢æ°ãã¹ ïŒåå¿è ã«æé©ã§ãïŒã äºæ³ã©ãããLLVMã¯ãã³ã³ãã€ã«äžã®ããã°ã©ã ã§èŠã€ãã£ãåé¢æ°ã«å¯ŸããŠäžèšã®ã¡ãœãããåŒã³åºããŸãã ãããŸã§ã®ãšãããã¡ãœããã¯é¢æ°ã®ååã®ã¿ã衚瀺ããŸãã
詳现ïŒ
- errsïŒïŒãšåŒã°ããèŠçŽ ã¯ãLLVMãæäŸããC ++åºåã¹ããªãŒã ã§ãã ã³ã³ãœãŒã«ãžã®åºåã«äœ¿çšãããŸãã
- ãã®é¢æ°ã¯falseãè¿ããFãå€æŽãããŠããªãããšã瀺ããŸããåŸã§PPã®å€æŽãéå§ãããšãã«ãtrueãè¿ãå¿ èŠããããŸãã
çµç«
CMakeã䜿çšããŠãã¹ãäœæããŸãã
$ cd llvm-pass-skeleton $ mkdir build $ cd build $ cmake .. # Generate the Makefile. $ make # Actually build the pass.
LLVMãã°ããŒãã«ã«ã€ã³ã¹ããŒã«ãããŠããªãå ŽåãCMakeã¯ãã®å Žæãæå®ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãLLVMãLLVM_DIRç°å¢å€æ°å ã«ããshare / llvm / cmake /ãã£ã¬ã¯ããªãŒãžã®ãã¹ãèšå®ããŸãã 以äžã¯ãHomebrewã·ã¹ãã ã®ãã¹ã®äŸã§ãã
$ LLVM_DIR=/usr/local/opt/llvm/share/llvm/cmake cmake ..
ã¢ã»ã³ããªã«ãããå ±æã©ã€ãã©ãªãäœæãããŸãã build / skeleton / libSkeletonPass.soãã¡ã€ã«ããŸãã¯äœ¿çšãããã©ãããã©ãŒã ã«å¿ããŠåæ§ã®ååã®ãã¡ã€ã«ã«ãããŸãã 次ã®ã¹ãããã§ã¯ããã®ã©ã€ãã©ãªãããŒãããŠãå®éã®ããã°ã©ã ã³ãŒãã®ãã¹ãå®è¡ããŸãã
éè·¯
ãã¹ãå®äºããã«ã¯ãåãåã£ãã°ããã®ã©ã€ãã©ãªã䜿çšããå¿ èŠãããããšã瀺ããã©ã°ã䜿çšããŠCããã°ã©ã ãã³ã³ãã€ã«ããŸãã
$ clang -Xclang -load -Xclang build/skeleton/libSkeletonPass.* something.c I saw a function called main!
-Xclang -load -Xclang path / to / lib.soããã·ãŒãžã£ã䜿çšãããã®ãã³ã¹ã¯ã Clangã§ããã»ãŒãžãããŒãããã³ã¢ã¯ãã£ãåããããã«å¿ èŠãªãã¹ãŠã§ãã ãããã£ãŠã倧èŠæš¡ãããžã§ã¯ãã§äœæ¥ããå Žåããããã®åŒæ°ãCFLAGS Makefileå€æ°ãªã¹ããŸãã¯ãã«ãã·ã¹ãã ã®å¯Ÿå¿ããåçç©ã«è¿œå ã§ããŸãã
ïŒããã«ãclangãå®è¡ããã«èªåã§ãã¹ãå®è¡ã§ããŸããLLVMoptã³ãã³ãã䜿çšãããã®æ¹æ³ã¯ãå ¬åŒããã¥ã¡ã³ãã§æšå¥šãããŠããŸã ããã ãããã®èšäºã§ã¯èª¬æããŸããïŒã
ããã§ãšãããããŸããã³ã³ãã€ã©ãå®æããŸããïŒ æ¬¡ã®ã¹ãããã§ã¯ããHelloãworldïŒãã¬ãã«ã®ããã»ãŒãžãããèå³æ·±ããã®ã«æ¹è¯ããæ¹æ³ãèŠãŠãããŸãã
LLVMäžéãã¥ãŒæ§é
LLVMã§ããã°ã©ã ãæäœããã«ã¯ããœãããŠã§ã¢ã®æ§é ãç解ããŠãããšããã§ãããã
ã¢ãžã¥ãŒã«ã«ã¯é¢æ°ãå«ãŸãããã®é¢æ°ã«ã¯åœä»€ãå«ãBasicBlocksãå«ãŸããŸãã Moduleãé€ããã¹ãŠã®ã¯ã©ã¹ã¯Valueãã掟çããŸãã
ã³ã³ãã
以äžã¯ãæãéèŠãªLLVMã³ã³ããŒãã³ãã®æŠèŠã§ãã
- ã¢ãžã¥ãŒã«ã¯ãåã«ãœãŒã¹ãã¡ã€ã«ïŒå€§ãŸãã«èšã£ãŠïŒãŸãã¯å€æåäœïŒå³å¯ã«ã¢ãããŒãããå ŽåïŒã§ãã ã¢ãžã¥ãŒã«ã«ã¯ãä»ã®ãã¹ãŠã®ãšã³ãã£ãã£ãå«ãŸããŸãã
- ãŸããã¢ãžã¥ãŒã«ã«ã¯ååã«å®å šã«å¯Ÿå¿ããå®è¡å¯èœã³ãŒãã®ååä»ããããã¯ã§ããé¢æ°ãå«ãŸããŸãïŒC ++ã®é¢æ°ãšã¡ãœããã®äž¡æ¹ãLLVMé¢æ°ã«å¯Ÿå¿ããŸãïŒã
- ååãšåŒæ°ã®å®£èšã«å ããŠãé¢æ°ã¯åºæ¬ãããã¯ïŒBasicBlockïŒã®ã³ã³ãããŒãšããŠæ©èœããŸãã ããŒã¹ãŠãããã¯ãã³ã³ãã€ã©çè«ããããªãã¿ã®æŠå¿µã§ãã ãã ãããã®èšäºã§ã¯ããããåã«åœä»€ã®é£ç¶ãããããã¯ãšèŠãªããŸãã
- åæ§ã«ãåœä»€ã¯ã³ãŒããæã€1ã€ã®æäœã§ãã ãã®æœè±¡åã¬ãã«ã¯ã RISCãã·ã³ã³ãŒããšã»ãŒåãã§ãã ããšãã°ãåœä»€ã¯æŽæ°ã®è¿œå ãæµ®åå°æ°ç¹ã«ããé€ç®ããŸãã¯ã¡ã¢ãªãžã®ä¿åã§ãã
ã»ãšãã©ã®LLVMãšã³ãã£ãã£ïŒé¢æ°ãããŒã¹ãããã¯ãããã³åœä»€ïŒã¯ããŠããã¿ã¹ValueããŒã¹ã¯ã©ã¹ãã掟çããC ++ã¯ã©ã¹ã§ãã å€ãšã¯ãèšç®ã§äœ¿çšã§ããããŒã¿ïŒæ°å€ãã³ãŒãã¢ãã¬ã¹ãªã©ïŒãããã³ã°ããŒãã«å€æ°ãšå®æ°ïŒããªãã©ã«ããŸãã¯ãã€ããã£ãšãŒãå€ããšããŠç¥ãããŠãã5ãªã©ïŒã§ãã
åæ±èª¬ææž
以äžã¯ã人éãèªãã圢åŒã®LLVMãœãããŠã§ã¢ã®åœä»€ã®äŸã§ãã
%5 = add i32 %4, 2
ãã®åœä»€ã¯ã2ã€ã®32ãããæ°ãå ç®ããŸãïŒi32ã¯ããã瀺ããŸãïŒã ã¬ãžã¹ã¿ãŒ4ïŒïŒ 4ãšã©ãã«ä»ãïŒã®æ°å€ãšå®æ°2ïŒå®éã«ã¯2ïŒã«æ°å€ãè¿œå ããçµæãã¬ãžã¹ã¿ãŒ5ã«æžã蟌ã¿ãŸããããã¯ãLLVMãœãããŠã§ã¢ãå®ç§ãªRISCãã·ã³ã³ãŒãã®ããã«èŠãããšããæå³ã§ãã ã¬ãžã¹ã¿ãªã©ã®åãçšèªã䜿çšããŸãããã¬ãžã¹ã¿ã®æ°ã¯ç¡éã§ãã
åãåœä»€ããC ++ åœä»€ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãšããŠã³ã³ãã€ã©ãŒå ã«æ瀺ãããŸãã ãªããžã§ã¯ãã«ã¯ããããè¿œå ã§ããããšã瀺ããªãã³ãŒããšãä»ã®Valueãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãšããŠæ©èœãããªãã©ã³ãã®ã¿ã€ããšãªã¹ãããããŸãã ãã®äŸã§ã¯ãæ°å€2ãè¡šãConstantãªããžã§ã¯ããæããå¥ã®åœä»€ãªããžã§ã¯ãïŒåœä»€ïŒãïŒ 5ã¬ãžã¹ã¿ã«å¯Ÿå¿ããŠããŸãã ïŒLLVMãéçãª1åéãã®å²ãåœãŠã®åœ¢åŒã§ãããšãããšãã¬ãžã¹ã¿ãšåœä»€ã¯å®éã«ã¯åãã§ããã¬ãžã¹ã¿çªå·ã¯ããã¹ãè¡šçŸã®ææç©ã§ããïŒ
ãšããã§ãããã°ã©ã ã®LLVMãœãããŠã§ã¢ãèŠããå Žåã¯ãClangã«åãåãããŠãã ããïŒ
$ clang -emit-llvm -S -o - something.c
ãã¹ã§äžéãã¥ãŒã確èªãã
äœæ¥äžã®LLVMãã¹ã«æ»ããŸãããã 䟿å©ãªäžè¬çãªdumpïŒïŒã¡ãœããã䜿çšããŠãPPã®ãã¹ãŠã®éèŠãªãªããžã§ã¯ãããã§ãã¯ã§ããŸãããã®ã¡ãœããã¯ãPPå ã®ãªããžã§ã¯ãã®èªã¿åãå¯èœãªè¡šçŸã衚瀺ããŸãã ãã¹ãåŠçäžã®åé¢æ°ã®Functionãªããžã§ã¯ããåãåããšãé¢æ°ã®åºæ¬ãããã¯ãšåãããã¯ã®åœä»€ã«1ã€ãã€ã¢ã¯ã»ã¹ããŸãã
ãããè¡ãã³ãŒãã次ã«ç€ºããŸãã llvm-pass-skeletonãªããžããªã®containersãã©ã³ãããååŸã§ããŸã ïŒ
errs() << "Function body:\n"; F.dump(); for (auto& B : F) { errs() << "Basic block:\n"; B.dump(); for (auto& I : B) { errs() << "Instruction: "; I.dump(); } }
C ++ 11ã®æŽŸæãªèªåããã³foreachã䜿çšãããšãLLVM PPéå±€ããã€ãã¹ããã®ã«äŸ¿å©ã§ãã
ãã¹ãåæ§ç¯ããŠå®è¡ãããšãåºåã«ç°ãªãLLVMãšã³ãã£ãã£ãééããé åºã§è¡šç€ºãããŸãã
ããã»ãŒãžã䜿çšããŠããè€éãªåé¡ã解決ãã
å®éã®å¥è·¡ã¯ãããã°ã©ã å ã®ãã¿ãŒã³ãæ€çŽ¢ããçºèŠãããåŸã«ã³ãŒããå€æŽãããšãã«çºçããŸãã ç°¡åãªäŸãèããŠã¿ãŸãããã åé¢æ°ã®æåã®2é æŒç®åïŒã+ããã-ããªã©ïŒãä¹ç®ã§çœ®ãæããããšããŸãã 圹ã«ç«ã€ãããããŸããããïŒ
ãããè¡ãã³ãŒãã次ã«ç€ºããŸãã ãã®ããŒãžã§ã³ãšãè©Šçšã§ããããã°ã©ã ã®äŸã¯ãLLVM gitãªããžããªã®mutateãã©ã³ãã§å ¥æã§ããŸã ã
for (auto& B : F) { for (auto& I : B) { if (auto* op = dyn_cast<BinaryOperator>(&I)) { // Insert at the point where the instruction `op` appears. IRBuilder<> builder(op); // Make a multiply with the same operands as `op`. Value* lhs = op->getOperand(0); Value* rhs = op->getOperand(1); Value* mul = builder.CreateMul(lhs, rhs); // Everywhere the old instruction was used as an operand, use our // new multiply instruction instead. for (auto& U : op->uses()) { User* user = U.getUser(); // A User is anything with operands. user->setOperand(U.getOperandNo(), mul); } // We modified the code. return true; } } }
詳现ïŒ
- dyn_castïŒpïŒã³ã³ã¹ãã©ã¯ãã¯LLVMåºæã§ãããåçã¿ã€ããã£ã¹ããå®è¡ããŸãã æ éã«èãæãããLLVMã¡ã«ããºã ã䜿çšããŠãåçãªåãã§ãã¯ãè¿ éã«å®è¡ããŸããã³ã³ãã€ã©ã¯åžžã«ãããã䜿çšããŸãã Iããã€ããªBinaryOperatoræŒç®åã§ã¯ãªãå Žåãã³ã³ã¹ãã©ã¯ãã¯NULLãã€ã³ã¿ãŒãè¿ããããã³ãŒãã®ããã«ç¹æ®ãªã±ãŒã¹ãåŠçããã®ã«çæ³çã§ãã
- IRBuilderã¯ãã³ãŒãããã«ãããããã«èšèšãããŠããŸãã å¿ èŠãªåœä»€ãäœæããããã®ç¡æ°ã®ã¡ãœãããæäŸããŸãã
- æ°ããåœä»€ãã³ãŒãã«åã蟌ãã«ã¯ã䜿çšããããã¹ãŠã®å ŽæãèŠã€ããŠããã®åœä»€ãåŒæ°ãšããŠæ¿å ¥ããå¿ èŠããããŸãã Instructionãå€ã§ããããšãæãåºããŠãã ããã ãã®å Žåãä¹ç®ã®åœä»€ã¯å¥ã®åœä»€ã®ãªãã©ã³ããšããŠäœ¿çšãããŸããã€ãŸããçµæã¯åŒæ°ã«ãªããŸãã
- ããã«ãå€ãåœä»€ãåé€ããå¿ èŠããããŸãã ãã ãã説æãç ©éã«ãªããªãããã«ããã®æé ã¯çç¥ããŸããã
ããã§ãããã°ã©ã ïŒãªããžããªå ã®example.c ïŒãã³ã³ãã€ã«ã§ããŸãã
#include <stdio.h> int main(int argc, const char** argv) { int num; scanf("%i", &num); printf("%i\n", num + 2); return 0; }
éåžžã®ã³ã³ãã€ã©ãŒã¯ã³ãŒãã«æåŸ ãããåäœãäžããã¢ãžã¥ãŒã«ã®æäœåŸã2ã2ã§ä¹ç®ãã代ããã«ã³ãŒããæäŸããŸãã
$ cc example.c $ ./a.out 10 12 $ clang -Xclang -load -Xclang build/skeleton/libSkeletonPass.so example.c $ ./a.out 10 20
éæ³ïŒ
ã©ã€ãã©ãªãšå®è¡å¯èœã³ãŒãã®ãªã³ã¯
äºçŽ°ãªããšãããªãããã«ã³ãŒããå€æŽããå¿ èŠãããå Žåã¯ã IRBuilderã䜿çšããŠå¿ èŠãªåœä»€ãçæããã®ã«å€å€§ãªåŽåããããå¯èœæ§ããããŸãã 代ããã«ãCã§ç®çã®åäœãå®è£ ããã³ã³ãã€ã«ãããããã°ã©ã ãšãªã³ã¯ã§ããŸãã ãã®ã»ã¯ã·ã§ã³ã§ã¯ããã€ããªæŒç®ã®çµæãéãã«å€æŽããã®ã§ã¯ãªããèšé²ããã©ã€ãã©ãªãèšè¿°ããæ¹æ³ã«ã€ããŠèª¬æããŸãã
llvm-pass-skeletonãªããžããªã®rtlibãã©ã³ãããååŸããããããè¡ãããã°ã©ã ã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
// Get the function to call from our runtime library. LLVMContext& Ctx = F.getContext(); Constant* logFunc = F.getParent()->getOrInsertFunction( "logop", Type::getVoidTy(Ctx), Type::getInt32Ty(Ctx), NULL ); for (auto& B : F) { for (auto& I : B) { if (auto* op = dyn_cast<BinaryOperator>(&I)) { // Insert *after* `op`. IRBuilder<> builder(op); builder.SetInsertPoint(&B, ++builder.GetInsertPoint()); // Insert a call to our function. Value* args[] = {op}; builder.CreateCall(logFunc, args); return true; } } }
å¿ èŠãªããŒã«ã¯ã Module :: getOrInsertFunctionããã³IRBuilder :: CreateCallã§ãã æåã®ã³ãŒãã¯ãCã³ãŒãã«void logopïŒint iïŒé¢æ°ã®å®£èšããããã®ããã«ãlogopé¢æ°ã«å®£èšãè¿œå ããŸãã äœãªãã ãã®è¿œå ããã宣èšã¯ãã©ã€ãã©ãªãŒïŒ ãªããžããªãŒã®rtlib.c ïŒã®logopé¢æ°ã®å®çŸ©ã«å¯Ÿå¿ããŠããŸãã
#include <stdio.h> void logop(int i) { printf("computed: %i\n", i); }
å€æŽããããã°ã©ã ãå®è¡ããã«ã¯ãã©ã€ãã©ãªã«ãªã³ã¯ããŸãïŒ
$ cc -c rtlib.c $ clang -Xclang -load -Xclang build/skeleton/libSkeletonPass.so -c example.c $ cc example.o rtlib.o $ ./a.out 12 computed: 14 14
å¿ èŠã«å¿ããŠãããã°ã©ã ãšã©ã€ãã©ãªããªã³ã¯ããŠããããã·ã³ã³ãŒãã«ã³ã³ãã€ã«ã§ããŸãã llvm-linkãŠãŒãã£ãªãã£ã圹ç«ã¡ãŸããããã¯ãPPã¬ãã«ã§ldã®å€§ãŸããªåçç©ãšèŠãªãããšãã§ããŸãã
泚é
ã»ãšãã©ã®ãããžã§ã¯ãã§ã¯ãéçºè ãšã®å¯Ÿè©±ãå¿ èŠã§ãã ãã®ãããLLVMãã¹ã«å¿ èŠãªæ å ±ãããã°ã©ã ããäŒããã¡ã¢ã䜿çšãããšäŸ¿å©ã§ãã ã¡ã¢ãäœæããã«ã¯ããã€ãã®æ¹æ³ããããŸãã
- å®çšçã§ããã«ãŒçãªæ¹æ³ã¯ããããžãã¯ãæ©èœã䜿çšããããšã§ãã ããããŒãã¡ã€ã«ã«ç©ºã®æ¬æãšãå¯èœã§ããã°ç¹å¥ãªäžæã®ååãæã€é¢æ°ã宣èšããŸãã ãã®ãã¡ã€ã«ããœãŒã¹ã³ãŒãã«å«ãããããã®é¢æ°ãžã®åŒã³åºããè¿œå ããŸãã 次ã«ããã¹ãå®è¡ããªãããé¢æ°ãåŒã³åºãCallInståœä»€ãèŠã€ããŠããããã䜿çšããŠããžãã¯é¢æ°ãå®è¡ããŸãã ããšãã°ã__enable_instrumentationïŒïŒããã³__disable_instrumentationïŒïŒåŒã³åºãã䜿çšããŠãããã°ã©ã ãç¹å®ã®é åã«å¯ŸããŠè¡ã£ãã³ãŒãå€æŽãå¶éããããšãã§ããŸãã
- ããã°ã©ããŒãé¢æ°ãŸãã¯å€æ°ã®å®£èšã«ããŒã«ãŒãè¿œå ã§ããããã«ãããå ŽåãClang __attribute __ïŒïŒAnnotateïŒ "foo"ïŒïŒã³ã³ã¹ãã©ã¯ãã¯æå®ãããæååã®ã¡ã¿ããŒã¿ãè¿œå ããæž¡ããšãã«åŠçã§ããŸãã ãã©ã³ãã³ã»ãã«ãã¯ããã®ãã¯ããã¯ã«é¢ããåçš¿ãæžããŸããã 宣èšã§ã¯ãªãåŒãããŒã¯ããå Žåã¯ã __ builtin_annotationïŒeã "foo"ïŒçµã¿èŸŒã¿æ§æãé©ããŠããŸãããæ®å¿µãªããããã¥ã¡ã³ãåãããŠããããæ©èœãå¶éãããŠããŸãã
- ãªã¹ã¯ãåããŠClangãçŽæ¥å€æŽããæ°ããæ§æã解éã§ããŸãã ãããããããè¡ãããšã¯ãå§ãããŸããã
- åã®ã¡ã¢ãäœæããå¿ èŠãããå ŽåïŒããã¯ãæ°ã¥ããŠããªãå Žåã§ããããªãé »ç¹ã«å¿ èŠã§ãïŒãä»ç§ã¯Qualaã·ã¹ãã ãéçºããŠããŸãã JSR-308 for Javaãªã©ã®ã«ã¹ã¿ã ã¿ã€ã修食åãšãã©ã°ã€ã³ã¿ã€ãã·ã¹ãã ã®ãµããŒããClangã«è¿œå ããŸãã ãã®ãããžã§ã¯ãã§äžç·ã«ä»äºãããããšã«èå³ããããªãæããŠãã ããïŒ
å°æ¥ã®åºçç©ã§ãªã¹ããããŠããæ¹æ³ã«ã€ããŠããã«è©³ãããäŒãããããšæããŸãã
ãã®ä»å€æ°...
LLVMã«ã¯å€§ããªå¯èœæ§ããããŸãã ãã®èšäºã§åãäžããŠããªããããã¯ã®ã¿ããªã¹ãããŸãã
- LLVMã°ããŒãã³ã³ããŒãã¡ã³ãã§å©çšå¯èœãªå¹ åºãã¯ã©ã·ãã¯ã³ã³ãã€ã©åæããŒã«ã䜿çšããŸãã
- ããã¯ãšã³ãããã¡ã€ãã©ã€ãºããããšã«ãããèšèšè ã«å¿ èŠãªç¹å¥ãªæ©æ¢°åœä»€ã®äœæã
- ãããã°æ å ±ã䜿çšããŠããœãããŠã§ã¢ã®ç¹å®ã®ãã€ã³ãã«å¯Ÿå¿ãããœãŒã¹ã³ãŒãã®è¡ã®è¡çªå·ãšæåã«é¢ããããŒã¿ãååŸããŸãã
- Clangããã¯ãšã³ãã®ãã©ã°ã€ã³ãäœæããŸã ã
䟡å€ã®ããäœããäœæã§ããããã«ãååãªæ å ±ãæäŸããŠããã ããã°å¹žãã§ãã èšäºã圹ç«ã€ãã©ããã調æ»ããäœæãã ç§ã«æžããŠãã ãã ïŒ
________________________________________
ãã®èšäºã®å£é çã®çºè¡šã«åºåžããå€ãã®é©ãã¹ãæçšãªè³ªåãããŠããã建ç¯ãšã·ã¹ãã ã®ã°ã«ãŒãããã¯ã·ã³ãã³å€§åŠã®ã¹ã¿ããã«æè¬ããŸãã
芪æãªãèªè ããã®è¿œå ïŒ
- Emery Bergerã¯ãç¹å®ã®ã¢ãŒããã¯ãã£èŠä»¶ïŒã¬ãžã¹ã¿ãã¡ã¢ãªéå±€ãåœä»€ãšã³ã³ãŒãã£ã³ã°ãªã©ïŒãé å®ããå Žåã Pinãªã©ã®ãã€ãããã¯ãã€ããªã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ããŒã«ãäŸç¶ãšããŠæ£ããéžæã§ãããšææããŸããã
- Brandon Holtã¯ãGraphVizã䜿çšããå¶åŸ¡ãããŒã®ã°ã©ãåãªã©ãLLVMã§ãããã°ã®ãã³ããå ¬éããŸããã
- John Regehrãã 㯠ããããžã§ã¯ãã§èŠäºãªLLVMã«äŸåããããšãããŸãè¯ããªãçç±ã«ã€ããŠã³ã¡ã³ãããŸãã -APIã¯åžžã«å€åããŠããŸãã LLVMã®å éšã³ã³ããŒãã³ãã¯ãªãªãŒã¹ããšã«å€§ããç°ãªãããããããžã§ã¯ãã«é ããã«ã€ããŠããã«ã¯ããããã®å€æŽã«é ããã«ã€ããŠããå¿ èŠããããŸãã
- Alex Bradburyã¯ã LLVMé±åãã¥ãŒã¹ã¬ã¿ãŒãçºè¡ããŠããŸããããã¯ãLLVMãšã³ã·ã¹ãã ã®ã€ãã³ãã远跡ããããã®åªãããªãœãŒã¹ã§ãã
ABBYY Language Servicesã«ãã翻蚳