LLVM Tutorial - わいわいswiftc

F9feb45c0a049cccc3e2563f1fe2f869?s=47 sonson
December 17, 2018

LLVM Tutorial - わいわいswiftc

LLVM Tutorialについて発表しました.
公開しようと思っている翻訳メモはこちら.
https://github.com/sonsongithub/llvm-tutorial

F9feb45c0a049cccc3e2563f1fe2f869?s=128

sonson

December 17, 2018
Tweet

Transcript

  1. Getting start with llvm Θ͍Θ͍swiftc Yuichi Yoshida Senior researcher, DENSO

    IT Laboratory, Inc. #conference @sonson_twit © 2018 DENSO IT Laboratory, Inc., All rights reserved. Redistribution or public display not permitted without written permission from DENSO IT Laboratory, Inc. LLVM Tutorial
  2. https://peaks.cc/books/iOS12

  3. https://peaks.cc/books/iOS12

  4. ͳͥɼLLVMʁ • ੈͷதͷྲྀΕ • ϜʔΞͷ๏ଇͷݶք • CPUͷྔతਐԽ͸ɼݶքʹ͍͍ۙͮͯΔʢ෺ཧతʣ • ճආ͢Δʹ͸ʁ •

    ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
  5. ͜͜਺೥ͷ࿩ • Halide • LLVMΛ࢖͍ɼC/C++ʹ௚઀ฒྻίʔυΛ͔͚Δ • fixstars͕͜ΕͰHalide FPGAͳͲΛϦϦʔε • temp.split(y,

    y, yi, 8).parallel(y).vectorize(x, 4); • Tensorflow for Swift • SwiftͰػցֶशͷߦྻܭࢉ΍ฒྻܭࢉΛ΍Γ͍ͨ • Julia • ਺ֶతͳܭࢉΛඳ͖΍ͨ͘͢͠ݴޠ • LLVMΛ࢖༻ ཁॴɼཁॴͰLLVM͕ग़ͯ͘Δ
  6. ͜ͷลͷ࿩͸ੲͬͪ͜Ͱൃද https://tech.d-itlab.co.jp/programming/567/

  7. LLVM Tutorialͱ͸ʁ • Tutorials about using LLVM. Includes a tutorial

    about making a custom language with LLVM.
  8. LLVM Tutorial • LLVMΛ࢖ͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ • ಡΉͷʹඞཁͳεΩϧ • C++

    • ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡
  9. ϝϞॻ͖ͳͲ • https://github.com/sonsongithub/llvm-tutorial • LLVM Release Licenseʹج͖ͮɼ຋༁ϝϞ౳Λެ։ͯ͠ ͍·͢

  10. ࣮૷ • llvmͷΫϥεΛ࢖͍ίϯύΠϥΛ࡞Δ • C++ͰllvmͷΫϥεΛੜ੒͠ɼͦ͜ͰͳΜͧ΍Δ • ࠷ऴతʹ׬੒ͨ͠όΠφϦʹιʔείʔυΛ৯ΘͤΔ • ݁Ռɼղੳ݁Ռɼதؒίʔυɼߏจ໦Β͕ಘΒΕΔ

  11. ίϯύΠϧ؀ڥ • ίϚϯυͷྫ • llvm-configͳͲXcodeʹؚ·Εͳ͍πʔϧ͕͋Δ • macOSͷ৔߹ • brew install

    llvmͰΠϯετʔϧ͓ͯ͘͠ • Mojave͸/usr/include͕ͳ͍ͷͰखಈͰɾɾɾɾ • ࢲ͸ϋϚͬͨɾɾɾɾɾ • ”Xcode 10 Release Notes” • ؀ڥม਺ͷ੾Γସ͑Λ๨Εͣʹ clang++ --std=c++14 ./toy.cpp `llvm-config --cxxflags --ldflags --libs --libfiles —system-libs`
  12. ։ൃ͢ΔݴޠKaleidoscope • ໨ඪͱ࢓༷ • doubleܕͷΈ • ؔ਺͕࢖͑Δ • Standard libraryͷؔ਺Λ࢖͑Δ

    • if/elseจ • forจ • Ϣʔβఆٛԋࢉࢠ • REPL/JIT
  13. αϯϓϧ # Compute the x'th fibonacci number. def fib(x) if

    x < 3 then 1 else fib(x-1)+fib(x-2) # This expression will compute the 40th number. fib(40) # load standard library extern sin(arg); extern cos(arg); extern atan2(arg1, arg2); # call atan2 atan2(sin(.4), cos(42))
  14. ྲྀΕ • ιʔείʔυΛτʔΫϯʹ෼ׂ͢Δ • τʔΫϯ͔Βߏจ໦Λ࡞Δ • ߏจ໦ͷϊʔυΛLLVM IRʹม׵͢Δ • LLVM

    IRΛόΠφϦʹ͢Δ
  15. େલఏ

  16. νϡʔτϦΞϧͷιʔείʔυ͕͍͚ͯͳ͍

  17. άϩʔόϧม਺ͩΒ͚ɾɾɾ ͍͋ͬͪͬͨΓɼ͍ͬͪͬͨ͜Γɾɾɾɾɾɾ

  18. The error recovery in our parser will not be the

    best and is not particular user-friendly, but it will be enough for our tutorial. Note that instead of adding virtual methods to the ExprAST class hierarchy, it could also make sense to use a visitor pattern or some other way to model this. Again, this tutorial won’t dwell on good software engineering practices: for our purposes, adding a virtual method is simplest.
  19. ࠷ॳͷҰาʙޠኮղੳ(Lexer) • ·ͣιʔείʔυΛݻ·Γʹ෼ׂ͍ͯ͘͠ extern cos(0.1); ֎෦એݴ tok_extern Կ͔ͷࣝผࢠ tok_identifier ਺஋τʔΫϯ

    tok_number Χοίͱηϛίϩϯ͸ޠኮʹ౰ͨΒͳ͍ͷͰɼ ͱΓ͋͑ͣඈ͹͢
  20. Lexer • ந৅ߏจ໦ͱݺ͹ΕΔ໦ߏ଄Λ࡞Δ

  21. ͋ͱ͸ɾɾɾɾ • ΧοίΛਂ͞༏ઌͰॲཧ • ೋ߲ԋࢉࢠΛ༏ઌॱҐΛ͚ͭͯɼਂ͞༏ઌͰॲཧ • ɾɾɾ͏Μ͵Μ΍Δͱɼந৅ߏจ໦͕׬੒

  22. ߏจ໦ͷϊʔυΫϥε /// ExprAST - Base class for all expression nodes.

    class ExprAST { public: virtual ~ExprAST() {} }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} }; ਺஋Λอଘ͢Δϊʔυ
  23. ม਺ͱೋ߲ԋࢉࢠ /// VariableExprAST - ม਺Λอଘ͢ΔͨΊͷཁૉ class VariableExprAST : public ExprAST

    { std::string Name; public: VariableExprAST(const std::string &Name) : Name(Name) {} }; /// 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)) {} }; +ͱ͔-Έ͍ͨͳԋࢉࢠͱ͔
  24. ؔ਺ݺͼग़͠ͷͨΊͷϊʔυ /// 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)) {} }; ؔ਺ݺͼग़͠ͷϊʔυɽ͔͜͜Βؔ਺ϙΠϯλΛݺͿʁ
  25. ؔ਺ͷϓϩτλΠϓએݴ /// PrototypeAST - This class represents the "prototype" for

    a function, /// which captures its name, and its argument names (thus implicitly the number /// of arguments the function takes). class PrototypeAST { std::string Name; std::vector<std::string> Args; public: PrototypeAST(const std::string &name, std::vector<std::string> Args) : Name(name), Args(std::move(Args)) {} const std::string &getName() const { return Name; } }; ؔ਺ͷ໊લɼҾ਺ͷ໊લͷϦετ͕ϓϩύςΟɽ ʢී௨͸ܕͷϦετͷ΋ඞཁʣ
  26. ؔ਺ͷϓϩτλΠϓએݴ /// FunctionAST - This class represents a function definition

    itself. 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)) {} }; ؔ਺ͷ࣮૷ɽ ϓϩτλΠϓ΁ͷϙΠϯλͱؔ਺ͷ࣮૷ຊମ΁ͷϙΠϯλ
  27. ந৅ߏจ໦ͷϊʔυ͕ἧ͏ • ExprAST • NumberExprAST • VariableExprAST • BinaryExprAST •

    CallExprAST • PrototypeAST • FunctionAST
  28. ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ /// numberexpr ::= number static std::unique_ptr<ExprAST> ParseNumberExpr() { auto

    Result = llvm::make_unique<NumberExprAST>(NumVal); getNextToken(); // consume the number return std::move(Result); } NumVal͕άϩʔόϧม਺ͰɼgetNextToken()Ͱ άϩʔόϧม਺ʹ࣍ͷτʔΫϯΛಡΈࠐΉ ͭ·ΓɼԚ͍
  29. ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ auto LHS = llvm::make_unique<VariableExprAST>("x"); auto RHS = llvm::make_unique<VariableExprAST>("y"); auto

    Result = std::make_unique<BinaryExprAST>('+', std::move(LHS), std::move(RHS));
  30. codegenͷͨΊͷΦϒδΣΫτ • static LLVMContext TheContext; • γϯάϧτϯʁσʔλ΍ܕ͕͢΂ͯอଘ͢ΔΦϒδΣ Ϋτɽ • static

    IRBuilder<> Builder(TheContext); • llvmͷIRΛੜ੒͢ΔͨΊͷΦϒδΣΫτɽ • static std::unique_ptr<Module> TheModule; • ͍ΘΏΔϞδϡʔϧɽ͜͜ʹάϩʔόϧม਺͕อଘ ͞ΕΔɽ͜ͷΦϒΤδΣΫτʹ͢΂ͯͷσʔλ͕อ ଘ͞Εɼ͋ΒΏΔ΋ͷ͸͜͜΁ͷϙΠϯλ • static std::map<std::string, Value *> NamedValues; • ม਺໊ʁͷ௥੻ʹ࢖͏ϚοϓͬΆ͍ɽ
  31. LLVM IRΛੜ੒͢Δ • ͖͞΄ͲͷϊʔυʹcodegenΛੜ΍͢ /// ExprAST - Base class for

    all expression nodes. class ExprAST { public: virtual ~ExprAST() {} virtual Value *codegen() = 0; }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} virtual Value *codegen(); }; ValueɾɾɾStatic Single Assignment RegisterΛࣔ͢ม਺
  32. ೋ߲ԋࢉࢠͷ৔߹ 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"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } }
  33. ଓ͘