forked from nulang-org/nulang
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfix_wasm.py
More file actions
124 lines (111 loc) · 5.68 KB
/
Copy pathfix_wasm.py
File metadata and controls
124 lines (111 loc) · 5.68 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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import re
with open("src/mir_wasm.rs", "r") as f:
content = f.read()
# 1. Fix 256 locals
content = re.sub(
r"let local_count = func\.locals\.len\(\) \+ func\.params\.len\(\) \+ func\.captures\.len\(\);\n\s*let wasm_locals: Vec<_> = \(0\.\.local_count\)\.map\(\|\_\| \(1u32, ValType::I64\)\)\.collect\(\);",
r"let local_count = func.locals.len() + func.params.len() + func.captures.len();\n let wasm_locals: Vec<_> = vec![(256u32, ValType::I64)];",
content
)
# 2. Pass func to compile_terminator
content = re.sub(
r"self\.compile_terminator\(&mut body, &block\.terminator, &labels, li\);",
r"self.compile_terminator(&mut body, &block.terminator, &labels, li, func);",
content
)
content = re.sub(
r"fn compile_terminator\(\n\s*&self,\n\s*body: &mut Function,\n\s*term: &Terminator,\n\s*labels: &HashMap<BlockId, u32>,\n\s*cur: u32,\n\s*\)",
r"fn compile_terminator(\n &self,\n body: &mut Function,\n term: &Terminator,\n labels: &HashMap<BlockId, u32>,\n cur: u32,\n func: &mir::Function,\n )",
content
)
# 3. Fix Branch Terminator
content = re.sub(
r"Terminator::Branch \{ cond, then_, else_ \} => \{\n\s*body\.instruction\(&Instruction::LocalGet\(cond\.0\)\);\n\s*body\.instruction\(&Instruction::I64Const\(1\)\);\n\s*body\.instruction\(&Instruction::I64And\);",
r"Terminator::Branch { cond, then_, else_ } => {\n body.instruction(&Instruction::LocalGet(self.mir_local(cond, func)));\n body.instruction(&Instruction::I64Const(1));\n body.instruction(&Instruction::I64And);\n body.instruction(&Instruction::I32WrapI64);",
content
)
# 4. Fix Unary Ops
content = re.sub(
r"RValue::Unary\(_, _\) => \{\n\s*body\.instruction\(&Instruction::I64Const\(value_layout::TAG_NIL as i64\)\);\n\s*\}",
r"""RValue::Unary(op, a) => {
self.compile_unary(body, *op, a, func);
}""",
content
)
unary_impl = """ fn compile_unary(
&self,
body: &mut Function,
op: crate::ast::UnOp,
a: &mir::LocalId,
func: &mir::Function,
) {
use crate::ast::UnOp;
let pm = value_layout::PAYLOAD_MASK as i64;
match op {
UnOp::Neg => {
body.instruction(&Instruction::I64Const(0));
body.instruction(&Instruction::LocalGet(self.mir_local(a, func)));
body.instruction(&Instruction::I64Const(pm));
body.instruction(&Instruction::I64And);
body.instruction(&Instruction::I64Sub);
body.instruction(&Instruction::I64Const(pm));
body.instruction(&Instruction::I64And);
body.instruction(&Instruction::I64Const(value_layout::TAG_INT as i64));
body.instruction(&Instruction::I64Or);
}
UnOp::Not => {
let tf = value_layout::tag_bool(false) as i64;
let tt = value_layout::tag_bool(true) as i64;
body.instruction(&Instruction::LocalGet(self.mir_local(a, func)));
body.instruction(&Instruction::I64Const(tt));
body.instruction(&Instruction::I64Eq);
body.instruction(&Instruction::I64ExtendI32S);
body.instruction(&Instruction::I64Const(tf - tt));
body.instruction(&Instruction::I64Mul);
body.instruction(&Instruction::I64Const(tt));
body.instruction(&Instruction::I64Add);
}
_ => {
body.instruction(&Instruction::I64Const(value_layout::TAG_NIL as i64));
}
}
}
"""
content = content.replace(" fn compile_const(", unary_impl + " fn compile_const(")
# 5. Fix Binary Ops
content = re.sub(
r"body\.instruction\(&Instruction::LocalGet\(254\)\);\n\n\s*match op \{",
r"""body.instruction(&Instruction::LocalGet(254));
let sign_extend_both = |b: &mut Function| {
b.instruction(&Instruction::LocalSet(254));
b.instruction(&Instruction::I64Const(16));
b.instruction(&Instruction::I64Shl);
b.instruction(&Instruction::I64Const(16));
b.instruction(&Instruction::I64ShrS);
b.instruction(&Instruction::LocalGet(254));
b.instruction(&Instruction::I64Const(16));
b.instruction(&Instruction::I64Shl);
b.instruction(&Instruction::I64Const(16));
b.instruction(&Instruction::I64ShrS);
};
match op {""",
content
)
content = content.replace(
"BinOp::Div => {\n body.instruction(&Instruction::I64DivS);\n }",
"BinOp::Div => {\n sign_extend_both(body);\n body.instruction(&Instruction::I64DivS);\n }"
)
content = content.replace(
"BinOp::Mod => {\n body.instruction(&Instruction::I64RemS);\n }",
"BinOp::Mod => {\n sign_extend_both(body);\n body.instruction(&Instruction::I64RemS);\n }"
)
content = content.replace(
"cmp @ (BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Gt | BinOp::Le | BinOp::Ge) => {\n match cmp {",
"cmp @ (BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Gt | BinOp::Le | BinOp::Ge) => {\n sign_extend_both(body);\n match cmp {"
)
content = content.replace(
"body.instruction(&Instruction::I64Const(ti));\n body.instruction(&Instruction::I64Or);",
"body.instruction(&Instruction::I64Const(pm));\n body.instruction(&Instruction::I64And);\n body.instruction(&Instruction::I64Const(ti));\n body.instruction(&Instruction::I64Or);"
)
with open("src/mir_wasm.rs", "w") as f:
f.write(content)