11use crate :: compiler:: lexer:: Token ;
22use slotmap:: { DefaultKey , SlotMap } ;
33use smol_str:: SmolStr ;
4+ use std:: collections:: HashMap ;
5+ use linked_hash_map:: LinkedHashMap ;
6+
7+ #[ derive( Copy , Clone , Default , Eq , PartialEq , Ord , PartialOrd , Hash , Debug ) ]
8+ pub struct LocalAddr {
9+ pub offset : usize ,
10+ }
411
512#[ derive( Clone , Debug , PartialEq ) ]
613pub enum Operand {
@@ -34,51 +41,164 @@ pub struct Value {
3441}
3542
3643#[ derive( Clone , Debug , PartialEq ) ]
37- #[ allow( dead_code) ] //TODO
44+ #[ allow( dead_code) ] // TODO
3845pub enum OpCode {
39- StackLocal ( DefaultKey , Operand ) , // 栈局部变量加载
40- StoreLocal ( DefaultKey , Operand ) , // 将一个变量加载到栈顶
41- Push ( Operand ) , // 将值压入操作栈
42- Call ( SmolStr ) , // 函数调用 (调用路径) : 只能被 Ref 操作触发
43- Return , // 栈顶结果返回
44- Add , // 从栈顶提取两个操作数相加并将结果压回操作栈
45- Sub , // -
46- Mul , // *
47- Div , // /
48- And , // &&
49- Or , // ||
50- Rmd , // %
51- Equ , // ==
52- SAdd , // ++
53- SSub , // --
54- Not , // !
55- NotEqu , // !=
56- BigEqu , // >=
57- LesEqu , // <=
58- Big , // >
59- Less , // <
60- Store , // =
61- AddS , // +=
62- SubS , // -=
63- MulS , // *=
64- DivS , // /=
65- RmdS , // %=
66- BitAnd , // &
67- BitOr , // |
68- BitXor , // ^
69- BAndS , // &=
70- BOrS , // |=
71- BXorS , // ^=
72- BLeft , // <<
73- BRight , // >>
74- Ref , // .
75- AIndex , // 数组索引
46+ // Option<LocalAddr> 为各 IR 的逻辑地址
47+ StackLocal ( Option < LocalAddr > , DefaultKey , Operand ) , // 栈局部变量加载
48+ StoreLocal ( Option < LocalAddr > , DefaultKey , Operand ) , // 将一个变量加载到栈顶
49+ Push ( Option < LocalAddr > , Operand ) , // 将值压入操作栈
50+ Call ( Option < LocalAddr > , SmolStr ) , // 函数调用
51+ Jump ( Option < LocalAddr > , LocalAddr ) , // 无条件跳转
52+ JumpTrue ( Option < LocalAddr > , Option < LocalAddr > , Operand ) , // 栈顶结果为真则跳转
53+ Return ( Option < LocalAddr > ) , // 栈顶结果返回
54+ Break ( Option < LocalAddr > ) , // 退出循环
55+ Continue ( Option < LocalAddr > ) , // 取消本次循环
56+ Nop ( Option < LocalAddr > ) , // 空操作
57+
58+ Add ( Option < LocalAddr > ) , // +
59+ Sub ( Option < LocalAddr > ) , // -
60+ Mul ( Option < LocalAddr > ) , // *
61+ Div ( Option < LocalAddr > ) , // /
62+ And ( Option < LocalAddr > ) , // &&
63+ Or ( Option < LocalAddr > ) , // ||
64+ Rmd ( Option < LocalAddr > ) , // %
65+
66+ Equ ( Option < LocalAddr > ) , // ==
67+ NotEqu ( Option < LocalAddr > ) , // !=
68+ BigEqu ( Option < LocalAddr > ) , // >=
69+ LesEqu ( Option < LocalAddr > ) , // <=
70+ Big ( Option < LocalAddr > ) , // >
71+ Less ( Option < LocalAddr > ) , // <
72+
73+ SAdd ( Option < LocalAddr > ) , // ++
74+ SSub ( Option < LocalAddr > ) , // --
75+
76+ Not ( Option < LocalAddr > ) , // !
77+
78+ Store ( Option < LocalAddr > ) , // =
79+ AddS ( Option < LocalAddr > ) , // +=
80+ SubS ( Option < LocalAddr > ) , // -=
81+ MulS ( Option < LocalAddr > ) , // *=
82+ DivS ( Option < LocalAddr > ) , // /=
83+ RmdS ( Option < LocalAddr > ) , // %=
84+
85+ BitAnd ( Option < LocalAddr > ) , // &
86+ BitOr ( Option < LocalAddr > ) , // |
87+ BitXor ( Option < LocalAddr > ) , // ^
88+
89+ BAndS ( Option < LocalAddr > ) , // &=
90+ BOrS ( Option < LocalAddr > ) , // |=
91+ BXorS ( Option < LocalAddr > ) , // ^=
92+
93+ BLeft ( Option < LocalAddr > ) , // <<
94+ BRight ( Option < LocalAddr > ) , // >>
95+
96+ Ref ( Option < LocalAddr > ) , // .
97+ AIndex ( Option < LocalAddr > ) , // 数组索引
98+ }
99+
100+ impl OpCode {
101+ fn relocate_addr ( & mut self , addr_map : & HashMap < LocalAddr , LocalAddr > ) {
102+ // 重定位第一个字段:Option<LocalAddr>
103+ if let Some ( new_addr) = addr_map. get ( & self . get_id ( ) ) {
104+ self . set_id ( * new_addr) ;
105+ }
106+
107+ // 重定位 Jump 和 JumpTrue 的跳转目标
108+ match self {
109+ OpCode :: Jump ( _, target_addr) => {
110+ if let Some ( new_addr) = addr_map. get ( target_addr) {
111+ * target_addr = * new_addr;
112+ }
113+ }
114+ OpCode :: JumpTrue ( _, target, ..) => {
115+ if let Some ( j_target) = target
116+ && let Some ( & new_target) = addr_map. get ( j_target)
117+ {
118+ * target = Some ( new_target) ;
119+ }
120+ }
121+ // 其他 OpCode 没有额外的 LocalAddr 字段
122+ _ => { }
123+ }
124+ }
76125}
77126
78- #[ derive( Clone , Debug ) ]
127+ #[ derive( Debug , PartialEq , Clone ) ]
128+ pub struct OpCodeTable {
129+ opcodes : LinkedHashMap < LocalAddr , OpCode > ,
130+ alloc_addr : LocalAddr ,
131+ }
132+
133+ impl OpCodeTable {
134+ pub fn new ( ) -> Self {
135+ OpCodeTable {
136+ opcodes : LinkedHashMap :: new ( ) ,
137+ alloc_addr : LocalAddr { offset : 0 } ,
138+ }
139+ }
140+
141+ pub fn add_opcode ( & mut self , opcode : OpCode ) -> LocalAddr {
142+ let addr = self . alloc_addr ;
143+ self . opcodes . insert ( addr, opcode) ;
144+ self . alloc_addr . offset += 1 ;
145+ if let Some ( op) = self . opcodes . get_mut ( & addr) {
146+ op. set_id ( addr) ;
147+ } else {
148+ unreachable ! ( )
149+ }
150+ addr
151+ }
152+
153+ // 返回IR块最后一条IR的逻辑地址
154+ pub fn append_code ( & mut self , code : & mut OpCodeTable ) -> ( LocalAddr , Option < LocalAddr > ) {
155+ let start_offset = self . alloc_addr . offset ;
156+ if code. opcodes . is_empty ( ) {
157+ return ( LocalAddr {
158+ offset : self . alloc_addr . offset ,
159+ } , None ) ;
160+ }
161+ let mut old_to_new: HashMap < LocalAddr , LocalAddr > = HashMap :: new ( ) ;
162+
163+ // 遍历所有 opcode(按 offset 顺序)
164+ let mut entries: Vec < _ > = code. opcodes . iter ( ) . collect ( ) ;
165+ entries. sort_unstable_by_key ( |& ( addr, _) | addr. offset ) ;
166+
167+ // 为每个旧地址分配新地址
168+ for ( old_addr, _) in & entries {
169+ let od = * * old_addr;
170+ old_to_new. insert (
171+ od,
172+ LocalAddr {
173+ offset : self . alloc_addr . offset ,
174+ } ,
175+ ) ;
176+ self . alloc_addr . offset += 1 ;
177+ }
178+
179+ // 插入并重定位
180+ let mut last_addr = None ;
181+ for ( old_addr, op) in entries {
182+ let mut new_op = op. clone ( ) ;
183+ new_op. relocate_addr ( & old_to_new) ;
184+
185+ let new_addr = old_to_new[ old_addr] ;
186+ self . opcodes . insert ( new_addr, new_op) ;
187+ last_addr = Some ( new_addr) ;
188+ }
189+
190+ ( LocalAddr { offset : start_offset} , last_addr)
191+ }
192+
193+ pub fn find_code_mut ( & mut self , key : LocalAddr ) -> Option < & mut OpCode > {
194+ self . opcodes . get_mut ( & key)
195+ }
196+ }
197+
198+ #[ derive( Debug , Clone ) ]
79199#[ allow( dead_code) ] //TODO
80200pub struct Code {
81- codes : Vec < OpCode > ,
201+ codes : OpCodeTable ,
82202 values : SlotMap < DefaultKey , Value > ,
83203 stack_size : usize ,
84204 root : bool , // 是否是根脚本上下文 (true: 根上下文|false: 函数上下文)
@@ -87,19 +207,15 @@ pub struct Code {
87207impl Code {
88208 pub fn new ( root : bool ) -> Code {
89209 Self {
90- codes : vec ! [ ] ,
210+ codes : OpCodeTable :: new ( ) ,
91211 values : SlotMap :: new ( ) ,
92212 stack_size : 0 ,
93213 root,
94214 }
95215 }
96216
97- pub fn add_opcode ( & mut self , opcode : OpCode ) {
98- self . codes . push ( opcode) ;
99- }
100-
101- pub fn append_code ( & mut self , code : & mut Vec < OpCode > ) {
102- self . codes . append ( code) ;
217+ pub fn get_code_table ( & mut self ) -> & mut OpCodeTable {
218+ & mut self . codes
103219 }
104220
105221 pub fn find_value_key ( & mut self , name : SmolStr ) -> Option < DefaultKey > {
@@ -124,3 +240,62 @@ impl Code {
124240 self . values . insert ( va)
125241 }
126242}
243+
244+ macro_rules! mathch_opcodes {
245+ ( $expr: expr, $slot: ident, $stmt: expr) => {
246+ match $expr {
247+ OpCode :: StackLocal ( $slot, ..)
248+ | OpCode :: StoreLocal ( $slot, ..)
249+ | OpCode :: Push ( $slot, ..)
250+ | OpCode :: Call ( $slot, ..)
251+ | OpCode :: Jump ( $slot, ..)
252+ | OpCode :: JumpTrue ( $slot, ..)
253+ | OpCode :: Return ( $slot)
254+ | OpCode :: Break ( $slot)
255+ | OpCode :: Continue ( $slot)
256+ | OpCode :: Add ( $slot)
257+ | OpCode :: Sub ( $slot)
258+ | OpCode :: Mul ( $slot)
259+ | OpCode :: Div ( $slot)
260+ | OpCode :: And ( $slot)
261+ | OpCode :: Or ( $slot)
262+ | OpCode :: Rmd ( $slot)
263+ | OpCode :: Equ ( $slot)
264+ | OpCode :: NotEqu ( $slot)
265+ | OpCode :: BigEqu ( $slot)
266+ | OpCode :: LesEqu ( $slot)
267+ | OpCode :: Big ( $slot)
268+ | OpCode :: Less ( $slot)
269+ | OpCode :: SAdd ( $slot)
270+ | OpCode :: SSub ( $slot)
271+ | OpCode :: Not ( $slot)
272+ | OpCode :: Store ( $slot)
273+ | OpCode :: AddS ( $slot)
274+ | OpCode :: SubS ( $slot)
275+ | OpCode :: MulS ( $slot)
276+ | OpCode :: DivS ( $slot)
277+ | OpCode :: RmdS ( $slot)
278+ | OpCode :: BitAnd ( $slot)
279+ | OpCode :: BitOr ( $slot)
280+ | OpCode :: BitXor ( $slot)
281+ | OpCode :: BAndS ( $slot)
282+ | OpCode :: BOrS ( $slot)
283+ | OpCode :: BXorS ( $slot)
284+ | OpCode :: BLeft ( $slot)
285+ | OpCode :: BRight ( $slot)
286+ | OpCode :: Ref ( $slot)
287+ | OpCode :: AIndex ( $slot)
288+ | OpCode :: Nop ( $slot) => $stmt,
289+ }
290+ } ;
291+ }
292+
293+ impl OpCode {
294+ pub fn get_id ( & self ) -> LocalAddr {
295+ mathch_opcodes ! ( self , slot, slot) . unwrap ( )
296+ }
297+
298+ pub fn set_id ( & mut self , id : LocalAddr ) {
299+ mathch_opcodes ! ( self , slot, * slot = Some ( id) ) ;
300+ }
301+ }
0 commit comments