LLVM Воронин Дмитрий Agenda • • • • • • Что такое LLVM LLVM проекты Промежуточное представление LLVM Пример создания новой фазы компиляции в LLVM Пример внедрения новой фазы в компилятор clang Пример использования JIT компиляции в LLVM 2 LLVM • LLVM – набор средств разработки (компиляторы, ассемблеры, дебаггеры, библиотеки и пр.), тесно связанных между собой. • Идея разработки: - создать блоки (библиотеки), из которых можно «собирать» готовые решения (или внедрять блоки в свои проекты) - максимально переиспользовать разработанный код • Примеры: - использование парсера фронтенда для нужд IDE (индексирование, подсветка ситаксиса, рефакторинг) - использование единого промежуточного представление (IR) для всех входных языков, как для статической так и для динамической компиляции. 3 LLVM проекты • Clang – C/C++/Objective-C фронтент • DragonEgg – плагин к GCC, заменяющий GCC оптимизатор LLVM’овским • LLDB – дебаггер (для Mac OS X) • Libc++ - реализация C++ библиотеки для нового стандарта C++’0X • VMKit – реализация Java Virtual Machine 4 СПО проекты (на базе LLVM) • Crack – скриптовый язык программирования, объединяющий парадигмы C++, Java, Python • TCE – TTA-based Co-design Environment (TTA – Transport Triggered Architecture), тулчейн для преобразования C/C++ программы в VHDL • PinaVM – SystemC фронтенд, SystemC – язык для системного моделирования, дизайна и верификации • IcedTea – замена «несвободных» компонент в OpenJDK • GHC – Glasgow Haskel Compiler • Rubinius – реализация Ruby • FAUST – Functional AUdio Stream (real time audio signal processing language) 5 Проприетарные проекты (на базе LLVM) • • • • • Компилятор фирмы Apple Копилятор GPGPU фирмы Nvidia Компилятор GPGPU фирмы AMD Компилятор фирмы RapidMind (куплена фирмой Intel) Portable Native Client фирмы Google 6 LLVM IRs AST LLVM IR C Fortran CodeGen IR X86 Backend Optimizer Ada Power PC Backend ARM Backend 7 Основные объекты LLVM IR LLVMContext - Instruction constants maps and predefined constants types maps and predefined types map of value handles list of global variables and aliases values and types sym-tabs list of functions Function - list of arguments list of basic blocks values sym-tab BasicBlock - list of uses result type Use - pointer to argument (Value) Module - - list of instructions 8 Constant Type Типы Type* DerivedType IntegerType CompositeType StructType ArrayType FunctionType OpaqueType SequentialType VectorType *Type has a list of it’s uses 9 PointerType Значения Value Argument User* Constant BasicBlock Instruction * User has a list of it’s uses 10 Константы Constant ConstantInt ConstantFP ConstantArray ConstantStruct ConstantVector BlockAddress ConstantExpr UnaryConstantExpr BinaryConstantExpr GetElementPtrConstantExpr SelectConstantExpr ExtractElementConstantExpr InsertElementConstantExpr ShuffleVectorConstantExpr ExtractValueConstantExpr InsertValueConstantExpr CompareConstantExpr 11 GlobalValue BlockAddress GlobalVariable GlobalAlias Function Инструкции Instruction StoreInst GetElementPtrInst SelectInst BinaryOperator CallInst UnaryInstruction TerminatorInst CmpInst _other_ CastInst AllocaInst LoadInst VAArgInst ExtractValueInst TruncInst ZExtInst SExtInst FPTruncInst FPExtInst UIToFPInst SIToFPInst FPToUIInst FPToSIInst IntToPtrInst PtrToIntInst BitCastInst ICmpInst FCmpInst ReturnInst BranchInst SwitchInst IndirectInst InvokeInst UnwindInst UnreachableInst 12 Специальные инструкции (intrinsic) CallInst IntrinsicInst MemIntrinsic EHExceptionIntrinsic EHSelectIntrinsic MemSetInst MemTransferInst MemCpyInst MemMoveInst 13 DbgInfoIntrinsic DbgDeclareInst DbgValueInst Пример IR int foo( int *a, int size) { int i, sum = 0; for( i=0; i<size; i++) sum += a[i]; return sum; define i32 @foo(i32* %a, i32 %size) { ;<label>:0 %1 = icmp sgt i32 %size, 0 br i1 %1, label %1, label %3 ;<label>:1 ; preds = %1, %0 %i.1 = phi i32 [ 0, %0 ], [ %i.2, %1 ] %sum.1 = phi i32 [ 0, %1 ], [ %4, %1 ] } %gep = getelementptr i32* %a, i32 %i.1 %3 = load i32* %gep %4 = add i32 %3, %sum.1 %i.2 = add i32 %i.1, 1 %p = icmp eq i32 %i.2, %size br i1 %p, label %2, label %1 ;<label>:2 ; preds = %1, %0 %sum.2 = phi i32 [ 0, %0 ], [ %4, %1 ] ret i32 %sum.2 } 14 Приведения объектов IR (isa, cast, dyn_cast) Каждый класс реализует метод static inline bool classof( Value* val); template < class X, class Y > inline bool isa( Y *val); template < class X, class Y > inline X cast( Y *val); template < class X, class Y> inline X dyn_cast( Y *val); for ( BasicBlock::iterator it = bb->begin(), …) { Instruction *inst = it; if ( isa< BranchInst >( inst) ) { // inst можно привести к BranchInst BranchInst *br = cast< BranchInst >( inst); } if ( InvokeInst *invoke = dyn_cast< InvokeInst >( inst) ) { // invoke приведен к InvokeInst } } 15 QA 16