Skip to content

Commit

Permalink
compiler: minor fixes and improvements for nil analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Aug 22, 2024
1 parent 10e0bce commit 22d3a84
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 12 deletions.
17 changes: 16 additions & 1 deletion src/julec/opt/nil.jule
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
// license that can be found in the LICENSE file.

use std::jule::lex::{TokenId}
use std::jule::sema::{Var, StructSubIdentExprModel, UnaryExprModel, ExprModel, TypeKind}
use std::jule::sema::{
Var,
TypeKind,
ExprModel,
StructSubIdentExprModel,
UnaryExprModel,
BuiltinNewCallExprModel,
}

const invalidNil = 0x0

Expand Down Expand Up @@ -75,6 +82,14 @@ fn possibleNilRemove(mut &n: &nils, m: ExprModel) {
}
}

fn isGuaranteedNonNilExpr(mut &n: &nils, m: ExprModel): bool {
match type m {
| &BuiltinNewCallExprModel:
ret true
}
ret n != nil && n.isSafe(getNilVar(m))
}

fn isNilValidType(mut t: &TypeKind): bool { ret t.Sptr() != nil }

fn getNilVar(m: ExprModel): uintptr {
Expand Down
32 changes: 30 additions & 2 deletions src/julec/opt/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ impl scopeOptimizer {

fn optimizeVar(mut &self, mut v: &Var) {
if v.Value != nil {
if self.data.nils != nil &&
isNilValidType(v.Kind.Kind) &&
isGuaranteedNonNilExpr(self.data.nils, v.Value.Data.Model) {
const safe = true
self.data.nils.pushVar(getNilVar(v), safe)
}
exprOptimizer.optimizeData(v.Value.Data.Model, self.data)
}
}
Expand Down Expand Up @@ -390,7 +396,14 @@ impl scopeOptimizer {
possibleBoundaryRemove(self.data.boundary, assign.L.Model)
}
if self.data.nils != nil {
possibleNilRemove(self.data.nils, assign.L.Model)
if isGuaranteedNonNilExpr(self.data.nils, assign.R.Model) {
if isNilValidType(assign.L.Kind) {
const safe = true
self.data.nils.pushVar(getNilVar(assign.L.Model), safe)
}
} else {
possibleNilRemove(self.data.nils, assign.L.Model)
}
}

match {
Expand Down Expand Up @@ -505,11 +518,26 @@ impl scopeOptimizer {
ret
}

for (_, mut l) in assign.L {
mut tup := (&TupleExprModel)(nil)
match type assign.R {
| &TupleExprModel:
tup = (&TupleExprModel)(assign.R)
}
for (i, mut l) in assign.L {
if l != nil {
if self.data.boundary != nil {
possibleBoundaryRemove(self.data.boundary, l.Model)
}
if self.data.nils != nil {
if tup != nil && isGuaranteedNonNilExpr(self.data.nils, tup.Datas[i].Model) {
if isNilValidType(l.Kind) {
const safe = true
self.data.nils.pushVar(getNilVar(l.Model), safe)
}
} else {
possibleNilRemove(self.data.nils, l.Model)
}
}
exprOptimizer.optimizeData(l.Model, self.data)
}
}
Expand Down
9 changes: 0 additions & 9 deletions std/jule/sema/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -1425,15 +1425,6 @@ impl scopeChecker {
},
}
self.s.checkVarValue(v)
// Set value to nil.
// Because this variable should be uninitialized declaration.
// Otherwise, code generation needs more analysis.
// For references, leave values. References always should be initialized.
// So, some optimizations and utilities may use this rule.
if !v.Reference {
v.Value = nil
}

st.L = append(st.L, &Data{
Lvalue: !v.Constant,
Mutable: v.Mutable,
Expand Down

0 comments on commit 22d3a84

Please sign in to comment.