LLVM Tutorial 02 - わいわいswiftc

F9feb45c0a049cccc3e2563f1fe2f869?s=47 sonson
March 01, 2019

LLVM Tutorial 02 - わいわいswiftc

LLVMチュートリアルをやってみよう.
今回は第3章くらいまでです.

F9feb45c0a049cccc3e2563f1fe2f869?s=128

sonson

March 01, 2019
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. LLVM IRಡΊ·͔͢ʁ @G = weak global i32 0 ; type

    of @G is i32* @H = weak global i32 0 ; type of @H is i32* define i32 @test(i1 %Condition) { entry: br i1 %Condition, label %cond_true, label %cond_false cond_true: %X.0 = load i32* @G br label %cond_next cond_false: %X.1 = load i32* @H br label %cond_next cond_next: %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ] ret i32 %X.2 }
  4. LLVMͱ͸ʁ • ίϯύΠϥ։ൃج൫ • ίϯύΠϥΛ࡞ΔͨΊͷϥΠϒϥϦ • C++Ͱॻ͔Ε͍ͯΔ • ෭࢈෺ •

    LLDB • clang • GNU GCC͕ංେԽ͗ͨ͢͠ର߅അ • dragoneggͱݺ͹ΕΔgccͷόοΫΤϯυ΋͋Δ • libc++
  5. $ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT LLVMΛ࢖ͬͯ࡞Δ ͜ͷPass͕ॏཁ ৭ʑ༻ҙ͞Ε͍ͯΔ͠ ࣗ෼Ͱ΋࡞ΕΔ

    x86, ARM, ia64, i386ɾɾɾͳͲ όΠφϦ΁ͷม׵͸LLVMͷϞδϡʔϧ
  6. ΦϨΦϨ ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT ͑͜͜͞࡞Ε͹ ͋ͱ͸LLVMʹ೚ͤΒΕΔ

  7. Swiftͷ৔߹ 4XJGU 4*- 4*- ܕ੍໿ 4*- 3"8 4*- ࠷దԽ --7.*3

    4XJGU*OUFSNFEJBUF-BOHVBHF
  8. Ԡ༻ BSN " " 4

  9. Ԡ༻ BSN " " 4 BSN " " 4 BSN

    " " 4 BSN " " 4 BSN " " 4
  10. Ԡ༻ CJUDPEF " " 4 BSN --7.Λ࢖͍ ֤σόΠε޲͚ ʹ࠷దԽ

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

    ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
  12. ͜͜਺೥ͷ࿩ • 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͕ग़ͯ͘Δ
  13. [11]

  14. Halide [10] • εϨου • SIMD • GPU • ͳͲͳͲɾɾɾ

  15. Halide HalideͳΒɼ͜ͷίʔυͰશͯͷ؀ڥʹϙʔτͰ͖Δ [10] • εϨου • SIMD • GPU •

    ͳͲͳͲɾɾɾ
  16. ·ͱΊΔͱ • ࠷ۙͷίϯύΠϥ͸LLVM • HalideͳͲΛར༻͢Δʹ΋LLVM • ΍͸ΓɼLLVMΛ஌Βͳ͍ͱલʹਐΊͳ͍

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

    • ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡ • ਖ਼௚ɼจ͕௕͗ͯ͢ಡΊͳ͔ͬͨΓɼ͋Μ·ϝϯς φϯε͞Εͯͳ͍ͱ͜Ζ΋͋Δ
  18. LLVM Tutorialͱ͸ʁ • Tutorials about using LLVM. Includes a tutorial

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

  20. TutorialͷϏϧυʹ͍ͭͯ • 7.0͸Chapter4Ҏ߱ɼStandard libraryͷؔ਺Λ௚઀Ϧ ϯΫͯ͠Δαϯϓϧ͸࢖͑ͳ͍ • ֎෦ͷAPIݺͼग़͠ʹࣦഊͯ͠Ϋϥογϡ͢Δ • 6.0͸OK •

    github͔ΒνΣοΫΞ΢τ͠ɼϏϧυ͢Δͷ͕ྑ͍ • ֬ೝͨ͠؀ڥ • macOS, brewͱιʔε͔ΒϏϧυ • Linux, aptͷύοέʔδͱιʔε͔ΒϏϧυ
  21. ίϯύΠϥͷதʹ /// ίϯύΠϥͷதͰɼKaleidoscope͔Βݺ΂Δؔ਺Λఆٛ͢Δ /// putchard - putchar that takes a

    double and returns 0. extern "C" DLLEXPORT double putchard(double X) { fputc((char)X, stderr); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. extern "C" DLLEXPORT double printd(double X) { fprintf(stderr, "%f\n", X); return 0; }
  22. TutorialϏϧυํ๏ • macOS • clang++ɾɾɾdeveloper tool • llvm-configɾɾɾιʔε͔ΒࣗલͰϏϧυͨ͠΋ͷ • linux

    • g++ɾɾɾbuild essentials • llvm-configɾɾɾaptͰπʔϧΛΠϯετʔϧ • -rdynamic,-Wl,–export-dynamic͕ඞཁͳ͜ͱ΋͋Δ clang++ ./toy.cpp `../../../build/bin/llvm-config --cxxflags --ldflags --libs --libfiles --system-libs`
  23. ಺༁ • ͸͡Ίʹ • ύʔαͱந৅ߏจ໦ • LLVM IRίʔυੜ੒ • JITͱ࠷దԽ

    • ੍ޚϑϩʔ • ԋࢉࢠͷఆٛ • mutableͷಋೖ • ίϯύΠϧ • σόοά৘ใ • ·ͱΊ
  24. LLVM IRͷಛ௃ • Ϩδελɼม਺͸ແݶʹ͋Δ • ̏൪஍ίʔυΈ͍ͨͳײ͡ • SSA(Static Single Assignment

    form) • ੩త୯Ұ୅ೖɾɾɾม਺͸มԽ͠ͳ͍ • ܕ͸ݫີ a = (b + c) ∗ d ʢʴɼ̱ɼ̲ɼtmpaddʣ ʢˎɼtmpaddɼ̳ɼaʣ
  25. LLVM IRͷαϯϓϧ define double @baz(double %x) { entry: %ifcond =

    fcmp one double %x, 0.000000e+00 br i1 %ifcond, label %then, label %else then: ; preds = %entry %calltmp = call double @foo() br label %ifcont else: ; preds = %entry %calltmp1 = call double @bar() br label %ifcont ifcont: ; preds = %else, %then %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ] ret double %iftmp }
  26. ։ൃ͢ΔݴޠKaleidoscope • ໨ඪͱ࢓༷ • doubleܕͷΈ • ؔ਺͕࢖͑Δ • Standard libraryͷؔ਺Λ࢖͑Δ

    • if/elseจ • forจ • Ϣʔβఆٛԋࢉࢠ • REPL/JIT
  27. ࠷ॳ • ̍ߦΛίϯύΠϧ͢Δ • ม਺͸ͳ͍ • ؔ਺͸͋Δ • math.hͱ͔͸࢖͑Δ •

    if/else/forจ͸ͳ͠ɾɾɾޙ͔Β௥Ճ • ͭ·ΓνϡʔϦϯά׬શͰ͸ͳ͍
  28. ͜Ε͔ΒC++Ͱ࡞Δ΋ͷ ,BMFJEPTDPQFͷιʔείʔυ ΦϨΦϨݴޠͷιʔείʔυ ίϯύΠϥ --7.*3΍όΠφϦ ,BMFJEPTDPQFΛղऍ͠ --7.Λ࢖ͬͯɼ--7.*3Λੜ੒͠ɼ όΠφϦΛు͘ ͭ·ΓɼC++Ͱݴޠͷ࢓༷Λॻ͍͍ͯ͘ײ͡

  29. ࠷ॳͷҰาʙޠኮղੳ(Lexer) • ·ͣιʔείʔυΛݻ·Γʹ෼ׂ͍ͯ͘͠ extern cos(0.1); ֎෦એݴ tok_extern Կ͔ͷࣝผࢠ tok_identifier ਺஋τʔΫϯ

    tok_number Χοίͱηϛίϩϯ͸ޠኮʹ౰ͨΒͳ͍ͷͰɼ ͱΓ͋͑ͣඈ͹͢
  30. ୈೋาʙந৅ߏจ໦ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘
  31. ந৅ߏจ໦ͷΫϥε class ExprAST { public: virtual ~ExprAST() = default; virtual

    Value *codegen() = 0; };
  32. ม਺Λอ࣋͢Δϊʔυ class VariableExprAST : public ExprAST { std::string Name; public:

    VariableExprAST(const std::string &Name) : Name(Name) {} Value *codegen() override; };
  33. ೋ߲ԋࢉࢠ 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; };
  34. ؔ਺એݴ 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)) {} Function *codegen(); const std::string &getName() const { return Name; } };
  35. ؔ਺࣮૷ 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(); };
  36. ந৅ߏจ໦ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘
  37. ந৅ߏจ໦ def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘
  38. LLVM IRΛੜ੒͢Δ class ExprAST { public: virtual ~ExprAST() = default;

    virtual Value *codegen() = 0; }; ֤ϊʔυ͔ΒLLVM IRΛੜ੒͢Δ ߏจ໦ͷϊʔυ͝ͱʹੜ੒ͷͨΊͷίʔυΛ࣮૷͍ͯ͘͠
  39. codegenͷ࢓ࣄ • llvm::ValueΫϥεΛฦ͢ • ͜ͷΫϥε͕LLVM IRΛు͍ͯ͘ΕΔ • llvm::Value • ੩త୯Ұ୅ೖϨδελΛࣔ͢

    if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); FnIR->print(errs()); fprintf(stderr, "\n"); }
  40. ೋ߲ԋࢉࢠͷ৔߹ 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"); return Builder.CreateUIToFP( L, Type::getDoubleTy(TheContext), "booltmp"); default: return LogErrorV("invalid binary operator"); } } ܭࢉ݁ՌΛอଘ͢ΔϨδελ໊
  41. ؔ਺એݴ Function *PrototypeAST::codegen() { 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() ); // Set names for all arguments. unsigned Idx = 0; for (auto &Arg : F->args()) Arg.setName(Args[Idx++]); return F; }
  42. ؔ਺࣮૷ Function *FunctionAST::codegen() { Function *TheFunction = TheModule->getFunction( Proto->getName()); if

    (!TheFunction) TheFunction = Proto->codegen(); if (!TheFunction) return nullptr; // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create( TheContext, "entry", TheFunction); Builder.SetInsertPoint(BB);
  43. ؔ਺࣮૷ // Record the function arguments in the NamedValues map.

    NamedValues.clear(); for (auto &Arg : TheFunction->args()) NamedValues[Arg.getName()] = &Arg; if (Value *RetVal = Body->codegen()) { // Finish off the function. Builder.CreateRet(RetVal); // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); return TheFunction; } // Error reading body, remove function. TheFunction->eraseFromParent(); return nullptr; }
  44. ந৅ߏจ໦͔ΒLLVM IRΛ࡞Δ def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST

    Body BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b
  45. codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b BEEUNQGBEEEPVCMFB C
  46. codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b BEEUNQGBEEEPVCMFB C BEEUNQGBEEEPVCMFBEEUNQ D
  47. codegen def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b EFpOFEPVCMF!IPHF EPVCMFB EPVCMFC EPVCMFD \ FOUSZ BEEUNQGBEEEPVCMFB C BEEUNQGBEEEPVCMFBEEUNQ D SFUEPVCMFBEEUNQ ^
  48. ·ͱΊ • LLVMʹ͍ͭͯ • എܠɼྺ࢙ɼԠ༻ • LLVM Tutorial • ந৅ߏจ໦

    • LLVM IRͷੜ੒ • ͔͜͜Β͕͓΋͠Ζ͍ • PassʹΑΔ࠷దԽ • ੍ޚϑϩʔͷ࣮૷ • mutableม਺ͷಋೖ
  49. ଓ͘