From 73e25a571f12d3deaa6f4493a5b4792a9dae39eb Mon Sep 17 00:00:00 2001 From: johannst Date: Sat, 24 Sep 2022 22:38:40 +0000 Subject: deploy: 295081130ca1eed6e67dfc035e2df2c9ed49b174 --- src/llvm_kaleidoscope_rs/codegen.rs.html | 596 ++++++++++++++---- src/llvm_kaleidoscope_rs/lexer.rs.html | 286 +++++---- src/llvm_kaleidoscope_rs/lib.rs.html | 218 +++---- src/llvm_kaleidoscope_rs/llvm/basic_block.rs.html | 87 +++ src/llvm_kaleidoscope_rs/llvm/builder.rs.html | 430 +++++++++---- src/llvm_kaleidoscope_rs/llvm/lljit.rs.html | 234 +++---- src/llvm_kaleidoscope_rs/llvm/mod.rs.html | 56 +- src/llvm_kaleidoscope_rs/llvm/module.rs.html | 276 +++++---- src/llvm_kaleidoscope_rs/llvm/pass_manager.rs.html | 36 +- src/llvm_kaleidoscope_rs/llvm/type_.rs.html | 42 +- src/llvm_kaleidoscope_rs/llvm/value.rs.html | 396 ++++++++---- src/llvm_kaleidoscope_rs/parser.rs.html | 682 ++++++++++++++++----- 12 files changed, 2283 insertions(+), 1056 deletions(-) create mode 100644 src/llvm_kaleidoscope_rs/llvm/basic_block.rs.html (limited to 'src/llvm_kaleidoscope_rs') diff --git a/src/llvm_kaleidoscope_rs/codegen.rs.html b/src/llvm_kaleidoscope_rs/codegen.rs.html index e94ac8d..44ee848 100644 --- a/src/llvm_kaleidoscope_rs/codegen.rs.html +++ b/src/llvm_kaleidoscope_rs/codegen.rs.html @@ -1,102 +1,108 @@ -codegen.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+codegen.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -160,12 +166,171 @@
 160
 161
 162
-
-use std::collections::HashMap;
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+
use std::collections::HashMap;
 
-use crate::llvm::{FnValue, FunctionPassManager, IRBuilder, Module, Value};
-use crate::parser::{ExprAST, FunctionAST, PrototypeAST};
-use crate::Either;
+use crate::llvm::{FnValue, FunctionPassManager, IRBuilder, Module, Value};
+use crate::parser::{ExprAST, FunctionAST, PrototypeAST};
+use crate::Either;
 
 type CodegenResult<T> = Result<T, String>;
 
@@ -181,9 +346,9 @@
     /// Compile either a [`PrototypeAST`] or a [`FunctionAST`] into the LLVM `module`.
     pub fn compile(
         module: &'llvm Module,
-        fn_protos: &mut HashMap<String, PrototypeAST>,
+        fn_protos: &mut HashMap<String, PrototypeAST>,
         compilee: Either<&PrototypeAST, &FunctionAST>,
-    ) -> CodegenResult<FnValue<'llvm>> {
+    ) -> CodegenResult<FnValue<'llvm>> {
         let mut cg = Codegen {
             module,
             builder: &IRBuilder::with_ctx(module),
@@ -193,40 +358,40 @@
         let mut variables = HashMap::new();
 
         match compilee {
-            Either::A(proto) => Ok(cg.codegen_prototype(proto)),
-            Either::B(func) => cg.codegen_function(func, &mut variables),
+            Either::A(proto) => Ok(cg.codegen_prototype(proto)),
+            Either::B(func) => cg.codegen_function(func, &mut variables),
         }
     }
 
     fn codegen_expr(
         &self,
         expr: &ExprAST,
-        named_values: &mut HashMap<&'llvm str, Value<'llvm>>,
-    ) -> CodegenResult<Value<'llvm>> {
+        named_values: &mut HashMap<String, Value<'llvm>>,
+    ) -> CodegenResult<Value<'llvm>> {
         match expr {
-            ExprAST::Number(num) => Ok(self.module.type_f64().const_f64(*num)),
-            ExprAST::Variable(name) => match named_values.get(name.as_str()) {
-                Some(value) => Ok(*value),
-                None => Err("Unknown variable name".into()),
+            ExprAST::Number(num) => Ok(self.module.type_f64().const_f64(*num)),
+            ExprAST::Variable(name) => match named_values.get(name.as_str()) {
+                Some(value) => Ok(*value),
+                None => Err("Unknown variable name".into()),
             },
-            ExprAST::Binary(binop, lhs, rhs) => {
+            ExprAST::Binary(binop, lhs, rhs) => {
                 let l = self.codegen_expr(lhs, named_values)?;
                 let r = self.codegen_expr(rhs, named_values)?;
 
                 match binop {
-                    '+' => Ok(self.builder.fadd(l, r)),
-                    '-' => Ok(self.builder.fsub(l, r)),
-                    '*' => Ok(self.builder.fmul(l, r)),
-                    '<' => {
+                    '+' => Ok(self.builder.fadd(l, r)),
+                    '-' => Ok(self.builder.fsub(l, r)),
+                    '*' => Ok(self.builder.fmul(l, r)),
+                    '<' => {
                         let res = self.builder.fcmpult(l, r);
                         // Turn bool into f64.
                         Ok(self.builder.uitofp(res, self.module.type_f64()))
                     }
-                    _ => Err("invalid binary operator".into()),
+                    _ => Err("invalid binary operator".into()),
                 }
             }
-            ExprAST::Call(callee, args) => match self.get_function(callee) {
-                Some(callee) => {
+            ExprAST::Call(callee, args) => match self.get_function(callee) {
+                Some(callee) => {
                     if callee.args() != args.len() {
                         return Err("Incorrect # arguments passed".into());
                     }
@@ -237,21 +402,181 @@
                         .map(|arg| self.codegen_expr(arg, named_values))
                         .collect::<CodegenResult<_>>()?;
 
-                    Ok(self.builder.call(callee, &mut args))
+                    Ok(self.builder.call(callee, &mut args))
                 }
-                None => Err("Unknown function referenced".into()),
+                None => Err("Unknown function referenced".into()),
             },
+            ExprAST::If { cond, then, else_ } => {
+                // For 'if' expressions we are building the following CFG.
+                //
+                //         ; cond
+                //         br
+                //          |
+                //    +-----+------+
+                //    v            v
+                //  ; then       ; else
+                //    |            |
+                //    +-----+------+
+                //          v
+                //        ; merge
+                //        phi then, else
+                //        ret phi
+
+                let cond_v = {
+                    // Codgen 'cond' expression.
+                    let v = self.codegen_expr(cond, named_values)?;
+                    // Compare 'v' against '0' as 'one = ordered not equal'.
+                    self.builder
+                        .fcmpone(v, self.module.type_f64().const_f64(0f64))
+                };
+
+                // Get the function we are currently inserting into.
+                let the_function = self.builder.get_insert_block().get_parent();
+
+                // Create basic blocks for the 'then' / 'else' expressions as well as the return
+                // instruction ('merge').
+                //
+                // Append the 'then' basic block to the function, don't insert the 'else' and
+                // 'merge' basic blocks yet.
+                let then_bb = self.module.append_basic_block(the_function);
+                let else_bb = self.module.create_basic_block();
+                let merge_bb = self.module.create_basic_block();
+
+                // Create a conditional branch based on the result of the 'cond' expression.
+                self.builder.cond_br(cond_v, then_bb, else_bb);
+
+                // Move to 'then' basic block and codgen the 'then' expression.
+                self.builder.pos_at_end(then_bb);
+                let then_v = self.codegen_expr(then, named_values)?;
+                // Create unconditional branch to 'merge' block.
+                self.builder.br(merge_bb);
+                // Update reference to current basic block (in case the 'then' expression added new
+                // basic blocks).
+                let then_bb = self.builder.get_insert_block();
+
+                // Now append the 'else' basic block to the function.
+                the_function.append_basic_block(else_bb);
+                // Move to 'else' basic block and codgen the 'else' expression.
+                self.builder.pos_at_end(else_bb);
+                let else_v = self.codegen_expr(else_, named_values)?;
+                // Create unconditional branch to 'merge' block.
+                self.builder.br(merge_bb);
+                // Update reference to current basic block (in case the 'else' expression added new
+                // basic blocks).
+                let else_bb = self.builder.get_insert_block();
+
+                // Now append the 'merge' basic block to the function.
+                the_function.append_basic_block(merge_bb);
+                // Move to 'merge' basic block.
+                self.builder.pos_at_end(merge_bb);
+                // Codegen the phi node returning the appropriate value depending on the branch
+                // condition.
+                let phi = self.builder.phi(
+                    self.module.type_f64(),
+                    &[(then_v, then_bb), (else_v, else_bb)],
+                );
+
+                Ok(*phi)
+            }
+            ExprAST::For {
+                var,
+                start,
+                end,
+                step,
+                body,
+            } => {
+                // For 'for' expression we build the following structure.
+                //
+                // entry:
+                //   init = start expression
+                //   br loop
+                // loop:
+                //   i = phi [%init, %entry], [%new_i, %loop]
+                //   ; loop body ...
+                //   new_i = increment %i by step expression
+                //   ; check end condition and branch
+                // end:
+
+                // Compute initial value for the loop variable.
+                let start_val = self.codegen_expr(start, named_values)?;
+
+                let the_function = self.builder.get_insert_block().get_parent();
+                // Get current basic block (used in the loop variable phi node).
+                let entry_bb = self.builder.get_insert_block();
+                // Add new basic block to emit loop body.
+                let loop_bb = self.module.append_basic_block(the_function);
+
+                self.builder.br(loop_bb);
+                self.builder.pos_at_end(loop_bb);
+
+                // Build phi not to pick loop variable in case we come from the 'entry' block.
+                // Which is the case when we enter the loop for the first time.
+                // We will add another incoming value once we computed the updated loop variable
+                // below.
+                let variable = self
+                    .builder
+                    .phi(self.module.type_f64(), &[(start_val, entry_bb)]);
+
+                // Insert the loop variable into the named values map that it can be referenced
+                // from the body as well as the end condition.
+                // In case the loop variable shadows an existing variable remember the shared one.
+                let old_val = named_values.insert(var.into(), *variable);
+
+                // Generate the loop body.
+                self.codegen_expr(body, named_values)?;
+
+                // Generate step value expression if available else use '1'.
+                let step_val = if let Some(step) = step {
+                    self.codegen_expr(step, named_values)?
+                } else {
+                    self.module.type_f64().const_f64(1f64)
+                };
+
+                // Increment loop variable.
+                let next_var = self.builder.fadd(*variable, step_val);
+
+                // Generate the loop end condition.
+                let end_cond = self.codegen_expr(end, named_values)?;
+                let end_cond = self
+                    .builder
+                    .fcmpone(end_cond, self.module.type_f64().const_f64(0f64));
+
+                // Get current basic block.
+                let loop_end_bb = self.builder.get_insert_block();
+                // Add new basic block following the loop.
+                let after_bb = self.module.append_basic_block(the_function);
+
+                // Register additional incoming value for the loop variable. This will choose the
+                // updated loop variable if we are iterating in the loop.
+                variable.add_incoming(next_var, loop_end_bb);
+
+                // Branch depending on the loop end condition.
+                self.builder.cond_br(end_cond, loop_bb, after_bb);
+
+                self.builder.pos_at_end(after_bb);
+
+                // Restore the shadowed variable if there was one.
+                if let Some(old_val) = old_val {
+                    // We inserted 'var' above so it must exist.
+                    *named_values.get_mut(var).unwrap() = old_val;
+                } else {
+                    named_values.remove(var);
+                }
+
+                // Loops just always return 0.
+                Ok(self.module.type_f64().const_f64(0f64))
+            }
         }
     }
 
-    fn codegen_prototype(&self, PrototypeAST(name, args): &PrototypeAST) -> FnValue<'llvm> {
+    fn codegen_prototype(&self, PrototypeAST(name, args): &PrototypeAST) -> FnValue<'llvm> {
         let type_f64 = self.module.type_f64();
 
         let mut doubles = Vec::new();
         doubles.resize(args.len(), type_f64);
 
         // Build the function type: fn(f64, f64, ..) -> f64
-        let ft = self.module.type_fn(&mut doubles, type_f64);
+        let ft = self.module.type_fn(&mut doubles, type_f64);
 
         // Create the function declaration.
         let f = self.module.add_fn(name, ft);
@@ -265,10 +590,10 @@
     }
 
     fn codegen_function(
-        &mut self,
+        &mut self,
         FunctionAST(proto, body): &FunctionAST,
-        named_values: &mut HashMap<&'llvm str, Value<'llvm>>,
-    ) -> CodegenResult<FnValue<'llvm>> {
+        named_values: &mut HashMap<String, Value<'llvm>>,
+    ) -> CodegenResult<FnValue<'llvm>> {
         // Insert the function prototype into the `fn_protos` map to keep track for re-generating
         // declarations in other modules.
         self.fn_protos.insert(proto.0.clone(), proto.clone());
@@ -290,7 +615,7 @@
         // Update the map with the current functions args.
         for idx in 0..the_function.args() {
             let arg = the_function.arg(idx);
-            named_values.insert(arg.get_name(), arg);
+            named_values.insert(arg.get_name().into(), arg);
         }
 
         // Codegen function body.
@@ -311,10 +636,10 @@
     /// If the function is not available in the module, check if the prototype is known and codegen
     /// it.
     /// Return [`None`] if the prototype is not known.
-    fn get_function(&self, name: &str) -> Option<FnValue<'llvm>> {
+    fn get_function(&self, name: &str) -> Option<FnValue<'llvm>> {
         let callee = match self.module.get_fn(name) {
-            Some(callee) => callee,
-            None => {
+            Some(callee) => callee,
+            None => {
                 let proto = self.fn_protos.get(name)?;
                 self.codegen_prototype(proto)
             }
@@ -323,7 +648,6 @@
         Some(callee)
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/lexer.rs.html b/src/llvm_kaleidoscope_rs/lexer.rs.html index 4b13fd9..2249ba0 100644 --- a/src/llvm_kaleidoscope_rs/lexer.rs.html +++ b/src/llvm_kaleidoscope_rs/lexer.rs.html @@ -1,102 +1,108 @@ -lexer.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+lexer.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -179,8 +185,32 @@
 179
 180
 181
-
-#[derive(Debug, PartialEq)]
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+
#[derive(Debug, PartialEq)]
 pub enum Token {
     Eof,
     Def,
@@ -188,6 +218,11 @@
     Identifier(String),
     Number(f64),
     Char(char),
+    If,
+    Then,
+    Else,
+    For,
+    In,
 }
 
 pub struct Lexer<I>
@@ -202,12 +237,12 @@
 where
     I: Iterator<Item = char>,
 {
-    pub fn new(mut input: I) -> Lexer<I> {
+    pub fn new(mut input: I) -> Lexer<I> {
         let last_char = input.next();
         Lexer { input, last_char }
     }
 
-    fn step(&mut self) -> Option<char> {
+    fn step(&mut self) -> Option<char> {
         self.last_char = self.input.next();
         self.last_char
     }
@@ -215,7 +250,7 @@
     /// Lex and return the next token.
     ///
     /// Implement `int gettok();` from the tutorial.
-    pub fn gettok(&mut self) -> Token {
+    pub fn gettok(&mut self) -> Token {
         // Eat up whitespaces.
         while matches!(self.last_char, Some(c) if c.is_ascii_whitespace()) {
             self.step();
@@ -242,21 +277,26 @@
             }
 
             match ident.as_ref() {
-                "def" => return Token::Def,
-                "extern" => return Token::Extern,
-                _ => {}
+                "def" => return Token::Def,
+                "extern" => return Token::Extern,
+                "if" => return Token::If,
+                "then" => return Token::Then,
+                "else" => return Token::Else,
+                "for" => return Token::For,
+                "in" => return Token::In,
+                _ => {}
             }
 
             return Token::Identifier(ident);
         }
 
         // Number: [0-9.]+
-        if last_char.is_ascii_digit() || last_char == '.' {
+        if last_char.is_ascii_digit() || last_char == '.' {
             let mut num = String::new();
             num.push(last_char);
 
             while let Some(c) = self.step() {
-                if c.is_ascii_digit() || c == '.' {
+                if c.is_ascii_digit() || c == '.' {
                     num.push(c)
                 } else {
                     break;
@@ -268,12 +308,12 @@
         }
 
         // Eat up comment.
-        if last_char == '#' {
+        if last_char == '#' {
             loop {
                 match self.step() {
-                    Some(c) if c == '\r' || c == '\n' => return self.gettok(),
-                    None => return Token::Eof,
-                    _ => { /* consume comment */ }
+                    Some(c) if c == '\r' || c == '\n' => return self.gettok(),
+                    None => return Token::Eof,
+                    _ => { /* consume comment */ }
                 }
             }
         }
@@ -360,8 +400,22 @@
         assert_eq!(Token::Identifier("c".into()), lex.gettok());
         assert_eq!(Token::Eof, lex.gettok());
     }
+
+    #[test]
+    fn test_ite() {
+        let mut lex = Lexer::new("if then else".chars());
+        assert_eq!(Token::If, lex.gettok());
+        assert_eq!(Token::Then, lex.gettok());
+        assert_eq!(Token::Else, lex.gettok());
+    }
+
+    #[test]
+    fn test_for() {
+        let mut lex = Lexer::new("for in".chars());
+        assert_eq!(Token::For, lex.gettok());
+        assert_eq!(Token::In, lex.gettok());
+    }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/lib.rs.html b/src/llvm_kaleidoscope_rs/lib.rs.html index 955f3c8..97ad5f7 100644 --- a/src/llvm_kaleidoscope_rs/lib.rs.html +++ b/src/llvm_kaleidoscope_rs/lib.rs.html @@ -1,102 +1,108 @@ -lib.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+lib.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -109,8 +115,7 @@
 109
 110
 111
-
-use std::convert::TryFrom;
+
use std::convert::TryFrom;
 
 pub mod codegen;
 pub mod lexer;
@@ -129,7 +134,7 @@
 impl SmallCStr {
     /// Create a new C string from `src`.
     /// Returns [`None`] if `src` exceeds the fixed size or contains any `\0` bytes.
-    pub fn new<T: AsRef<[u8]>>(src: &T) -> Option<SmallCStr> {
+    pub fn new<T: AsRef<[u8]>>(src: &T) -> Option<SmallCStr> {
         let src = src.as_ref();
         let len = src.len();
 
@@ -146,7 +151,7 @@
     }
 
     /// Return pointer to C string.
-    pub const fn as_ptr(&self) -> *const libc::c_char {
+    pub const fn as_ptr(&self) -> *const libc::c_char {
         self.0.as_ptr().cast()
     }
 }
@@ -154,7 +159,7 @@
 impl TryFrom<&str> for SmallCStr {
     type Error = ();
 
-    fn try_from(value: &str) -> Result<Self, Self::Error> {
+    fn try_from(value: &str) -> Result<Self, Self::Error> {
         SmallCStr::new(&value).ok_or(())
     }
 }
@@ -221,7 +226,6 @@
         assert!(scs.is_err());
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/basic_block.rs.html b/src/llvm_kaleidoscope_rs/llvm/basic_block.rs.html new file mode 100644 index 0000000..581b8e2 --- /dev/null +++ b/src/llvm_kaleidoscope_rs/llvm/basic_block.rs.html @@ -0,0 +1,87 @@ +basic_block.rs - source +
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
use llvm_sys::{core::LLVMGetBasicBlockParent, prelude::LLVMBasicBlockRef};
+
+use std::marker::PhantomData;
+
+use super::FnValue;
+
+/// Wrapper for a LLVM Basic Block.
+#[derive(Copy, Clone)]
+pub struct BasicBlock<'llvm>(LLVMBasicBlockRef, PhantomData<&'llvm ()>);
+
+impl<'llvm> BasicBlock<'llvm> {
+    /// Create a new BasicBlock instance.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `bb_ref` is a null pointer.
+    pub(super) fn new(bb_ref: LLVMBasicBlockRef) -> BasicBlock<'llvm> {
+        assert!(!bb_ref.is_null());
+        BasicBlock(bb_ref, PhantomData)
+    }
+
+    /// Get the raw LLVM value reference.
+    #[inline]
+    pub(super) fn bb_ref(&self) -> LLVMBasicBlockRef {
+        self.0
+    }
+
+    /// Get the function to which the basic block belongs.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn get_parent(&self) -> FnValue<'llvm> {
+        let value_ref = unsafe { LLVMGetBasicBlockParent(self.bb_ref()) };
+        assert!(!value_ref.is_null());
+
+        FnValue::new(value_ref)
+    }
+}
+
+
+ \ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/builder.rs.html b/src/llvm_kaleidoscope_rs/llvm/builder.rs.html index 9ac539b..934351a 100644 --- a/src/llvm_kaleidoscope_rs/llvm/builder.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/builder.rs.html @@ -1,102 +1,108 @@ -builder.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+builder.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -187,11 +193,101 @@
 187
 188
 189
-
-use llvm_sys::{
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+
use llvm_sys::{
     core::{
-        LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFMul, LLVMBuildFSub, LLVMBuildRet, LLVMBuildUIToFP,
-        LLVMCreateBuilderInContext, LLVMDisposeBuilder, LLVMPositionBuilderAtEnd,
+        LLVMAddIncoming, LLVMBuildBr, LLVMBuildCondBr, LLVMBuildFAdd, LLVMBuildFCmp, LLVMBuildFMul,
+        LLVMBuildFSub, LLVMBuildPhi, LLVMBuildRet, LLVMBuildUIToFP, LLVMCreateBuilderInContext,
+        LLVMDisposeBuilder, LLVMGetInsertBlock, LLVMPositionBuilderAtEnd,
     },
     prelude::{LLVMBuilderRef, LLVMValueRef},
     LLVMRealPredicate,
@@ -199,7 +295,7 @@
 
 use std::marker::PhantomData;
 
-use super::{BasicBlock, FnValue, Module, Type, Value};
+use super::{BasicBlock, FnValue, Module, PhiValue, Type, Value};
 
 // Definition of LLVM C API functions using our `repr(transparent)` types.
 extern "C" {
@@ -207,10 +303,10 @@
         arg1: LLVMBuilderRef,
         arg2: Type<'_>,
         Fn: FnValue<'_>,
-        Args: *mut Value<'_>,
+        Args: *mut Value<'_>,
         NumArgs: ::libc::c_uint,
-        Name: *const ::libc::c_char,
-    ) -> LLVMValueRef;
+        Name: *const ::libc::c_char,
+    ) -> LLVMValueRef;
 }
 
 /// Wrapper for a LLVM IR Builder.
@@ -225,7 +321,7 @@
     /// # Panics
     ///
     /// Panics if creating the IR Builder fails.
-    pub fn with_ctx(module: &'llvm Module) -> IRBuilder<'llvm> {
+    pub fn with_ctx(module: &'llvm Module) -> IRBuilder<'llvm> {
         let builder = unsafe { LLVMCreateBuilderInContext(module.ctx()) };
         assert!(!builder.is_null());
 
@@ -238,16 +334,28 @@
     /// Position the IR Builder at the end of the given Basic Block.
     pub fn pos_at_end(&self, bb: BasicBlock<'llvm>) {
         unsafe {
-            LLVMPositionBuilderAtEnd(self.builder, bb.0);
+            LLVMPositionBuilderAtEnd(self.builder, bb.bb_ref());
         }
     }
 
+    /// Get the BasicBlock the IRBuilder currently inputs into.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn get_insert_block(&self) -> BasicBlock<'llvm> {
+        let bb_ref = unsafe { LLVMGetInsertBlock(self.builder) };
+        assert!(!bb_ref.is_null());
+
+        BasicBlock::new(bb_ref)
+    }
+
     /// Emit a [fadd](https://llvm.org/docs/LangRef.html#fadd-instruction) instruction.
     ///
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn fadd(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
+    pub fn fadd(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
         debug_assert!(lhs.is_f64(), "fadd: Expected f64 as lhs operand!");
         debug_assert!(rhs.is_f64(), "fadd: Expected f64 as rhs operand!");
 
@@ -267,7 +375,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn fsub(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
+    pub fn fsub(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
         debug_assert!(lhs.is_f64(), "fsub: Expected f64 as lhs operand!");
         debug_assert!(rhs.is_f64(), "fsub: Expected f64 as rhs operand!");
 
@@ -287,7 +395,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn fmul(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
+    pub fn fmul(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
         debug_assert!(lhs.is_f64(), "fmul: Expected f64 as lhs operand!");
         debug_assert!(rhs.is_f64(), "fmul: Expected f64 as rhs operand!");
 
@@ -302,14 +410,14 @@
         Value::new(value_ref)
     }
 
-    /// Emit a [fcmult](https://llvm.org/docs/LangRef.html#fcmp-instruction) instruction.
+    /// Emit a [fcmpult](https://llvm.org/docs/LangRef.html#fcmp-instruction) instruction.
     ///
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn fcmpult(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
-        debug_assert!(lhs.is_f64(), "fcmplt: Expected f64 as lhs operand!");
-        debug_assert!(rhs.is_f64(), "fcmplt: Expected f64 as rhs operand!");
+    pub fn fcmpult(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
+        debug_assert!(lhs.is_f64(), "fcmpult: Expected f64 as lhs operand!");
+        debug_assert!(rhs.is_f64(), "fcmpult: Expected f64 as rhs operand!");
 
         let value_ref = unsafe {
             LLVMBuildFCmp(
@@ -317,7 +425,28 @@
                 LLVMRealPredicate::LLVMRealULT,
                 lhs.value_ref(),
                 rhs.value_ref(),
-                b"fcmplt\0".as_ptr().cast(),
+                b"fcmpult\0".as_ptr().cast(),
+            )
+        };
+        Value::new(value_ref)
+    }
+
+    /// Emit a [fcmpone](https://llvm.org/docs/LangRef.html#fcmp-instruction) instruction.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn fcmpone(&self, lhs: Value<'llvm>, rhs: Value<'llvm>) -> Value<'llvm> {
+        debug_assert!(lhs.is_f64(), "fcmone: Expected f64 as lhs operand!");
+        debug_assert!(rhs.is_f64(), "fcmone: Expected f64 as rhs operand!");
+
+        let value_ref = unsafe {
+            LLVMBuildFCmp(
+                self.builder,
+                LLVMRealPredicate::LLVMRealONE,
+                lhs.value_ref(),
+                rhs.value_ref(),
+                b"fcmpone\0".as_ptr().cast(),
             )
         };
         Value::new(value_ref)
@@ -328,7 +457,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn uitofp(&self, val: Value<'llvm>, dest_type: Type<'llvm>) -> Value<'llvm> {
+    pub fn uitofp(&self, val: Value<'llvm>, dest_type: Type<'llvm>) -> Value<'llvm> {
         debug_assert!(val.is_int(), "uitofp: Expected integer operand!");
 
         let value_ref = unsafe {
@@ -347,7 +476,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn call(&self, fn_value: FnValue<'llvm>, args: &mut [Value<'llvm>]) -> Value<'llvm> {
+    pub fn call(&self, fn_value: FnValue<'llvm>, args: &mut [Value<'llvm>]) -> Value<'llvm> {
         let value_ref = unsafe {
             LLVMBuildCall2(
                 self.builder,
@@ -370,14 +499,69 @@
         let ret = unsafe { LLVMBuildRet(self.builder, ret.value_ref()) };
         assert!(!ret.is_null());
     }
+
+    /// Emit an unconditional [br](https://llvm.org/docs/LangRef.html#br-instruction) instruction.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn br(&self, dest: BasicBlock<'llvm>) {
+        let br_ref = unsafe { LLVMBuildBr(self.builder, dest.bb_ref()) };
+        assert!(!br_ref.is_null());
+    }
+
+    /// Emit a conditional [br](https://llvm.org/docs/LangRef.html#br-instruction) instruction.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn cond_br(&self, cond: Value<'llvm>, then: BasicBlock<'llvm>, else_: BasicBlock<'llvm>) {
+        let br_ref = unsafe {
+            LLVMBuildCondBr(
+                self.builder,
+                cond.value_ref(),
+                then.bb_ref(),
+                else_.bb_ref(),
+            )
+        };
+        assert!(!br_ref.is_null());
+    }
+
+    /// Emit a [phi](https://llvm.org/docs/LangRef.html#phi-instruction) instruction.
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn phi(
+        &self,
+        phi_type: Type<'llvm>,
+        incoming: &[(Value<'llvm>, BasicBlock<'llvm>)],
+    ) -> PhiValue<'llvm> {
+        let phi_ref =
+            unsafe { LLVMBuildPhi(self.builder, phi_type.type_ref(), b"phi\0".as_ptr().cast()) };
+        assert!(!phi_ref.is_null());
+
+        for (val, bb) in incoming {
+            debug_assert_eq!(
+                val.type_of().kind(),
+                phi_type.kind(),
+                "Type of incoming phi value must be the same as the type used to build the phi node."
+            );
+
+            unsafe {
+                LLVMAddIncoming(phi_ref, &mut val.value_ref() as _, &mut bb.bb_ref() as _, 1);
+            }
+        }
+
+        PhiValue::new(phi_ref)
+    }
 }
 
 impl Drop for IRBuilder<'_> {
-    fn drop(&mut self) {
+    fn drop(&mut self) {
         unsafe { LLVMDisposeBuilder(self.builder) }
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/lljit.rs.html b/src/llvm_kaleidoscope_rs/llvm/lljit.rs.html index 8abbc19..5a5a376 100644 --- a/src/llvm_kaleidoscope_rs/llvm/lljit.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/lljit.rs.html @@ -1,102 +1,108 @@ -lljit.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+lljit.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -152,8 +158,7 @@
 152
 153
 154
-
-use llvm_sys::orc2::{
+
use llvm_sys::orc2::{
     lljit::{
         LLVMOrcCreateLLJIT, LLVMOrcLLJITAddLLVMIRModuleWithRT, LLVMOrcLLJITGetGlobalPrefix,
         LLVMOrcLLJITGetMainJITDylib, LLVMOrcLLJITLookup, LLVMOrcLLJITRef,
@@ -167,12 +172,12 @@
 use std::marker::PhantomData;
 
 use super::{Error, Module};
-use crate::SmallCStr;
+use crate::SmallCStr;
 
 /// Marker trait to constrain function signatures that can be looked up in the JIT.
 pub trait JitFn {}
 
-impl JitFn for unsafe extern "C" fn() -> f64 {}
+impl JitFn for unsafe extern "C" fn() -> f64 {}
 
 /// Wrapper for a LLVM [LLJIT](https://www.llvm.org/docs/ORCv2.html#lljit-and-lllazyjit).
 pub struct LLJit {
@@ -186,11 +191,11 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer or an error.
-    pub fn new() -> LLJit {
+    pub fn new() -> LLJit {
         let (jit, dylib) = unsafe {
             let mut jit = std::ptr::null_mut();
             let err = LLVMOrcCreateLLJIT(
-                &mut jit as _,
+                &mut jit as _,
                 std::ptr::null_mut(), /* builder: nullptr -> default */
             );
 
@@ -213,7 +218,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer or an error.
-    pub fn add_module(&self, module: Module) -> ResourceTracker<'_> {
+    pub fn add_module(&self, module: Module) -> ResourceTracker<'_> {
         let tsmod = module.into_raw_thread_safe_module();
 
         let rt = unsafe {
@@ -235,13 +240,13 @@
     /// # Panics
     ///
     /// Panics if the symbol is not found in the JIT.
-    pub fn find_symbol<F: JitFn>(&self, sym: &str) -> F {
+    pub fn find_symbol<F: JitFn>(&self, sym: &str) -> F {
         let sym =
             SmallCStr::try_from(sym).expect("Failed to convert 'sym' argument to small C string!");
 
         unsafe {
             let mut addr = 0u64;
-            let err = LLVMOrcLLJITLookup(self.jit, &mut addr as _, sym.as_ptr());
+            let err = LLVMOrcLLJITLookup(self.jit, &mut addr as _, sym.as_ptr());
 
             if let Some(err) = Error::from(err) {
                 panic!("Error: {}", err.as_str());
@@ -261,7 +266,7 @@
         unsafe {
             let mut proc_syms_gen: LLVMOrcDefinitionGeneratorRef = std::ptr::null_mut();
             let err = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
-                &mut proc_syms_gen as _,
+                &mut proc_syms_gen as _,
                 self.global_prefix(),
                 None,                 /* filter */
                 std::ptr::null_mut(), /* filter ctx */
@@ -276,7 +281,7 @@
     }
 
     /// Return the global prefix character according to the LLJITs data layout.
-    fn global_prefix(&self) -> libc::c_char {
+    fn global_prefix(&self) -> libc::c_char {
         unsafe { LLVMOrcLLJITGetGlobalPrefix(self.jit) }
     }
 }
@@ -288,14 +293,14 @@
 pub struct ResourceTracker<'jit>(LLVMOrcResourceTrackerRef, PhantomData<&'jit ()>);
 
 impl<'jit> ResourceTracker<'jit> {
-    fn new(rt: LLVMOrcResourceTrackerRef) -> ResourceTracker<'jit> {
+    fn new(rt: LLVMOrcResourceTrackerRef) -> ResourceTracker<'jit> {
         assert!(!rt.is_null());
         ResourceTracker(rt, PhantomData)
     }
 }
 
 impl Drop for ResourceTracker<'_> {
-    fn drop(&mut self) {
+    fn drop(&mut self) {
         unsafe {
             let err = LLVMOrcResourceTrackerRemove(self.0);
 
@@ -307,7 +312,6 @@
         };
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/mod.rs.html b/src/llvm_kaleidoscope_rs/llvm/mod.rs.html index d6eb8b2..3dca9c7 100644 --- a/src/llvm_kaleidoscope_rs/llvm/mod.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/mod.rs.html @@ -1,12 +1,18 @@ -mod.rs - source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
+mod.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
 10
 11
 12
@@ -72,12 +78,7 @@
 72
 73
 74
-75
-76
-77
-78
-
-//! Safe wrapper around the LLVM C API.
+
//! Safe wrapper around the LLVM C API.
 //!
 //! References returned from the LLVM API are tied to the `'llvm` lifetime which is bound to the
 //! context where the objects are created in.
@@ -90,7 +91,6 @@
 use llvm_sys::{
     core::LLVMShutdown,
     error::{LLVMDisposeErrorMessage, LLVMErrorRef, LLVMGetErrorMessage},
-    prelude::LLVMBasicBlockRef,
     target::{
         LLVM_InitializeNativeAsmParser, LLVM_InitializeNativeAsmPrinter,
         LLVM_InitializeNativeTarget,
@@ -98,8 +98,8 @@
 };
 
 use std::ffi::CStr;
-use std::marker::PhantomData;
 
+mod basic_block;
 mod builder;
 mod lljit;
 mod module;
@@ -107,25 +107,22 @@
 mod type_;
 mod value;
 
+pub use basic_block::BasicBlock;
 pub use builder::IRBuilder;
 pub use lljit::{LLJit, ResourceTracker};
 pub use module::Module;
 pub use pass_manager::FunctionPassManager;
 pub use type_::Type;
-pub use value::{FnValue, Value};
-
-/// Wrapper for a LLVM Basic Block.
-#[derive(Copy, Clone)]
-pub struct BasicBlock<'llvm>(LLVMBasicBlockRef, PhantomData<&'llvm ()>);
+pub use value::{FnValue, PhiValue, Value};
 
 struct Error<'llvm>(&'llvm mut libc::c_char);
 
 impl<'llvm> Error<'llvm> {
-    fn from(err: LLVMErrorRef) -> Option<Error<'llvm>> {
-        (!err.is_null()).then(|| Error(unsafe { &mut *LLVMGetErrorMessage(err) }))
+    fn from(err: LLVMErrorRef) -> Option<Error<'llvm>> {
+        (!err.is_null()).then(|| Error(unsafe { &mut *LLVMGetErrorMessage(err) }))
     }
 
-    fn as_str(&self) -> &str {
+    fn as_str(&self) -> &str {
         unsafe { CStr::from_ptr(self.0) }
             .to_str()
             .expect("Expected valid UTF8 string from LLVM API")
@@ -133,9 +130,9 @@
 }
 
 impl Drop for Error<'_> {
-    fn drop(&mut self) {
+    fn drop(&mut self) {
         unsafe {
-            LLVMDisposeErrorMessage(self.0 as *mut libc::c_char);
+            LLVMDisposeErrorMessage(self.0 as *mut libc::c_char);
         }
     }
 }
@@ -155,7 +152,6 @@
         LLVMShutdown();
     };
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/module.rs.html b/src/llvm_kaleidoscope_rs/llvm/module.rs.html index be37a0b..99846f4 100644 --- a/src/llvm_kaleidoscope_rs/llvm/module.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/module.rs.html @@ -1,102 +1,108 @@ -module.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+module.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -194,11 +200,25 @@
 194
 195
 196
-
-use llvm_sys::{
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+
use llvm_sys::{
     core::{
-        LLVMAddFunction, LLVMAppendBasicBlockInContext, LLVMDisposeModule, LLVMDoubleTypeInContext,
-        LLVMDumpModule, LLVMGetNamedFunction, LLVMModuleCreateWithNameInContext,
+        LLVMAddFunction, LLVMAppendBasicBlockInContext, LLVMCreateBasicBlockInContext,
+        LLVMDisposeModule, LLVMDoubleTypeInContext, LLVMDumpModule, LLVMGetNamedFunction,
+        LLVMModuleCreateWithNameInContext,
     },
     orc2::{
         LLVMOrcCreateNewThreadSafeContext, LLVMOrcCreateNewThreadSafeModule,
@@ -210,19 +230,18 @@
 };
 
 use std::convert::TryFrom;
-use std::marker::PhantomData;
 
 use super::{BasicBlock, FnValue, Type};
-use crate::SmallCStr;
+use crate::SmallCStr;
 
 // Definition of LLVM C API functions using our `repr(transparent)` types.
 extern "C" {
     fn LLVMFunctionType(
         ReturnType: Type<'_>,
-        ParamTypes: *mut Type<'_>,
+        ParamTypes: *mut Type<'_>,
         ParamCount: ::libc::c_uint,
         IsVarArg: LLVMBool,
-    ) -> LLVMTypeRef;
+    ) -> LLVMTypeRef;
 }
 
 /// Wrapper for a LLVM Module with its own LLVM Context.
@@ -238,7 +257,7 @@
     /// # Panics
     ///
     /// Panics if creating the context or the module fails.
-    pub fn new() -> Self {
+    pub fn new() -> Self {
         let (tsctx, ctx, module) = unsafe {
             // We generate a thread safe context because we are going to jit this IR module and
             // there is no method to create a thread safe context wrapper from an existing context
@@ -260,13 +279,13 @@
 
     /// Get the raw LLVM context reference.
     #[inline]
-    pub(super) fn ctx(&self) -> LLVMContextRef {
+    pub(super) fn ctx(&self) -> LLVMContextRef {
         self.ctx
     }
 
     /// Get the raw LLVM module reference.
     #[inline]
-    pub(super) fn module(&self) -> LLVMModuleRef {
+    pub(super) fn module(&self) -> LLVMModuleRef {
         self.module
     }
 
@@ -275,8 +294,8 @@
     /// If ownership of the raw reference is not transferred (eg to the JIT), memory will be leaked
     /// in case the reference is disposed explicitly with LLVMOrcDisposeThreadSafeModule.
     #[inline]
-    pub(super) fn into_raw_thread_safe_module(mut self) -> LLVMOrcThreadSafeModuleRef {
-        let m = std::mem::replace(&mut self.module, std::ptr::null_mut());
+    pub(super) fn into_raw_thread_safe_module(mut self) -> LLVMOrcThreadSafeModuleRef {
+        let m = std::mem::replace(&mut self.module, std::ptr::null_mut());
 
         // ThreadSafeModule has unique ownership.
         // Takes ownership of module and increments ThreadSafeContext ref count.
@@ -299,7 +318,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn type_f64(&self) -> Type<'llvm> {
+    pub fn type_f64(&self) -> Type<'llvm> {
         let type_ref = unsafe { LLVMDoubleTypeInContext(self.ctx) };
         Type::new(type_ref)
     }
@@ -309,7 +328,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn type_fn(&'llvm self, args: &mut [Type<'llvm>], ret: Type<'llvm>) -> Type<'llvm> {
+    pub fn type_fn(&'llvm self, args: &mut [Type<'llvm>], ret: Type<'llvm>) -> Type<'llvm> {
         let type_ref = unsafe {
             LLVMFunctionType(
                 ret,
@@ -328,7 +347,7 @@
     ///
     /// Panics if LLVM API returns a `null` pointer or `name` could not be converted to a
     /// [`SmallCStr`].
-    pub fn add_fn(&'llvm self, name: &str, fn_type: Type<'llvm>) -> FnValue<'llvm> {
+    pub fn add_fn(&'llvm self, name: &str, fn_type: Type<'llvm>) -> FnValue<'llvm> {
         debug_assert_eq!(
             fn_type.kind(),
             LLVMTypeKind::LLVMFunctionTypeKind,
@@ -348,7 +367,7 @@
     /// # Panics
     ///
     /// Panics if `name` could not be converted to a [`SmallCStr`].
-    pub fn get_fn(&'llvm self, name: &str) -> Option<FnValue<'llvm>> {
+    pub fn get_fn(&'llvm self, name: &str) -> Option<FnValue<'llvm>> {
         let name = SmallCStr::try_from(name)
             .expect("Failed to convert 'name' argument to small C string!");
 
@@ -363,7 +382,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn append_basic_block(&'llvm self, fn_value: FnValue<'llvm>) -> BasicBlock<'llvm> {
+    pub fn append_basic_block(&'llvm self, fn_value: FnValue<'llvm>) -> BasicBlock<'llvm> {
         let block = unsafe {
             LLVMAppendBasicBlockInContext(
                 self.ctx,
@@ -373,12 +392,26 @@
         };
         assert!(!block.is_null());
 
-        BasicBlock(block, PhantomData)
+        BasicBlock::new(block)
+    }
+
+    /// Create a free-standing Basic Block without adding it to a function.
+    /// This can be added to a function at a later point in time with
+    /// [`FnValue::append_basic_block`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if LLVM API returns a `null` pointer.
+    pub fn create_basic_block(&self) -> BasicBlock<'llvm> {
+        let block = unsafe { LLVMCreateBasicBlockInContext(self.ctx, b"block\0".as_ptr().cast()) };
+        assert!(!block.is_null());
+
+        BasicBlock::new(block)
     }
 }
 
 impl Drop for Module {
-    fn drop(&mut self) {
+    fn drop(&mut self) {
         unsafe {
             // In case we turned the module into a ThreadSafeModule, we must not dispose the module
             // reference because ThreadSafeModule took ownership!
@@ -391,7 +424,6 @@
         }
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/pass_manager.rs.html b/src/llvm_kaleidoscope_rs/llvm/pass_manager.rs.html index ab73029..ebf9b28 100644 --- a/src/llvm_kaleidoscope_rs/llvm/pass_manager.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/pass_manager.rs.html @@ -1,12 +1,18 @@ -pass_manager.rs - source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
+pass_manager.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
 10
 11
 12
@@ -73,8 +79,7 @@
 73
 74
 75
-
-use llvm_sys::{
+
use llvm_sys::{
     core::{
         LLVMCreateFunctionPassManagerForModule, LLVMDisposePassManager,
         LLVMInitializeFunctionPassManager, LLVMRunFunctionPassManager,
@@ -105,7 +110,7 @@
     ///
     /// The list of selected optimization passes is taken from the tutorial chapter [LLVM
     /// Optimization Passes](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl04.html#id3).
-    pub fn with_ctx(module: &'llvm Module) -> FunctionPassManager<'llvm> {
+    pub fn with_ctx(module: &'llvm Module) -> FunctionPassManager<'llvm> {
         let fpm = unsafe {
             // Borrows module reference.
             LLVMCreateFunctionPassManagerForModule(module.module())
@@ -143,13 +148,12 @@
 }
 
 impl Drop for FunctionPassManager<'_> {
-    fn drop(&mut self) {
+    fn drop(&mut self) {
         unsafe {
             LLVMDisposePassManager(self.fpm);
         }
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/type_.rs.html b/src/llvm_kaleidoscope_rs/llvm/type_.rs.html index 89e332a..98daee4 100644 --- a/src/llvm_kaleidoscope_rs/llvm/type_.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/type_.rs.html @@ -1,12 +1,18 @@ -type_.rs - source
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
+type_.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
 10
 11
 12
@@ -56,8 +62,7 @@
 56
 57
 58
-
-use llvm_sys::{
+
use llvm_sys::{
     core::{LLVMConstReal, LLVMDumpType, LLVMGetTypeKind},
     prelude::LLVMTypeRef,
     LLVMTypeKind,
@@ -65,7 +70,7 @@
 
 use std::marker::PhantomData;
 
-use super::Value;
+use super::Value;
 
 /// Wrapper for a LLVM Type Reference.
 #[derive(Copy, Clone)]
@@ -78,19 +83,19 @@
     /// # Panics
     ///
     /// Panics if `type_ref` is a null pointer.
-    pub(super) fn new(type_ref: LLVMTypeRef) -> Self {
+    pub(super) fn new(type_ref: LLVMTypeRef) -> Self {
         assert!(!type_ref.is_null());
         Type(type_ref, PhantomData)
     }
 
     /// Get the raw LLVM type reference.
     #[inline]
-    pub(super) fn type_ref(&self) -> LLVMTypeRef {
+    pub(super) fn type_ref(&self) -> LLVMTypeRef {
         self.0
     }
 
     /// Get the LLVM type kind for the given type reference.
-    pub(super) fn kind(&self) -> LLVMTypeKind {
+    pub(super) fn kind(&self) -> LLVMTypeKind {
         unsafe { LLVMGetTypeKind(self.type_ref()) }
     }
 
@@ -104,7 +109,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn const_f64(self, n: f64) -> Value<'llvm> {
+    pub fn const_f64(self, n: f64) -> Value<'llvm> {
         debug_assert_eq!(
             self.kind(),
             LLVMTypeKind::LLVMDoubleTypeKind,
@@ -115,7 +120,6 @@
         Value::new(value_ref)
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/llvm/value.rs.html b/src/llvm_kaleidoscope_rs/llvm/value.rs.html index 950eae0..eaea9c3 100644 --- a/src/llvm_kaleidoscope_rs/llvm/value.rs.html +++ b/src/llvm_kaleidoscope_rs/llvm/value.rs.html @@ -1,102 +1,108 @@ -value.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+value.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -166,12 +172,83 @@
 166
 167
 168
-
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+
#![allow(unused)]
+
 use llvm_sys::{
     analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction},
     core::{
-        LLVMCountBasicBlocks, LLVMCountParams, LLVMDumpValue, LLVMGetParam, LLVMGetReturnType,
-        LLVMGetValueKind, LLVMGetValueName2, LLVMSetValueName2, LLVMTypeOf,
+        LLVMAddIncoming, LLVMAppendExistingBasicBlock, LLVMCountBasicBlocks, LLVMCountParams,
+        LLVMDumpValue, LLVMGetParam, LLVMGetReturnType, LLVMGetValueKind, LLVMGetValueName2,
+        LLVMIsAFunction, LLVMIsAPHINode, LLVMSetValueName2, LLVMTypeOf,
     },
     prelude::LLVMValueRef,
     LLVMTypeKind, LLVMValueKind,
@@ -181,7 +258,8 @@
 use std::marker::PhantomData;
 use std::ops::Deref;
 
-use super::Type;
+use super::BasicBlock;
+use super::Type;
 
 /// Wrapper for a LLVM Value Reference.
 #[derive(Copy, Clone)]
@@ -194,22 +272,34 @@
     /// # Panics
     ///
     /// Panics if `value_ref` is a null pointer.
-    pub(super) fn new(value_ref: LLVMValueRef) -> Self {
+    pub(super) fn new(value_ref: LLVMValueRef) -> Self {
         assert!(!value_ref.is_null());
         Value(value_ref, PhantomData)
     }
 
     /// Get the raw LLVM value reference.
     #[inline]
-    pub(super) fn value_ref(&self) -> LLVMValueRef {
+    pub(super) fn value_ref(&self) -> LLVMValueRef {
         self.0
     }
 
     /// Get the LLVM value kind for the given value reference.
-    pub(super) fn kind(&self) -> LLVMValueKind {
+    pub(super) fn kind(&self) -> LLVMValueKind {
         unsafe { LLVMGetValueKind(self.value_ref()) }
     }
 
+    /// Check if value is `function` type.
+    pub(super) fn is_function(&self) -> bool {
+        let cast = unsafe { LLVMIsAFunction(self.value_ref()) };
+        !cast.is_null()
+    }
+
+    /// Check if value is `phinode` type.
+    pub(super) fn is_phinode(&self) -> bool {
+        let cast = unsafe { LLVMIsAPHINode(self.value_ref()) };
+        !cast.is_null()
+    }
+
     /// Dump the LLVM Value to stdout.
     pub fn dump(&self) {
         unsafe { LLVMDumpValue(self.value_ref()) };
@@ -220,7 +310,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn type_of(&self) -> Type<'llvm> {
+    pub fn type_of(&self) -> Type<'llvm> {
         let type_ref = unsafe { LLVMTypeOf(self.value_ref()) };
         Type::new(type_ref)
     }
@@ -239,10 +329,10 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn get_name(&self) -> &'llvm str {
+    pub fn get_name(&self) -> &'llvm str {
         let name = unsafe {
             let mut len: libc::size_t = 0;
-            let name = LLVMGetValueName2(self.0, &mut len as _);
+            let name = LLVMGetValueName2(self.0, &mut len as _);
             assert!(!name.is_null());
 
             CStr::from_ptr(name)
@@ -254,13 +344,13 @@
     }
 
     /// Check if value is of `f64` type.
-    pub fn is_f64(&self) -> bool {
-        self.type_of().kind() == LLVMTypeKind::LLVMDoubleTypeKind
+    pub fn is_f64(&self) -> bool {
+        self.type_of().kind() == LLVMTypeKind::LLVMDoubleTypeKind
     }
 
     /// Check if value is of integer type.
-    pub fn is_int(&self) -> bool {
-        self.type_of().kind() == LLVMTypeKind::LLVMIntegerTypeKind
+    pub fn is_int(&self) -> bool {
+        self.type_of().kind() == LLVMTypeKind::LLVMIntegerTypeKind
     }
 }
 
@@ -271,7 +361,7 @@
 
 impl<'llvm> Deref for FnValue<'llvm> {
     type Target = Value<'llvm>;
-    fn deref(&self) -> &Self::Target {
+    fn deref(&self) -> &Self::Target {
         &self.0
     }
 }
@@ -282,11 +372,10 @@
     /// # Panics
     ///
     /// Panics if `value_ref` is a null pointer.
-    pub(super) fn new(value_ref: LLVMValueRef) -> Self {
+    pub(super) fn new(value_ref: LLVMValueRef) -> Self {
         let value = Value::new(value_ref);
-        debug_assert_eq!(
-            value.kind(),
-            LLVMValueKind::LLVMFunctionValueKind,
+        debug_assert!(
+            value.is_function(),
             "Expected a fn value when constructing FnValue!"
         );
 
@@ -298,13 +387,13 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer.
-    pub fn ret_type(&self) -> Type<'llvm> {
+    pub fn ret_type(&self) -> Type<'llvm> {
         let type_ref = unsafe { LLVMGetReturnType(LLVMTypeOf(self.value_ref())) };
         Type::new(type_ref)
     }
 
     /// Get the number of function arguments for the given function value.
-    pub fn args(&self) -> usize {
+    pub fn args(&self) -> usize {
         unsafe { LLVMCountParams(self.value_ref()) as usize }
     }
 
@@ -313,7 +402,7 @@
     /// # Panics
     ///
     /// Panics if LLVM API returns a `null` pointer or indexed out of bounds.
-    pub fn arg(&self, idx: usize) -> Value<'llvm> {
+    pub fn arg(&self, idx: usize) -> Value<'llvm> {
         assert!(idx < self.args());
 
         let value_ref = unsafe { LLVMGetParam(self.value_ref(), idx as libc::c_uint) };
@@ -321,21 +410,74 @@
     }
 
     /// Get the number of Basic Blocks for the given function value.
-    pub fn basic_blocks(&self) -> usize {
+    pub fn basic_blocks(&self) -> usize {
         unsafe { LLVMCountBasicBlocks(self.value_ref()) as usize }
     }
 
+    /// Append a Basic Block to the end of the function value.
+    pub fn append_basic_block(&self, bb: BasicBlock<'llvm>) {
+        unsafe {
+            LLVMAppendExistingBasicBlock(self.value_ref(), bb.bb_ref());
+        }
+    }
+
     /// Verify that the given function is valid.
-    pub fn verify(&self) -> bool {
+    pub fn verify(&self) -> bool {
         unsafe {
             LLVMVerifyFunction(
                 self.value_ref(),
                 LLVMVerifierFailureAction::LLVMPrintMessageAction,
-            ) == 0
+            ) == 0
+        }
+    }
+}
+
+/// Wrapper for a LLVM Value Reference specialized for contexts where phi values are needed.
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct PhiValue<'llvm>(Value<'llvm>);
+
+impl<'llvm> Deref for PhiValue<'llvm> {
+    type Target = Value<'llvm>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<'llvm> PhiValue<'llvm> {
+    /// Create a new PhiValue instance.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `value_ref` is a null pointer.
+    pub(super) fn new(value_ref: LLVMValueRef) -> Self {
+        let value = Value::new(value_ref);
+        debug_assert!(
+            value.is_phinode(),
+            "Expected a phinode value when constructing PhiValue!"
+        );
+
+        PhiValue(value)
+    }
+
+    /// Add an incoming value to the end of a PHI list.
+    pub fn add_incoming(&self, ival: Value<'llvm>, ibb: BasicBlock<'llvm>) {
+        debug_assert_eq!(
+            ival.type_of().kind(),
+            self.type_of().kind(),
+            "Type of incoming phi value must be the same as the type used to build the phi node."
+        );
+
+        unsafe {
+            LLVMAddIncoming(
+                self.value_ref(),
+                &mut ival.value_ref() as _,
+                &mut ibb.bb_ref() as _,
+                1,
+            );
         }
     }
 }
-
-
- +
+
\ No newline at end of file diff --git a/src/llvm_kaleidoscope_rs/parser.rs.html b/src/llvm_kaleidoscope_rs/parser.rs.html index 9093695..d3c9594 100644 --- a/src/llvm_kaleidoscope_rs/parser.rs.html +++ b/src/llvm_kaleidoscope_rs/parser.rs.html @@ -1,102 +1,108 @@ -parser.rs - source
  1
-  2
-  3
-  4
-  5
-  6
-  7
-  8
-  9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
+parser.rs - source
+    
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
 100
 101
 102
@@ -458,8 +464,201 @@
 458
 459
 460
-
-use crate::lexer::{Lexer, Token};
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+
use crate::lexer::{Lexer, Token};
 
 #[derive(Debug, PartialEq)]
 pub enum ExprAST {
@@ -474,6 +673,22 @@
 
     /// Call - Expression class for function calls.
     Call(String, Vec<ExprAST>),
+
+    /// If - Expression class for if/then/else.
+    If {
+        cond: Box<ExprAST>,
+        then: Box<ExprAST>,
+        else_: Box<ExprAST>,
+    },
+
+    /// ForExprAST - Expression class for for/in.
+    For {
+        var: String,
+        start: Box<ExprAST>,
+        end: Box<ExprAST>,
+        step: Option<Box<ExprAST>>,
+        body: Box<ExprAST>,
+    },
 }
 
 /// PrototypeAST - This class represents the "prototype" for a function,
@@ -502,7 +717,7 @@
 where
     I: Iterator<Item = char>,
 {
-    pub fn new(lexer: Lexer<I>) -> Self {
+    pub fn new(lexer: Lexer<I>) -> Self {
         Parser {
             lexer,
             cur_tok: None,
@@ -517,14 +732,14 @@
     ///
     /// # Panics
     /// Panics if the parser doesn't have a current token.
-    pub fn cur_tok(&self) -> &Token {
+    pub fn cur_tok(&self) -> &Token {
         self.cur_tok.as_ref().expect("Parser: Expected cur_token!")
     }
 
     /// Advance the `cur_tok` by getting the next token from the lexer.
     ///
     /// Implement the fucntion `int getNextToken();` from the tutorial.
-    pub fn get_next_token(&mut self) {
+    pub fn get_next_token(&mut self) {
         self.cur_tok = Some(self.lexer.gettok());
     }
 
@@ -535,28 +750,28 @@
     /// numberexpr ::= number
     ///
     /// Implement `std::unique_ptr<ExprAST> ParseNumberExpr();` from the tutorial.
-    fn parse_num_expr(&mut self) -> ParseResult<ExprAST> {
+    fn parse_num_expr(&mut self) -> ParseResult<ExprAST> {
         match *self.cur_tok() {
-            Token::Number(num) => {
+            Token::Number(num) => {
                 // Consume the number token.
                 self.get_next_token();
                 Ok(ExprAST::Number(num))
             }
-            _ => unreachable!(),
+            _ => unreachable!(),
         }
     }
 
     /// parenexpr ::= '(' expression ')'
     ///
     /// Implement `std::unique_ptr<ExprAST> ParseParenExpr();` from the tutorial.
-    fn parse_paren_expr(&mut self) -> ParseResult<ExprAST> {
+    fn parse_paren_expr(&mut self) -> ParseResult<ExprAST> {
         // Eat '(' token.
         assert_eq!(*self.cur_tok(), Token::Char('('));
         self.get_next_token();
 
         let v = self.parse_expression()?;
 
-        if *self.cur_tok() == Token::Char(')') {
+        if *self.cur_tok() == Token::Char(')') {
             // Eat ')' token.
             self.get_next_token();
             Ok(v)
@@ -570,14 +785,14 @@
     ///   ::= identifier '(' expression* ')'
     ///
     /// Implement `std::unique_ptr<ExprAST> ParseIdentifierExpr();` from the tutorial.
-    fn parse_identifier_expr(&mut self) -> ParseResult<ExprAST> {
+    fn parse_identifier_expr(&mut self) -> ParseResult<ExprAST> {
         let id_name = match self.cur_tok.take() {
-            Some(Token::Identifier(id)) => {
+            Some(Token::Identifier(id)) => {
                 // Consume identifier.
                 self.get_next_token();
                 id
             }
-            _ => unreachable!(),
+            _ => unreachable!(),
         };
 
         if *self.cur_tok() != Token::Char('(') {
@@ -597,9 +812,7 @@
                     let arg = self.parse_expression()?;
                     args.push(arg);
 
-                    if *self.cur_tok() == Token::Char(')') {
-                        // Eat ')' token.
-                        self.get_next_token();
+                    if *self.cur_tok() == Token::Char(')') {
                         break;
                     }
 
@@ -611,22 +824,119 @@
                 }
             }
 
+            assert_eq!(*self.cur_tok(), Token::Char(')'));
+            // Eat ')' token.
+            self.get_next_token();
+
             Ok(ExprAST::Call(id_name, args))
         }
     }
 
+    /// ifexpr ::= 'if' expression 'then' expression 'else' expression
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseIfExpr();` from the tutorial.
+    fn parse_if_expr(&mut self) -> ParseResult<ExprAST> {
+        // Consume 'if' token.
+        assert_eq!(*self.cur_tok(), Token::If);
+        self.get_next_token();
+
+        let cond = self.parse_expression()?;
+
+        if *dbg!(self.cur_tok()) != Token::Then {
+            return Err("Expected 'then'".into());
+        }
+        // Consume 'then' token.
+        self.get_next_token();
+
+        let then = self.parse_expression()?;
+
+        if *self.cur_tok() != Token::Else {
+            return Err("Expected 'else'".into());
+        }
+        // Consume 'else' token.
+        self.get_next_token();
+
+        let else_ = self.parse_expression()?;
+
+        Ok(ExprAST::If {
+            cond: Box::new(cond),
+            then: Box::new(then),
+            else_: Box::new(else_),
+        })
+    }
+
+    /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseForExpr();` from the tutorial.
+    fn parse_for_expr(&mut self) -> ParseResult<ExprAST> {
+        // Consume the 'for' token.
+        assert_eq!(*self.cur_tok(), Token::For);
+        self.get_next_token();
+
+        let var = match self
+            .parse_identifier_expr()
+            .map_err(|_| String::from("expected identifier after 'for'"))?
+        {
+            ExprAST::Variable(var) => var,
+            _ => unreachable!(),
+        };
+
+        // Consume the '=' token.
+        if *self.cur_tok() != Token::Char('=') {
+            return Err("expected '=' after for".into());
+        }
+        self.get_next_token();
+
+        let start = self.parse_expression()?;
+
+        // Consume the ',' token.
+        if *self.cur_tok() != Token::Char(',') {
+            return Err("expected ',' after for start value".into());
+        }
+        self.get_next_token();
+
+        let end = self.parse_expression()?;
+
+        let step = if *self.cur_tok() == Token::Char(',') {
+            // Consume the ',' token.
+            self.get_next_token();
+
+            Some(self.parse_expression()?)
+        } else {
+            None
+        };
+
+        // Consume the 'in' token.
+        if *self.cur_tok() != Token::In {
+            return Err("expected 'in' after for".into());
+        }
+        self.get_next_token();
+
+        let body = self.parse_expression()?;
+
+        Ok(ExprAST::For {
+            var,
+            start: Box::new(start),
+            end: Box::new(end),
+            step: step.map(|s| Box::new(s)),
+            body: Box::new(body),
+        })
+    }
+
     /// primary
     ///   ::= identifierexpr
     ///   ::= numberexpr
     ///   ::= parenexpr
     ///
     /// Implement `std::unique_ptr<ExprAST> ParsePrimary();` from the tutorial.
-    fn parse_primary(&mut self) -> ParseResult<ExprAST> {
+    fn parse_primary(&mut self) -> ParseResult<ExprAST> {
         match *self.cur_tok() {
-            Token::Identifier(_) => self.parse_identifier_expr(),
-            Token::Number(_) => self.parse_num_expr(),
-            Token::Char('(') => self.parse_paren_expr(),
-            _ => Err("unknown token when expecting an expression".into()),
+            Token::Identifier(_) => self.parse_identifier_expr(),
+            Token::Number(_) => self.parse_num_expr(),
+            Token::Char('(') => self.parse_paren_expr(),
+            Token::If => self.parse_if_expr(),
+            Token::For => self.parse_for_expr(),
+            _ => Err("unknown token when expecting an expression".into()),
         }
     }
 
@@ -638,7 +948,7 @@
     ///   ::= primary binoprhs
     ///
     /// Implement `std::unique_ptr<ExprAST> ParseExpression();` from the tutorial.
-    fn parse_expression(&mut self) -> ParseResult<ExprAST> {
+    fn parse_expression(&mut self) -> ParseResult<ExprAST> {
         let lhs = self.parse_primary()?;
         self.parse_bin_op_rhs(0, lhs)
     }
@@ -647,7 +957,7 @@
     ///   ::= ('+' primary)*
     ///
     /// Implement `std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS);` from the tutorial.
-    fn parse_bin_op_rhs(&mut self, expr_prec: isize, mut lhs: ExprAST) -> ParseResult<ExprAST> {
+    fn parse_bin_op_rhs(&mut self, expr_prec: isize, mut lhs: ExprAST) -> ParseResult<ExprAST> {
         loop {
             let tok_prec = get_tok_precedence(self.cur_tok());
 
@@ -657,12 +967,12 @@
             }
 
             let binop = match self.cur_tok.take() {
-                Some(Token::Char(c)) => {
+                Some(Token::Char(c)) => {
                     // Eat binary operator.
                     self.get_next_token();
                     c
                 }
-                _ => unreachable!(),
+                _ => unreachable!(),
             };
 
             // lhs BINOP1 rhs BINOP2 remrhs
@@ -696,14 +1006,14 @@
     ///   ::= id '(' id* ')'
     ///
     /// Implement `std::unique_ptr<PrototypeAST> ParsePrototype();` from the tutorial.
-    fn parse_prototype(&mut self) -> ParseResult<PrototypeAST> {
+    fn parse_prototype(&mut self) -> ParseResult<PrototypeAST> {
         let id_name = match self.cur_tok.take() {
-            Some(Token::Identifier(id)) => {
+            Some(Token::Identifier(id)) => {
                 // Consume the identifier.
                 self.get_next_token();
                 id
             }
-            other => {
+            other => {
                 // Plug back current token.
                 self.cur_tok = other;
                 return Err("Expected function name in prototype".into());
@@ -719,9 +1029,9 @@
             self.get_next_token();
 
             match self.cur_tok.take() {
-                Some(Token::Identifier(arg)) => args.push(arg),
-                Some(Token::Char(',')) => {}
-                other => {
+                Some(Token::Identifier(arg)) => args.push(arg),
+                Some(Token::Char(',')) => {}
+                other => {
                     self.cur_tok = other;
                     break;
                 }
@@ -741,7 +1051,7 @@
     /// definition ::= 'def' prototype expression
     ///
     /// Implement `std::unique_ptr<FunctionAST> ParseDefinition();` from the tutorial.
-    pub fn parse_definition(&mut self) -> ParseResult<FunctionAST> {
+    pub fn parse_definition(&mut self) -> ParseResult<FunctionAST> {
         // Consume 'def' token.
         assert_eq!(*self.cur_tok(), Token::Def);
         self.get_next_token();
@@ -755,7 +1065,7 @@
     /// external ::= 'extern' prototype
     ///
     /// Implement `std::unique_ptr<PrototypeAST> ParseExtern();` from the tutorial.
-    pub fn parse_extern(&mut self) -> ParseResult<PrototypeAST> {
+    pub fn parse_extern(&mut self) -> ParseResult<PrototypeAST> {
         // Consume 'extern' token.
         assert_eq!(*self.cur_tok(), Token::Extern);
         self.get_next_token();
@@ -766,7 +1076,7 @@
     /// toplevelexpr ::= expression
     ///
     /// Implement `std::unique_ptr<FunctionAST> ParseTopLevelExpr();` from the tutorial.
-    pub fn parse_top_level_expr(&mut self) -> ParseResult<FunctionAST> {
+    pub fn parse_top_level_expr(&mut self) -> ParseResult<FunctionAST> {
         let e = self.parse_expression()?;
         let proto = PrototypeAST("__anon_expr".into(), Vec::new());
         Ok(FunctionAST(proto, e))
@@ -776,22 +1086,22 @@
 /// Get the binary operator precedence.
 ///
 /// Implement `int GetTokPrecedence();` from the tutorial.
-fn get_tok_precedence(tok: &Token) -> isize {
+fn get_tok_precedence(tok: &Token) -> isize {
     match tok {
-        Token::Char('<') => 10,
-        Token::Char('+') => 20,
-        Token::Char('-') => 20,
-        Token::Char('*') => 40,
-        _ => -1,
+        Token::Char('<') => 10,
+        Token::Char('+') => 20,
+        Token::Char('-') => 20,
+        Token::Char('*') => 40,
+        _ => -1,
     }
 }
 
 #[cfg(test)]
 mod test {
     use super::{ExprAST, FunctionAST, Parser, PrototypeAST};
-    use crate::lexer::Lexer;
+    use crate::lexer::Lexer;
 
-    fn parser(input: &str) -> Parser<std::str::Chars> {
+    fn parser(input: &str) -> Parser<std::str::Chars> {
         let l = Lexer::new(input.chars());
         let mut p = Parser::new(l);
 
@@ -818,9 +1128,72 @@
         );
     }
 
+    #[test]
+    fn parse_if() {
+        let mut p = parser("if 1 then 2 else 3");
+
+        let cond = Box::new(ExprAST::Number(1f64));
+        let then = Box::new(ExprAST::Number(2f64));
+        let else_ = Box::new(ExprAST::Number(3f64));
+
+        assert_eq!(p.parse_if_expr(), Ok(ExprAST::If { cond, then, else_ }));
+
+        let mut p = parser("if foo() then bar(2) else baz(3)");
+
+        let cond = Box::new(ExprAST::Call("foo".into(), vec![]));
+        let then = Box::new(ExprAST::Call("bar".into(), vec![ExprAST::Number(2f64)]));
+        let else_ = Box::new(ExprAST::Call("baz".into(), vec![ExprAST::Number(3f64)]));
+
+        assert_eq!(p.parse_if_expr(), Ok(ExprAST::If { cond, then, else_ }));
+    }
+
+    #[test]
+    fn parse_for() {
+        let mut p = parser("for i = 1, 2, 3 in 4");
+
+        let var = String::from("i");
+        let start = Box::new(ExprAST::Number(1f64));
+        let end = Box::new(ExprAST::Number(2f64));
+        let step = Some(Box::new(ExprAST::Number(3f64)));
+        let body = Box::new(ExprAST::Number(4f64));
+
+        assert_eq!(
+            p.parse_for_expr(),
+            Ok(ExprAST::For {
+                var,
+                start,
+                end,
+                step,
+                body
+            })
+        );
+    }
+
+    #[test]
+    fn parse_for_no_step() {
+        let mut p = parser("for i = 1, 2 in 4");
+
+        let var = String::from("i");
+        let start = Box::new(ExprAST::Number(1f64));
+        let end = Box::new(ExprAST::Number(2f64));
+        let step = None;
+        let body = Box::new(ExprAST::Number(4f64));
+
+        assert_eq!(
+            p.parse_for_expr(),
+            Ok(ExprAST::For {
+                var,
+                start,
+                end,
+                step,
+                body
+            })
+        );
+    }
+
     #[test]
     fn parse_primary() {
-        let mut p = parser("1337 foop \n bla(123)");
+        let mut p = parser("1337 foop \n bla(123) \n if a then b else c \n for x=1,2 in 3");
 
         assert_eq!(p.parse_primary(), Ok(ExprAST::Number(1337f64)));
 
@@ -830,6 +1203,26 @@
             p.parse_primary(),
             Ok(ExprAST::Call("bla".into(), vec![ExprAST::Number(123f64)]))
         );
+
+        assert_eq!(
+            p.parse_primary(),
+            Ok(ExprAST::If {
+                cond: Box::new(ExprAST::Variable("a".into())),
+                then: Box::new(ExprAST::Variable("b".into())),
+                else_: Box::new(ExprAST::Variable("c".into())),
+            })
+        );
+
+        assert_eq!(
+            p.parse_primary(),
+            Ok(ExprAST::For {
+                var: String::from("x"),
+                start: Box::new(ExprAST::Number(1f64)),
+                end: Box::new(ExprAST::Number(2f64)),
+                step: None,
+                body: Box::new(ExprAST::Number(3f64)),
+            })
+        );
     }
 
     #[test]
@@ -919,7 +1312,6 @@
         assert_eq!(p.parse_extern(), Ok(proto));
     }
 }
-
-
- +
+
\ No newline at end of file -- cgit v1.2.3