Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

https://peaks.cc/books/iOS12

Slide 3

Slide 3 text

https://peaks.cc/books/iOS12

Slide 4

Slide 4 text

ͳͥɼLLVMʁ • ੈͷதͷྲྀΕ • ϜʔΞͷ๏ଇͷݶք • CPUͷྔతਐԽ͸ɼݶքʹ͍͍ۙͮͯΔʢ෺ཧతʣ • ճආ͢Δʹ͸ʁ • ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ

Slide 5

Slide 5 text

͜͜਺೥ͷ࿩ • 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͕ग़ͯ͘Δ

Slide 6

Slide 6 text

͜ͷลͷ࿩͸ੲͬͪ͜Ͱൃද https://tech.d-itlab.co.jp/programming/567/

Slide 7

Slide 7 text

LLVM Tutorialͱ͸ʁ • Tutorials about using LLVM. Includes a tutorial about making a custom language with LLVM.

Slide 8

Slide 8 text

LLVM Tutorial • LLVMΛ࢖ͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ • ಡΉͷʹඞཁͳεΩϧ • C++ • ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡

Slide 9

Slide 9 text

ϝϞॻ͖ͳͲ • https://github.com/sonsongithub/llvm-tutorial • LLVM Release Licenseʹج͖ͮɼ຋༁ϝϞ౳Λެ։ͯ͠ ͍·͢

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

ίϯύΠϧ؀ڥ • ίϚϯυͷྫ • 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`

Slide 12

Slide 12 text

։ൃ͢ΔݴޠKaleidoscope • ໨ඪͱ࢓༷ • doubleܕͷΈ • ؔ਺͕࢖͑Δ • Standard libraryͷؔ਺Λ࢖͑Δ • if/elseจ • forจ • Ϣʔβఆٛԋࢉࢠ • REPL/JIT

Slide 13

Slide 13 text

αϯϓϧ # 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))

Slide 14

Slide 14 text

ྲྀΕ • ιʔείʔυΛτʔΫϯʹ෼ׂ͢Δ • τʔΫϯ͔Βߏจ໦Λ࡞Δ • ߏจ໦ͷϊʔυΛLLVM IRʹม׵͢Δ • LLVM IRΛόΠφϦʹ͢Δ

Slide 15

Slide 15 text

େલఏ

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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.

Slide 19

Slide 19 text

࠷ॳͷҰาʙޠኮղੳ(Lexer) • ·ͣιʔείʔυΛݻ·Γʹ෼ׂ͍ͯ͘͠ extern cos(0.1); ֎෦એݴ tok_extern Կ͔ͷࣝผࢠ tok_identifier ਺஋τʔΫϯ tok_number Χοίͱηϛίϩϯ͸ޠኮʹ౰ͨΒͳ͍ͷͰɼ ͱΓ͋͑ͣඈ͹͢

Slide 20

Slide 20 text

Lexer • ந৅ߏจ໦ͱݺ͹ΕΔ໦ߏ଄Λ࡞Δ

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

ߏจ໦ͷϊʔυΫϥε /// 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) {} }; ਺஋Λอଘ͢Δϊʔυ

Slide 23

Slide 23 text

ม਺ͱೋ߲ԋࢉࢠ /// 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 LHS, RHS; public: BinaryExprAST(char op, std::unique_ptr LHS, std::unique_ptr RHS) : Op(op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} }; +ͱ͔-Έ͍ͨͳԋࢉࢠͱ͔

Slide 24

Slide 24 text

ؔ਺ݺͼग़͠ͷͨΊͷϊʔυ /// CallExprAST - ؔ਺ݺͼग़͠ͱҾ਺Λอଘ͢ΔͨΊͷ໦ class CallExprAST : public ExprAST { std::string Callee; std::vector> Args; public: CallExprAST(const std::string &Callee, std::vector> Args) : Callee(Callee), Args(std::move(Args)) {} }; ؔ਺ݺͼग़͠ͷϊʔυɽ͔͜͜Βؔ਺ϙΠϯλΛݺͿʁ

Slide 25

Slide 25 text

ؔ਺ͷϓϩτλΠϓએݴ /// 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 Args; public: PrototypeAST(const std::string &name, std::vector Args) : Name(name), Args(std::move(Args)) {} const std::string &getName() const { return Name; } }; ؔ਺ͷ໊લɼҾ਺ͷ໊લͷϦετ͕ϓϩύςΟɽ ʢී௨͸ܕͷϦετͷ΋ඞཁʣ

Slide 26

Slide 26 text

ؔ਺ͷϓϩτλΠϓએݴ /// FunctionAST - This class represents a function definition itself. class FunctionAST { std::unique_ptr Proto; std::unique_ptr Body; public: FunctionAST(std::unique_ptr Proto, std::unique_ptr Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} }; ؔ਺ͷ࣮૷ɽ ϓϩτλΠϓ΁ͷϙΠϯλͱؔ਺ͷ࣮૷ຊମ΁ͷϙΠϯλ

Slide 27

Slide 27 text

ந৅ߏจ໦ͷϊʔυ͕ἧ͏ • ExprAST • NumberExprAST • VariableExprAST • BinaryExprAST • CallExprAST • PrototypeAST • FunctionAST

Slide 28

Slide 28 text

ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ /// numberexpr ::= number static std::unique_ptr ParseNumberExpr() { auto Result = llvm::make_unique(NumVal); getNextToken(); // consume the number return std::move(Result); } NumVal͕άϩʔόϧม਺ͰɼgetNextToken()Ͱ άϩʔόϧม਺ʹ࣍ͷτʔΫϯΛಡΈࠐΉ ͭ·ΓɼԚ͍

Slide 29

Slide 29 text

ιʔε͔Βؤுͬͯ໦Λ࡞͍ͬͯ͘ auto LHS = llvm::make_unique("x"); auto RHS = llvm::make_unique("y"); auto Result = std::make_unique('+', std::move(LHS), std::move(RHS));

Slide 30

Slide 30 text

codegenͷͨΊͷΦϒδΣΫτ • static LLVMContext TheContext; • γϯάϧτϯʁσʔλ΍ܕ͕͢΂ͯอଘ͢ΔΦϒδΣ Ϋτɽ • static IRBuilder<> Builder(TheContext); • llvmͷIRΛੜ੒͢ΔͨΊͷΦϒδΣΫτɽ • static std::unique_ptr TheModule; • ͍ΘΏΔϞδϡʔϧɽ͜͜ʹάϩʔόϧม਺͕อଘ ͞ΕΔɽ͜ͷΦϒΤδΣΫτʹ͢΂ͯͷσʔλ͕อ ଘ͞Εɼ͋ΒΏΔ΋ͷ͸͜͜΁ͷϙΠϯλ • static std::map NamedValues; • ม਺໊ʁͷ௥੻ʹ࢖͏ϚοϓͬΆ͍ɽ

Slide 31

Slide 31 text

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Λࣔ͢ม਺

Slide 32

Slide 32 text

ೋ߲ԋࢉࢠͷ৔߹ 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"); } }

Slide 33

Slide 33 text

ଓ͘