-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDCE.swift
More file actions
85 lines (75 loc) · 2.09 KB
/
DCE.swift
File metadata and controls
85 lines (75 loc) · 2.09 KB
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
//
// DCE.swift - AST-level Dead Code Elimination
//
// SwiSwi - a tiny Swift-like language
//
// Created for the Budapest Swift Meetup
// by Árpád Goretity (H2CO3)
// on 23/02/2016
//
// There's no warranty whatsoever.
//
func performDCEIfThenElse(ast: IfThenElseAST) -> AST {
if let cond = ast.condition as? IdentifierAST {
switch cond.name {
case "true":
// replace always-true 'if' by 'then' clause
return ast.thenBranch
case "false":
// replace always-false 'if' by 'else' clause (if any), or by an empty statement otherwise
if let elseBranch = ast.elseBranch {
return elseBranch
} else {
return EmptyStmtAST(ast.loc)
}
default:
break
}
}
// recurse into children for dead code
ast.thenBranch = performDCEBlock(ast.thenBranch)
if let elseBranch = ast.elseBranch {
ast.elseBranch = performDCE(elseBranch)
}
return ast
}
func performDCEWhileLoop(ast: WhileLoopAST) -> AST {
// remove while loop with constant false condition
if let cond = ast.condition as? IdentifierAST {
if cond.name == "false" {
// print("found dead loop body!")
return EmptyStmtAST(ast.loc)
}
}
// if the loop body itself is not dead, still search its children for dead code.
ast.body = performDCEBlock(ast.body)
return ast
}
func performDCEBlock(ast: BlockAST) -> BlockAST {
ast.children = ast.children.map(performDCE)
return ast
}
func performDCEProgram(ast: ProgramAST) -> ProgramAST {
ast.children = ast.children.map(performDCE)
return ast
}
func performDCEFunction(ast: FuncDefAST) -> FuncDefAST {
ast.body = performDCEBlock(ast.body)
return ast
}
func performDCE(ast: AST) -> AST {
switch ast {
case let program as ProgramAST:
return performDCEProgram(program)
case let block as BlockAST:
return performDCEBlock(block)
case let ifThenElse as IfThenElseAST:
return performDCEIfThenElse(ifThenElse)
case let whileLoop as WhileLoopAST:
return performDCEWhileLoop(whileLoop)
case let funcDef as FuncDefAST:
return performDCEFunction(funcDef)
default:
return ast // other kinds of statements can't contain nested statements AND be at the top level at once
}
}