Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Fix reference to literals (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavrilikhin-d authored Apr 28, 2024
1 parent 082b395 commit b6f7f41
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 11 deletions.
5 changes: 4 additions & 1 deletion src/hir/expressions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ pub use constructor::*;
mod implicit_conversion;
pub use implicit_conversion::*;

use crate::{mutability::Mutable, syntax::Ranged};
use crate::{
mutability::{Mutability, Mutable},
syntax::Ranged,
};

use derive_more::Display;

Expand Down
9 changes: 9 additions & 0 deletions src/mutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ pub trait Mutable {
fn is_immutable(&self) -> bool {
!self.is_mutable()
}

/// Get the mutability of this binding
fn mutability(&self) -> Mutability {
if self.is_mutable() {
Mutability::Mutable
} else {
Mutability::Immutable
}
}
}

impl Mutable for Mutability {
Expand Down
30 changes: 20 additions & 10 deletions src/semantics/tmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use derive_visitor::VisitorMut;

use crate::{
hir::{
Block, Declaration, Return, Statement, Typed, Variable, VariableData, VariableReference,
Block, Declaration, Expression, ImplicitConversion, ImplicitConversionKind, Return,
Statement, Typed, Variable, VariableData, VariableReference,
},
mutability::Mutability,
mutability::Mutable,
syntax::{Identifier, Keyword, Ranged},
};

#[derive(VisitorMut)]
#[visitor(Statement(exit), Return(enter))]
#[visitor(Statement(exit), Return(enter), ImplicitConversion(enter))]
pub struct TemporariesInserter {
temporaries: Vec<Variable>,
}
Expand All @@ -23,16 +24,11 @@ impl<'ctx> TemporariesInserter {
}
}

fn enter_return(&mut self, ret: &mut Return) {
if ret.value().is_none() {
return;
}

let expr = ret.value_mut().unwrap();
fn replace_with_tmp(&mut self, expr: &mut Expression) {
let offset = expr.start();
let tmp = Variable::new(VariableData {
keyword: Keyword::<"let">::at(offset),
mutability: Mutability::Immutable,
mutability: expr.mutability(),
name: Identifier::from(format!("$tmp@{offset}")).at(offset),
type_reference: None,
ty: expr.ty(),
Expand All @@ -46,6 +42,20 @@ impl<'ctx> TemporariesInserter {
self.temporaries.push(tmp);
}

fn enter_implicit_conversion(&mut self, conv: &mut ImplicitConversion) {
if conv.kind != ImplicitConversionKind::Reference
|| !matches!(*conv.expression, Expression::Literal(_))
{
return;
}

self.replace_with_tmp(&mut conv.expression)
}

fn enter_return(&mut self, ret: &mut Return) {
ret.value_mut().map(|expr| self.replace_with_tmp(expr));
}

fn exit_statement(&mut self, stmt: &mut Statement) {
if self.temporaries.is_empty() {
return;
Expand Down
11 changes: 11 additions & 0 deletions src/tests/snapshots/ppl__tests__reference_to_literal.hir.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: src/tests/mod.rs
expression: hir
---
fn foo <x: Reference<Integer>> -> None:
let $tmp@24: None = println (*x:Integer)
return ($tmp@24:None)

let $tmp@39: Integer = 42
foo (&$tmp@39:Reference<Integer>)
destroy ($tmp@39:Integer)
110 changes: 110 additions & 0 deletions src/tests/snapshots/ppl__tests__reference_to_literal.ir.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
source: src/tests/mod.rs
expression: ir
---
; ModuleID = 'main'
source_filename = "src/main.ppl"

%"Type<String>" = type { %String, %Integer }
%String = type { ptr }
%Integer = type { ptr }

@"Type<String>" = private global %"Type<String>" zeroinitializer
@0 = private unnamed_addr constant [7 x i8] c"String\00", align 1
@"$tmp@39" = global %Integer zeroinitializer

define private void @initialize() !dbg !3 {
%1 = alloca %"Type<String>", align 8, !dbg !7
%"Type<String>.name" = getelementptr inbounds %"Type<String>", ptr %1, i32 0, i32 0, !dbg !7
%2 = call %String @string_from_c_string_and_length(ptr @0, i64 6), !dbg !8
store %String %2, ptr %"Type<String>.name", align 8, !dbg !8
%"Type<String>.size" = getelementptr inbounds %"Type<String>", ptr %1, i32 0, i32 1, !dbg !8
%3 = call %Integer @integer_from_i64(i64 8), !dbg !8
store %Integer %3, ptr %"Type<String>.size", align 8, !dbg !8
%4 = load %"Type<String>", ptr %1, align 8, !dbg !8
store %"Type<String>" %4, ptr @"Type<String>", align 8, !dbg !8
br label %return, !dbg !8

return: ; preds = %0
ret void
}

declare %String @string_from_c_string_and_length(ptr, i64)

declare %Integer @integer_from_i64(i64)

define void @main.execute() !dbg !9 {
call void @initialize(), !dbg !10
call void @initialize.1(), !dbg !11
call void @"foo <:Reference<Integer>>"(ptr @"$tmp@39"), !dbg !11
call void @destroy_integer(ptr @"$tmp@39"), !dbg !11
br label %return, !dbg !11

return: ; preds = %0
ret void
}

define void @"foo <:Reference<Integer>>"(ptr %0) !dbg !12 {
%x = alloca ptr, align 8
store ptr %0, ptr %x, align 8
%2 = load ptr, ptr %x, align 8, !dbg !13
%3 = load %Integer, ptr %2, align 8, !dbg !13
call void @"println <:Integer>"(%Integer %3), !dbg !13
br label %return, !dbg !14

return: ; preds = %1
ret void
}

define private void @"println <:Integer>"(%Integer %0) !dbg !15 {
%x = alloca %Integer, align 8
store %Integer %0, ptr %x, align 8
%2 = load %Integer, ptr %x, align 8, !dbg !16
%3 = call %Integer @clone_integer(%Integer %2), !dbg !16
%4 = call %String @integer_as_string(%Integer %3), !dbg !16
call void @"println <:String>"(%String %4), !dbg !16
br label %return, !dbg !16

return: ; preds = %1
ret void
}

declare void @"println <:String>"(%String)

declare %String @integer_as_string(%Integer)

declare %Integer @clone_integer(%Integer)

define private void @initialize.1() !dbg !17 {
%1 = call %Integer @integer_from_i64(i64 42), !dbg !18
store %Integer %1, ptr @"$tmp@39", align 8, !dbg !18
br label %return, !dbg !18

return: ; preds = %0
ret void
}

declare void @destroy_integer(ptr)

!llvm.module.flags = !{!0}
!llvm.dbg.cu = !{!1}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: "ppl", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, sysroot: "/")
!2 = !DIFile(filename: "src/main.ppl", directory: ".")
!3 = distinct !DISubprogram(name: "initialize", linkageName: "initialize", scope: !2, file: !2, line: 2, type: !4, spFlags: DISPFlagDefinition, unit: !1)
!4 = !DISubroutineType(types: !5)
!5 = !{!6}
!6 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
!7 = !DILocation(line: 2, column: 6, scope: !3)
!8 = !DILocation(line: 0, scope: !3)
!9 = distinct !DISubprogram(name: "main.execute", linkageName: "main.execute", scope: !2, file: !2, type: !4, spFlags: DISPFlagDefinition, unit: !1)
!10 = !DILocation(line: 2, column: 6, scope: !9)
!11 = !DILocation(line: 2, column: 4, scope: !9)
!12 = distinct !DISubprogram(name: "foo <:Reference<Integer>>", linkageName: "foo <:Reference<Integer>>", scope: !9, file: !2, type: !4, spFlags: DISPFlagDefinition, unit: !1)
!13 = !DILocation(line: 0, column: 32, scope: !12)
!14 = !DILocation(line: 0, column: 24, scope: !12)
!15 = distinct !DISubprogram(name: "println <:Integer>", linkageName: "println <:Integer>", scope: !12, file: !2, line: 2, type: !4, spFlags: DISPFlagDefinition, unit: !1)
!16 = !DILocation(line: 2, column: 6, scope: !15)
!17 = distinct !DISubprogram(name: "initialize.1", linkageName: "initialize.1", scope: !9, file: !2, line: 2, type: !4, spFlags: DISPFlagDefinition, unit: !1)
!18 = !DILocation(line: 2, column: 4, scope: !17)
5 changes: 5 additions & 0 deletions src/tests/snapshots/ppl__tests__reference_to_literal.run.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: src/tests/mod.rs
expression: run_log
---
42

0 comments on commit b6f7f41

Please sign in to comment.