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

LLVM Tutorial 02 - わいわいswiftc

sonson
March 01, 2019

LLVM Tutorial 02 - わいわいswiftc

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

sonson

March 01, 2019
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 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 }
  3. LLVMͱ͸ʁ • ίϯύΠϥ։ൃج൫ • ίϯύΠϥΛ࡞ΔͨΊͷϥΠϒϥϦ • C++Ͱॻ͔Ε͍ͯΔ • ෭࢈෺ •

    LLDB • clang • GNU GCC͕ංେԽ͗ͨ͢͠ର߅അ • dragoneggͱݺ͹ΕΔgccͷόοΫΤϯυ΋͋Δ • libc++
  4. Ԡ༻ BSN " " 4 BSN " " 4 BSN

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

    ฒྻԽ • CPU͸ສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ΋։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔ೉ۃ·Δ ιϑτ΢ΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
  6. ͜͜਺೥ͷ࿩ • 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͕ग़ͯ͘Δ
  7. LLVM Tutorial • LLVMΛ࢖ͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ • ಡΉͷʹඞཁͳεΩϧ • C++

    • ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡ • ਖ਼௚ɼจ͕௕͗ͯ͢ಡΊͳ͔ͬͨΓɼ͋Μ·ϝϯς φϯε͞Εͯͳ͍ͱ͜Ζ΋͋Δ
  8. TutorialͷϏϧυʹ͍ͭͯ • 7.0͸Chapter4Ҏ߱ɼStandard libraryͷؔ਺Λ௚઀Ϧ ϯΫͯ͠Δαϯϓϧ͸࢖͑ͳ͍ • ֎෦ͷAPIݺͼग़͠ʹࣦഊͯ͠Ϋϥογϡ͢Δ • 6.0͸OK •

    github͔ΒνΣοΫΞ΢τ͠ɼϏϧυ͢Δͷ͕ྑ͍ • ֬ೝͨ͠؀ڥ • macOS, brewͱιʔε͔ΒϏϧυ • Linux, aptͷύοέʔδͱιʔε͔ΒϏϧυ
  9. ίϯύΠϥͷதʹ /// ίϯύΠϥͷதͰɼ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; }
  10. 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`
  11. ಺༁ • ͸͡Ίʹ • ύʔαͱந৅ߏจ໦ • LLVM IRίʔυੜ੒ • JITͱ࠷దԽ

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

    form) • ੩త୯Ұ୅ೖɾɾɾม਺͸มԽ͠ͳ͍ • ܕ͸ݫີ a = (b + c) ∗ d ʢʴɼ̱ɼ̲ɼtmpaddʣ ʢˎɼtmpaddɼ̳ɼaʣ
  13. 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 }
  14. ࠷ॳ • ̍ߦΛίϯύΠϧ͢Δ • ม਺͸ͳ͍ • ؔ਺͸͋Δ • math.hͱ͔͸࢖͑Δ •

    if/else/forจ͸ͳ͠ɾɾɾޙ͔Β௥Ճ • ͭ·ΓνϡʔϦϯά׬શͰ͸ͳ͍
  15. ୈೋาʙந৅ߏจ໦ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body

    BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘
  16. ม਺Λอ࣋͢Δϊʔυ class VariableExprAST : public ExprAST { std::string Name; public:

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

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

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

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

    if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); FnIR->print(errs()); fprintf(stderr, "\n"); }
  24. ೋ߲ԋࢉࢠͷ৔߹ 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"); } } ܭࢉ݁ՌΛอଘ͢ΔϨδελ໊
  25. ؔ਺એݴ 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; }
  26. ؔ਺࣮૷ 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);
  27. ؔ਺࣮૷ // 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; }
  28. ந৅ߏจ໦͔Β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
  29. 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
  30. 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
  31. 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 ^
  32. ·ͱΊ • LLVMʹ͍ͭͯ • എܠɼྺ࢙ɼԠ༻ • LLVM Tutorial • ந৅ߏจ໦

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