Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LLVM Tutorial - わいわいswiftc

Avatar for sonson sonson
December 17, 2018

LLVM Tutorial - わいわいswiftc

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

Avatar for sonson

sonson

December 17, 2018
Tweet

More Decks by sonson

Other Decks in Programming

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

    ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
  3. ͜͜਺೥ͷ࿩ • 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͕ग़ͯ͘Δ
  4. ίϯύΠϧ؀ڥ • ίϚϯυͷྫ • 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`
  5. αϯϓϧ # 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))
  6. 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.
  7. ߏจ໦ͷϊʔυΫϥε /// 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) {} }; ਺஋Λอଘ͢Δϊʔυ
  8. ม਺ͱೋ߲ԋࢉࢠ /// 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)) {} }; +ͱ͔-Έ͍ͨͳԋࢉࢠͱ͔
  9. ؔ਺ݺͼग़͠ͷͨΊͷϊʔυ /// 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)) {} }; ؔ਺ݺͼग़͠ͷϊʔυɽ͔͜͜Βؔ਺ϙΠϯλΛݺͿʁ
  10. ؔ਺ͷϓϩτλΠϓએݴ /// 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; } }; ؔ਺ͷ໊લɼҾ਺ͷ໊લͷϦετ͕ϓϩύςΟɽ ʢී௨͸ܕͷϦετͷ΋ඞཁʣ
  11. ؔ਺ͷϓϩτλΠϓએݴ /// 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)) {} }; ؔ਺ͷ࣮૷ɽ ϓϩτλΠϓ΁ͷϙΠϯλͱؔ਺ͷ࣮૷ຊମ΁ͷϙΠϯλ
  12. ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ /// 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()Ͱ άϩʔόϧม਺ʹ࣍ͷτʔΫϯΛಡΈࠐΉ ͭ·ΓɼԚ͍
  13. codegenͷͨΊͷΦϒδΣΫτ • static LLVMContext TheContext; • γϯάϧτϯʁσʔλ΍ܕ͕͢΂ͯอଘ͢ΔΦϒδΣ Ϋτɽ • static

    IRBuilder<> Builder(TheContext); • llvmͷIRΛੜ੒͢ΔͨΊͷΦϒδΣΫτɽ • static std::unique_ptr<Module> TheModule; • ͍ΘΏΔϞδϡʔϧɽ͜͜ʹάϩʔόϧม਺͕อଘ ͞ΕΔɽ͜ͷΦϒΤδΣΫτʹ͢΂ͯͷσʔλ͕อ ଘ͞Εɼ͋ΒΏΔ΋ͷ͸͜͜΁ͷϙΠϯλ • static std::map<std::string, Value *> NamedValues; • ม਺໊ʁͷ௥੻ʹ࢖͏ϚοϓͬΆ͍ɽ
  14. 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Λࣔ͢ม਺
  15. ೋ߲ԋࢉࢠͷ৔߹ 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"); } }