Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
LLVM Tutorial 02 - わいわいswiftc
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
sonson
March 01, 2019
Programming
460
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
LLVM Tutorial 02 - わいわいswiftc
LLVMチュートリアルをやってみよう.
今回は第3章くらいまでです.
sonson
March 01, 2019
More Decks by sonson
See All by sonson
計算グラフのJITコンパイラをLLVM on C++で作ろう
sonsongithub
2
620
LLVMでHalideみたいな計算グラフ+JITを作りたい
sonsongithub
0
1.6k
LLVM Tutorial - わいわいswiftc
sonsongithub
0
350
How to make and publish a Swift playground book for iPad
sonsongithub
5
19k
Swiftで実装するHTML特殊文字の高速処理
sonsongithub
3
8k
First step of 3D touch
sonsongithub
0
710
Getting started with 3D Touch
sonsongithub
0
800
SSLって必要ですか〜Let's Encryptを試してみよう
sonsongithub
3
600
Other Decks in Programming
See All in Programming
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
330
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
590
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
810
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
180
【やさしく解説 設計編・中級 #4】ルールの寿命と、システムの年輪
panda728
PRO
2
150
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
500
吝嗇家のためのAI活用 / AI development for miser - ChatGPT + Issue Driven Development
tooppoo
0
190
えっ!!コードを読まずに開発を!?
hananouchi
0
220
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.6k
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
490
OSINT for SRE: 学術論文とポストモーテムから探る システム障害の共通パターン / SRE NEXT 2026
tomoyk
1
3.9k
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
140
Featured
See All Featured
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
67
56k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.7k
Prompt Engineering for Job Search
mfonobong
0
380
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
180
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
390
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
260
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
900
It's Worth the Effort
3n
188
29k
Typedesign – Prime Four
hannesfritz
42
3.1k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
360
Site-Speed That Sticks
csswizardry
13
1.3k
Skip the Path - Find Your Career Trail
mkilby
1
170
Transcript
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
https://peaks.cc/books/iOS12
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 }
LLVMͱʁ • ίϯύΠϥ։ൃج൫ • ίϯύΠϥΛ࡞ΔͨΊͷϥΠϒϥϦ • C++Ͱॻ͔Ε͍ͯΔ • ෭࢈ •
LLDB • clang • GNU GCC͕ංେԽ͗ͨ͢͠ର߅അ • dragoneggͱݺΕΔgccͷόοΫΤϯυ͋Δ • libc++
$ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT LLVMΛͬͯ࡞Δ ͜ͷPass͕ॏཁ ৭ʑ༻ҙ͞Ε͍ͯΔ͠ ࣗͰ࡞ΕΔ
x86, ARM, ia64, i386ɾɾɾͳͲ όΠφϦͷมLLVMͷϞδϡʔϧ
ΦϨΦϨ ݴޠ --7.*3 1BTT όΠφϦ ίϯύΠϥ 1BTT ͑͜͜͞࡞Ε ͋ͱLLVMʹͤΒΕΔ
Swiftͷ߹ 4XJGU 4*- 4*- ܕ੍ 4*- 3"8 4*- ࠷దԽ --7.*3
4XJGU*OUFSNFEJBUF-BOHVBHF
Ԡ༻ BSN " " 4
Ԡ༻ BSN " " 4 BSN " " 4 BSN
" " 4 BSN " " 4 BSN " " 4
Ԡ༻ CJUDPEF " " 4 BSN --7.Λ͍ ֤σόΠε͚ ʹ࠷దԽ
ͳͥɼLLVMʁ • ੈͷதͷྲྀΕ • ϜʔΞͷ๏ଇͷݶք • CPUͷྔతਐԽɼݶքʹ͍͍ۙͮͯΔʢཧతʣ • ճආ͢Δʹʁ •
ฒྻԽ • CPUສೳ͗͢ΔˠGPU, FPGA, ASIC • ͲΕ։ൃ͕ࠓ·Ͱͷͱҧ͍͗ͯ͢ࠔۃ·Δ ιϑτΣΞͷ։ൃํ๏͕৭ʑࢼ͞Ε͍ͯΔ
͜͜ͷ • 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͕ग़ͯ͘Δ
[11]
Halide [10] • εϨου • SIMD • GPU • ͳͲͳͲɾɾɾ
Halide HalideͳΒɼ͜ͷίʔυͰશͯͷڥʹϙʔτͰ͖Δ [10] • εϨου • SIMD • GPU •
ͳͲͳͲɾɾɾ
·ͱΊΔͱ • ࠷ۙͷίϯύΠϥLLVM • HalideͳͲΛར༻͢ΔʹLLVM • ΓɼLLVMΛΒͳ͍ͱલʹਐΊͳ͍
LLVM Tutorial • LLVMΛͬͯΦϨΦϨݴޠͷίϯύΠϥΛ࡞Δ • C++ͰllvmΛϥΠϒϥϦͱͯ͠ɼίϯύΠϥΛ։ൃ • ಡΉͷʹඞཁͳεΩϧ • C++
• ӳޠ • ͳΜ͔brokenͩͬͨΓɼ͚ͩͨ͘ײ͡ • ਖ਼ɼจ͕͗ͯ͢ಡΊͳ͔ͬͨΓɼ͋Μ·ϝϯς φϯε͞Εͯͳ͍ͱ͜Ζ͋Δ
LLVM Tutorialͱʁ • Tutorials about using LLVM. Includes a tutorial
about making a custom language with LLVM.
ϝϞॻ͖ͳͲ • https://github.com/sonsongithub/llvm-tutorial • LLVM Release Licenseʹج͖ͮɼ༁ϝϞΛެ։ ͍ͯ͠·͢
TutorialͷϏϧυʹ͍ͭͯ • 7.0Chapter4Ҏ߱ɼStandard libraryͷؔΛϦ ϯΫͯ͠Δαϯϓϧ͑ͳ͍ • ֎෦ͷAPIݺͼग़͠ʹࣦഊͯ͠Ϋϥογϡ͢Δ • 6.0OK •
github͔ΒνΣοΫΞτ͠ɼϏϧυ͢Δͷ͕ྑ͍ • ֬ೝͨ͠ڥ • macOS, brewͱιʔε͔ΒϏϧυ • Linux, aptͷύοέʔδͱιʔε͔ΒϏϧυ
ίϯύΠϥͷதʹ /// ίϯύΠϥͷதͰɼ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; }
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`
༁ • ͡Ίʹ • ύʔαͱநߏจ • LLVM IRίʔυੜ • JITͱ࠷దԽ
• ੍ޚϑϩʔ • ԋࢉࢠͷఆٛ • mutableͷಋೖ • ίϯύΠϧ • σόοάใ • ·ͱΊ
LLVM IRͷಛ • Ϩδελɼมແݶʹ͋Δ • ̏൪ίʔυΈ͍ͨͳײ͡ • SSA(Static Single Assignment
form) • ੩త୯ҰೖɾɾɾมมԽ͠ͳ͍ • ܕݫີ a = (b + c) ∗ d ʢʴɼ̱ɼ̲ɼtmpaddʣ ʢˎɼtmpaddɼ̳ɼaʣ
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 }
։ൃ͢ΔݴޠKaleidoscope • ඪͱ༷ • doubleܕͷΈ • ͕ؔ͑Δ • Standard libraryͷؔΛ͑Δ
• if/elseจ • forจ • Ϣʔβఆٛԋࢉࢠ • REPL/JIT
࠷ॳ • ̍ߦΛίϯύΠϧ͢Δ • มͳ͍ • ؔ͋Δ • math.hͱ͔͑Δ •
if/else/forจͳ͠ɾɾɾޙ͔ΒՃ • ͭ·ΓνϡʔϦϯάશͰͳ͍
͜Ε͔ΒC++Ͱ࡞Δͷ ,BMFJEPTDPQFͷιʔείʔυ ΦϨΦϨݴޠͷιʔείʔυ ίϯύΠϥ --7.*3όΠφϦ ,BMFJEPTDPQFΛղऍ͠ --7.Λͬͯɼ--7.*3Λੜ͠ɼ όΠφϦΛు͘ ͭ·ΓɼC++Ͱݴޠͷ༷Λॻ͍͍ͯ͘ײ͡
࠷ॳͷҰาʙޠኮղੳ(Lexer) • ·ͣιʔείʔυΛݻ·Γʹׂ͍ͯ͘͠ extern cos(0.1); ֎෦એݴ tok_extern Կ͔ͷࣝผࢠ tok_identifier τʔΫϯ
tok_number ΧοίͱηϛίϩϯޠኮʹͨΒͳ͍ͷͰɼ ͱΓ͋͑ͣඈ͢
ୈೋาʙநߏจ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body
BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌʹج͖ͮɼਂ͞༏ઌͰߏจΛ࡞͍ͬͯ͘
நߏจͷΫϥε class ExprAST { public: virtual ~ExprAST() = default; virtual
Value *codegen() = 0; };
มΛอ࣋͢Δϊʔυ class VariableExprAST : public ExprAST { std::string Name; public:
VariableExprAST(const std::string &Name) : Name(Name) {} Value *codegen() override; };
ೋ߲ԋࢉࢠ 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; };
ؔએݴ 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; } };
࣮ؔ 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(); };
நߏจ def hoge(a b c) a+(b+c); FunctionAST Proto PrototypeAST Body
BinaryExprAST - + LHS VariableExprAST - a RHS BinaryExprAST - + LHS VariableExprAST - b RHS VariableExprAST - c ԋࢉࢠͷ༏ઌʹج͖ͮɼਂ͞༏ઌͰߏจΛ࡞͍ͬͯ͘
நߏจ def hoge(a b c) a+b+c; FunctionAST Proto PrototypeAST Body
BinaryExprAST - + LHS VariableExprAST - c RHS BinaryExprAST - + LHS VariableExprAST - a RHS VariableExprAST - b ԋࢉࢠͷ༏ઌʹج͖ͮɼਂ͞༏ઌͰߏจΛ࡞͍ͬͯ͘
LLVM IRΛੜ͢Δ class ExprAST { public: virtual ~ExprAST() = default;
virtual Value *codegen() = 0; }; ֤ϊʔυ͔ΒLLVM IRΛੜ͢Δ ߏจͷϊʔυ͝ͱʹੜͷͨΊͷίʔυΛ࣮͍ͯ͘͠
codegenͷࣄ • llvm::ValueΫϥεΛฦ͢ • ͜ͷΫϥε͕LLVM IRΛు͍ͯ͘ΕΔ • llvm::Value • ੩త୯ҰೖϨδελΛࣔ͢
if (auto *FnIR = ProtoAST->codegen()) { fprintf(stderr, "Read extern: "); FnIR->print(errs()); fprintf(stderr, "\n"); }
ೋ߲ԋࢉࢠͷ߹ 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"); } } ܭࢉ݁ՌΛอଘ͢ΔϨδελ໊
ؔએݴ 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; }
࣮ؔ 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);
࣮ؔ // 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; }
நߏจ͔Β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
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
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
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 ^
·ͱΊ • LLVMʹ͍ͭͯ • എܠɼྺ࢙ɼԠ༻ • LLVM Tutorial • நߏจ
• LLVM IRͷੜ • ͔͜͜Β͕͓͠Ζ͍ • PassʹΑΔ࠷దԽ • ੍ޚϑϩʔͷ࣮ • mutableมͷಋೖ
ଓ͘