$30 off During Our Annual Pro Sale. View Details »

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

    View Slide

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

    View Slide

  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
    }

    View Slide

  4. LLVMͱ͸ʁ
    • ίϯύΠϥ։ൃج൫
    • ίϯύΠϥΛ࡞ΔͨΊͷϥΠϒϥϦ
    • C++Ͱॻ͔Ε͍ͯΔ
    • ෭࢈෺
    • LLDB
    • clang
    • GNU GCC͕ංେԽ͗ͨ͢͠ର߅അ
    • dragoneggͱݺ͹ΕΔgccͷόοΫΤϯυ΋͋Δ
    • libc++

    View Slide

  5. $ݴޠ --7.*3 1BTT όΠφϦ
    ίϯύΠϥ 1BTT
    LLVMΛ࢖ͬͯ࡞Δ ͜ͷPass͕ॏཁ
    ৭ʑ༻ҙ͞Ε͍ͯΔ͠
    ࣗ෼Ͱ΋࡞ΕΔ
    x86, ARM, ia64, i386ɾɾɾͳͲ
    όΠφϦ΁ͷม׵͸LLVMͷϞδϡʔϧ

    View Slide

  6. ΦϨΦϨ
    ݴޠ
    --7.*3 1BTT όΠφϦ
    ίϯύΠϥ 1BTT
    ͑͜͜͞࡞Ε͹
    ͋ͱ͸LLVMʹ೚ͤΒΕΔ

    View Slide

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

    View Slide

  8. Ԡ༻
    BSN " " 4

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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͕ग़ͯ͘Δ

    View Slide

  13. [11]

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. LLVM Tutorial
    • LLVMΛ࢖ͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ
    • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ
    • ಡΉͷʹඞཁͳεΩϧ
    • C++
    • ӳޠ
    • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡
    • ਖ਼௚ɼจ͕௕͗ͯ͢ಡΊͳ͔ͬͨΓɼ͋Μ·ϝϯς
    φϯε͞Εͯͳ͍ͱ͜Ζ΋͋Δ

    View Slide

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

    View Slide

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

    View Slide

  20. TutorialͷϏϧυʹ͍ͭͯ
    • 7.0͸Chapter4Ҏ߱ɼStandard libraryͷؔ਺Λ௚઀Ϧ
    ϯΫͯ͠Δαϯϓϧ͸࢖͑ͳ͍
    • ֎෦ͷAPIݺͼग़͠ʹࣦഊͯ͠Ϋϥογϡ͢Δ
    • 6.0͸OK
    • github͔ΒνΣοΫΞ΢τ͠ɼϏϧυ͢Δͷ͕ྑ͍
    • ֬ೝͨ͠؀ڥ
    • macOS, brewͱιʔε͔ΒϏϧυ
    • Linux, aptͷύοέʔδͱιʔε͔ΒϏϧυ

    View Slide

  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;
    }

    View Slide

  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`

    View Slide

  23. ಺༁
    • ͸͡Ίʹ
    • ύʔαͱந৅ߏจ໦
    • LLVM IRίʔυੜ੒
    • JITͱ࠷దԽ
    • ੍ޚϑϩʔ
    • ԋࢉࢠͷఆٛ
    • mutableͷಋೖ
    • ίϯύΠϧ
    • σόοά৘ใ
    • ·ͱΊ

    View Slide

  24. LLVM IRͷಛ௃
    • Ϩδελɼม਺͸ແݶʹ͋Δ
    • ̏൪஍ίʔυΈ͍ͨͳײ͡
    • SSA(Static Single Assignment form)
    • ੩త୯Ұ୅ೖɾɾɾม਺͸มԽ͠ͳ͍
    • ܕ͸ݫີ
    a = (b + c) ∗ d
    ʢʴɼ̱ɼ̲ɼtmpaddʣ
    ʢˎɼtmpaddɼ̳ɼaʣ

    View Slide

  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
    }

    View Slide

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

    View Slide

  27. ࠷ॳ
    • ̍ߦΛίϯύΠϧ͢Δ
    • ม਺͸ͳ͍
    • ؔ਺͸͋Δ
    • math.hͱ͔͸࢖͑Δ
    • if/else/forจ͸ͳ͠ɾɾɾޙ͔Β௥Ճ
    • ͭ·ΓνϡʔϦϯά׬શͰ͸ͳ͍

    View Slide

  28. ͜Ε͔ΒC++Ͱ࡞Δ΋ͷ
    ,BMFJEPTDPQFͷιʔείʔυ
    ΦϨΦϨݴޠͷιʔείʔυ

    ίϯύΠϥ
    --7.*3΍όΠφϦ
    ,BMFJEPTDPQFΛղऍ͠
    --7.Λ࢖ͬͯɼ--7.*3Λੜ੒͠ɼ
    όΠφϦΛు͘
    ͭ·ΓɼC++Ͱݴޠͷ࢓༷Λॻ͍͍ͯ͘ײ͡

    View Slide

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

    View Slide

  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
    ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

    View Slide

  31. ந৅ߏจ໦ͷΫϥε
    class ExprAST {
    public:
    virtual ~ExprAST() = default;
    virtual Value *codegen() = 0;
    };

    View Slide

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

    View Slide

  33. ೋ߲ԋࢉࢠ
    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)) {}
    Value *codegen() override;
    };

    View Slide

  34. ؔ਺એݴ
    class PrototypeAST {
    std::string Name;
    std::vector Args;
    public:
    PrototypeAST(const std::string &Name, std::vector Args)
    : Name(Name), Args(std::move(Args)) {}
    Function *codegen();
    const std::string &getName() const { return Name; }
    };

    View Slide

  35. ؔ਺࣮૷
    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)) {}
    Function *codegen();
    };

    View Slide

  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
    ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

    View Slide

  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
    ԋࢉࢠͷ༏ઌ౓ʹج͖ͮɼਂ͞༏ઌͰߏจ໦Λ࡞͍ͬͯ͘

    View Slide

  38. LLVM IRΛੜ੒͢Δ
    class ExprAST {
    public:
    virtual ~ExprAST() = default;
    virtual Value *codegen() = 0;
    };
    ֤ϊʔυ͔ΒLLVM IRΛੜ੒͢Δ
    ߏจ໦ͷϊʔυ͝ͱʹੜ੒ͷͨΊͷίʔυΛ࣮૷͍ͯ͘͠

    View Slide

  39. codegenͷ࢓ࣄ
    • llvm::ValueΫϥεΛฦ͢
    • ͜ͷΫϥε͕LLVM IRΛు͍ͯ͘ΕΔ
    • llvm::Value
    • ੩త୯Ұ୅ೖϨδελΛࣔ͢
    if (auto *FnIR = ProtoAST->codegen()) {
    fprintf(stderr, "Read extern: ");
    FnIR->print(errs());
    fprintf(stderr, "\n");
    }

    View Slide

  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");
    }
    }
    ܭࢉ݁ՌΛอଘ͢ΔϨδελ໊

    View Slide

  41. ؔ਺એݴ
    Function *PrototypeAST::codegen() {
    std::vector 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;
    }

    View Slide

  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);

    View Slide

  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;
    }

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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
    ^

    View Slide

  48. ·ͱΊ
    • LLVMʹ͍ͭͯ
    • എܠɼྺ࢙ɼԠ༻
    • LLVM Tutorial
    • ந৅ߏจ໦
    • LLVM IRͷੜ੒
    • ͔͜͜Β͕͓΋͠Ζ͍
    • PassʹΑΔ࠷దԽ
    • ੍ޚϑϩʔͷ࣮૷
    • mutableม਺ͷಋೖ

    View Slide

  49. ଓ͘

    View Slide