diff --git a/docs/videos.org b/docs/videos.org index 3d03729..292d8b7 100644 --- a/docs/videos.org +++ b/docs/videos.org @@ -1,7 +1,7 @@ #+TITLE: How to build a compiler with LLVM and MLIR #+SEQ_TODO: TODO(t/!) NEXT(n/!) BLOCKED(b@/!) | DONE(d%) CANCELLED(c@/!) FAILED(f@/!) #+TAGS: READER(r) MISC(m) -#+STARTUP: logdrawer logdone logreschedule indent content align constSI entitiespretty +#+STARTUP: logdrawer logdone logreschedule indent content align constSI entitiespretty overview * DONE Episode 1 - Introduction ** What is it all about? @@ -159,7 +159,8 @@ We need to reform the AST to reflect the semantics of Serene closly. Let's run the compiler to see the semantic analysis in action. ** Let's check out the code -* Episode 7 - The Context and Namespace +* DONE Episode 7 - The Context and Namespace +CLOSED: [2021-09-04 Sat 10:53] ** Namespaces *** Unit of compilation *** Usually maps to a file @@ -169,3 +170,208 @@ Let's run the compiler to see the semantic analysis in action. *** The owner of LLVM/MLIR contexts *** Holds the namespace table *** Probably will contain the primitive types as well +* Episode 8 - MLIR Basics +** Serene Changes +- Introducing a SourceManager +- Reader changes +- *serenec* cli interface in changing + +** Disclaimer +*I'm not an expert in MLIR* + +** Why? +- A bit of history +- LLVM IR is to low level +- We need an IR to implement high level concepts and flows + *MLIR* is a framework to build a compiler with your own IR. kinda :P + +- Reusability +- ... +** Language +*** Overview +- SSA Based (https://en.wikipedia.org/wiki/Static_single_assignment_form) +- Typed +- Context free(for lack of better words) + +*** Dialects +- A collection of operations +- Custom types +- Meta data +- We can use a mixture of different dialects +**** builtin dialects: +- std +- llvm +- math +- async +- ... + +*** Opetations +- Higher level of abstraction +- Not instructions +- SSA forms +- Tablegen backend +- Verifiers and printers +*** Attributes +*** Blocks & Regions +*** Types +- Extesible +** Pass Infrastructure +Analysis and transformation infrastructure + +- We will implement most of our semantic analysis logic and type checker as passes + +** Pattern Rewriting +- Tablegen backed +** Operation Definition Specification +** Examples +*Not*: You need =mlir-mode= and =llvm-mode= available to you for the code highlighting of +the following code blocks. Both of those are distributed with the LLVM. + +*** General syntax +#+BEGIN_SRC mlir + %result:2 = "somedialect.blah"(%x#2) { some.attribute = true, other_attribute = 3 } + : (!somedialect<"example_type">) -> (!somedialect<"foo_s">, i8) + loc(callsite("main" at "main.srn":10:8)) +#+END_SRC + +*** Blocks and Regions +#+BEGIN_SRC mlir + func @simple(i64, i1) -> i64 { + ^bb0(%a: i64, %cond: i1): // Code dominated by ^bb0 may refer to %a + cond_br %cond, ^bb1, ^bb2 + + ^bb1: + br ^bb3(%a: i64) // Branch passes %a as the argument + + ^bb2: + %b = addi %a, %a : i64 + br ^bb3(%b: i64) // Branch passes %b as the argument + + // ^bb3 receives an argument, named %c, from predecessors + // and passes it on to bb4 along with %a. %a is referenced + // directly from its defining operation and is not passed through + // an argument of ^bb3. + ^bb3(%c: i64): + //br ^bb4(%c, %a : i64, i64) + "serene.ifop"(%c) ({ // if %a is in-scope in the containing region... + // then %a is in-scope here too. + %new_value = "another_op"(%c) : (i64) -> (i64) + + ^someblock(%new_value): + %x = "some_other_op"() {value = 4 : i64} : () -> i64 + + }) : (i64) -> (i64) + ^bb4(%d : i64, %e : i64): + %0 = addi %d, %e : i64 + return %0 : i64 // Return is also a terminator. + } +#+END_SRC + +*** SLIR example +Command line arguments to emir =slir= +#+BEGIN_SRC sh + ./builder run --build-dir ./build -emit slir `pwd`/docs/examples/hello_world.srn +#+END_SRC + +Output: +#+BEGIN_SRC mlir + module @user { + %0 = "serene.fn"() ( { + %2 = "serene.value"() {value = 0 : i64} : () -> i64 + return %2 : i64 + }) {args = {}, name = "main", sym_visibility = "public"} : () -> i64 + + %1 = "serene.fn"() ( { + %2 = "serene.value"() {value = 0 : i64} : () -> i64 + return %2 : i64 + }) {args = {n = i64, v = i64, y = i64}, name = "main1", sym_visibility = "public"} : () -> i64 + } +#+END_SRC + +*** Serene's MLIR (maybe we need a better name) + +Command line arguments to emir =mlir= +#+BEGIN_SRC sh + ./builder run --build-dir ./build -emit mlir `pwd`/docs/examples/hello_world.srn +#+END_SRC + +Output: +#+BEGIN_SRC mlir +module @user { + func @main() -> i64 { + %c3_i64 = constant 3 : i64 + return %c3_i64 : i64 + } + func @main1(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %c3_i64 = constant 3 : i64 + return %c3_i64 : i64 + } +} +#+END_SRC + +*** LIR +Command line arguments to emir =lir= +#+BEGIN_SRC sh + ./builder run --build-dir ./build -emit lir `pwd`/docs/examples/hello_world.srn +#+END_SRC + +Output: +#+BEGIN_SRC mlir +module @user { + llvm.func @main() -> i64 { + %0 = llvm.mlir.constant(3 : i64) : i64 + llvm.return %0 : i64 + } + llvm.func @main1(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 { + %0 = llvm.mlir.constant(3 : i64) : i64 + llvm.return %0 : i64 + } +} +#+END_SRC + +*** LLVMIR +Command line arguments to emir =llvmir= +#+BEGIN_SRC sh + ./builder run --build-dir ./build -emit ir `pwd`/docs/examples/hello_world.srn +#+END_SRC + +Output: +#+BEGIN_SRC llvm +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare i8* @malloc(i64 %0) + +declare void @free(i8* %0) + +define i64 @main() !dbg !3 { + ret i64 3, !dbg !7 +} + +define i64 @main1(i64 %0, i64 %1, i64 %2) !dbg !9 { + ret i64 3, !dbg !10 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "mlir", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "LLVMDialectModule", directory: "/") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "main", linkageName: "main", scope: null, file: !4, type: !5, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6) +!4 = !DIFile(filename: "REPL", directory: "/home/lxsameer/src/serene/serene/build") +!5 = !DISubroutineType(types: !6) +!6 = !{} +!7 = !DILocation(line: 0, column: 10, scope: !8) +!8 = !DILexicalBlockFile(scope: !3, file: !4, discriminator: 0) +!9 = distinct !DISubprogram(name: "main1", linkageName: "main1", scope: null, file: !4, line: 1, type: !5, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !6) +!10 = !DILocation(line: 1, column: 11, scope: !11) +!11 = !DILexicalBlockFile(scope: !9, file: !4, discriminator: 0) +#+END_SRC + +** Resources +- [[https://www.youtube.com/watch?v=Y4SvqTtOIDk][2020 LLVM Developers’ Meeting: M. Amini & R. Riddle “MLIR Tutorial”]] +- [[https://www.youtube.com/watch?v=qzljG6DKgic][2019 EuroLLVM Developers’ Meeting: T. Shpeisman & C. Lattner “MLIR: Multi-Level Intermediate Repr..”]] +- https://mlir.llvm.org/docs +- https://mlir.llvm.org/docs/LangRef +- https://en.wikipedia.org/wiki/Basic_block