1use std::collections::HashMap;
2use std::convert::TryFrom;
3use std::rc::Rc;
4
5use super::branch::*;
6use super::emit::*;
7use super::interface::IfaceMapping;
8use super::package::PkgUtil;
9use super::types::{TypeCache, TypeLookup};
10
11use goscript_vm::gc::GcoVec;
12use goscript_vm::instruction::*;
13use goscript_vm::metadata::*;
14use goscript_vm::objects::EntIndex;
15use goscript_vm::value::*;
16use goscript_vm::zero_val;
17
18use goscript_parser::ast::*;
19use goscript_parser::objects::Objects as AstObjects;
20use goscript_parser::objects::*;
21use goscript_parser::position::Pos;
22use goscript_parser::token::Token;
23use goscript_parser::visitor::{walk_decl, walk_expr, walk_stmt, ExprVisitor, StmtVisitor};
24use goscript_types::{
25 identical, Builtin, OperandMode, PackageKey as TCPackageKey, TCObjects, TypeInfo,
26 TypeKey as TCTypeKey,
27};
28
29macro_rules! current_func_mut {
30 ($owner:ident) => {
31 &mut $owner.objects.functions[*$owner.func_stack.last().unwrap()]
32 };
33}
34
35macro_rules! current_func {
36 ($owner:ident) => {
37 &$owner.objects.functions[*$owner.func_stack.last().unwrap()]
38 };
39}
40
41macro_rules! current_func_emitter {
42 ($owner:ident) => {
43 Emitter::new(current_func_mut!($owner))
44 };
45}
46
47pub struct CodeGen<'a> {
49 objects: &'a mut VMObjects,
50 ast_objs: &'a AstObjects,
51 tc_objs: &'a TCObjects,
52 dummy_gcv: &'a mut GcoVec,
53 tlookup: TypeLookup<'a>,
54 iface_mapping: &'a mut IfaceMapping,
55 pkg_util: PkgUtil<'a>,
56 branch: BranchHelper,
57 pkg_key: PackageKey,
58 func_stack: Vec<FunctionKey>,
59 func_t_stack: Vec<TCTypeKey>, blank_ident: IdentKey,
61}
62
63impl<'a> CodeGen<'a> {
64 pub fn new(
65 vmo: &'a mut VMObjects,
66 asto: &'a AstObjects,
67 tco: &'a TCObjects,
68 dummy_gcv: &'a mut GcoVec,
69 ti: &'a TypeInfo,
70 type_cache: &'a mut TypeCache,
71 mapping: &'a mut IfaceMapping,
72 pkg_indices: &'a HashMap<TCPackageKey, OpIndex>,
73 pkgs: &'a Vec<PackageKey>,
74 pkg: PackageKey,
75 bk: IdentKey,
76 ) -> CodeGen<'a> {
77 CodeGen {
78 objects: vmo,
79 ast_objs: asto,
80 tc_objs: tco,
81 dummy_gcv: dummy_gcv,
82 tlookup: TypeLookup::new(tco, ti, type_cache),
83 iface_mapping: mapping,
84 pkg_util: PkgUtil::new(asto, tco, pkg_indices, pkgs, pkg),
85 branch: BranchHelper::new(),
86 pkg_key: pkg,
87 func_stack: Vec::new(),
88 func_t_stack: Vec::new(),
89 blank_ident: bk,
90 }
91 }
92
93 pub fn pkg_util(&mut self) -> &mut PkgUtil<'a> {
94 &mut self.pkg_util
95 }
96
97 fn resolve_any_ident(&mut self, ident: &IdentKey, expr: Option<&Expr>) -> EntIndex {
98 let id = &self.ast_objs.idents[*ident];
99 match id.entity_key() {
100 None => match expr.map_or(&OperandMode::Value, |x| self.tlookup.get_expr_mode(x)) {
101 OperandMode::TypeExpr => {
102 let lookup = &self.tlookup;
103 let tctype = lookup.underlying_tc(lookup.get_use_tc_type(*ident));
104 let meta = lookup.basic_type_from_tc(tctype, self.objects);
105 EntIndex::BuiltInType(meta)
106 }
107 OperandMode::Value => match &*id.name {
108 "true" => EntIndex::BuiltInVal(Opcode::PUSH_TRUE),
109 "false" => EntIndex::BuiltInVal(Opcode::PUSH_FALSE),
110 "nil" => EntIndex::BuiltInVal(Opcode::PUSH_NIL),
111 _ => unreachable!(),
112 },
113 _ => unreachable!(),
114 },
115 Some(_) => self.resolve_var_ident(ident),
116 }
117 }
118
119 fn resolve_var_ident(&mut self, ident: &IdentKey) -> EntIndex {
120 let entity_key = &self.ast_objs.idents[*ident].entity_key().unwrap();
121 if let Some(index) = current_func!(self).entity_index(&entity_key).map(|x| *x) {
123 return index;
124 }
125 let upvalue = self
127 .func_stack
128 .clone()
129 .iter()
130 .skip(1) .rev()
132 .skip(1) .find_map(|ifunc| {
134 let f = &mut self.objects.functions[*ifunc];
135 let index = f.entity_index(&entity_key).map(|x| *x);
136 if let Some(ind) = index {
137 let desc = ValueDesc::new(
138 *ifunc,
139 ind.into(),
140 self.tlookup.get_use_value_type(*ident),
141 true,
142 );
143 Some(desc)
144 } else {
145 None
146 }
147 });
148 if let Some(uv) = upvalue {
149 let func = current_func_mut!(self);
150 let index = func.try_add_upvalue(&entity_key, uv);
151 return index;
152 }
153 EntIndex::PackageMember(self.pkg_key, *ident)
155 }
156
157 fn add_local_or_resolve_ident(
158 &mut self,
159 ikey: &IdentKey,
160 is_def: bool,
161 ) -> (EntIndex, Option<TCTypeKey>, usize) {
162 let ident = &self.ast_objs.idents[*ikey];
163 let pos = ident.pos;
164 if ident.is_blank() {
165 return (EntIndex::Blank, None, pos);
166 }
167 if is_def {
168 let meta = self
169 .tlookup
170 .gen_def_type_meta(*ikey, self.objects, self.dummy_gcv);
171 let zero_val = zero_val!(meta, self.objects, self.dummy_gcv);
172 let func = current_func_mut!(self);
173 let ident_key = ident.entity.clone().into_key();
174 let index = func.add_local(ident_key);
175 func.add_local_zero(zero_val);
176 if func.is_ctor() {
177 let pkg_key = func.package;
178 let pkg = &mut self.objects.packages[pkg_key];
179 pkg.add_var_mapping(ident.name.clone(), index.into());
180 }
181 let t = self.tlookup.get_def_tc_type(*ikey);
182 (index, Some(t), pos)
183 } else {
184 let index = self.resolve_var_ident(ikey);
185 let t = self.tlookup.get_use_tc_type(*ikey);
186 (index, Some(t), pos)
187 }
188 }
189
190 fn gen_def_var(&mut self, vs: &ValueSpec) {
191 let lhs = vs
192 .names
193 .iter()
194 .map(|n| -> (LeftHandSide, Option<TCTypeKey>, usize) {
195 let (index, t, pos) = self.add_local_or_resolve_ident(n, true);
196 (LeftHandSide::Primitive(index), t, pos)
197 })
198 .collect::<Vec<(LeftHandSide, Option<TCTypeKey>, usize)>>();
199 let rhs = if vs.values.is_empty() {
200 RightHandSide::Nothing
201 } else {
202 RightHandSide::Values(&vs.values)
203 };
204 self.gen_assign_def_var(&lhs, &vs.typ, &rhs);
205 }
206
207 fn gen_def_const(&mut self, names: &Vec<IdentKey>, values: &Vec<Expr>) {
208 assert!(names.len() == values.len());
209 for i in 0..names.len() {
210 let ident = self.ast_objs.idents[names[i]].clone();
211 let val = self.tlookup.get_const_value(values[i].id());
212 self.current_func_add_const_def(&ident, val);
213 }
214 }
215
216 fn gen_assign(
224 &mut self,
225 token: &Token,
226 lhs_exprs: &Vec<&Expr>,
227 rhs: RightHandSide,
228 ) -> Option<usize> {
229 let lhs = lhs_exprs
230 .iter()
231 .map(|expr| {
232 match expr {
233 Expr::Ident(ident) => {
234 let mut is_def = *token == Token::DEFINE;
236 if is_def {
237 let entity = &self.ast_objs.idents[*ident].entity_key();
238 is_def = entity.is_some()
239 && current_func!(self)
240 .entity_index(entity.as_ref().unwrap())
241 .is_none();
242 }
243 let (idx, t, p) = self.add_local_or_resolve_ident(ident, is_def);
244 (LeftHandSide::Primitive(idx), t, p)
245 }
246 Expr::Index(ind_expr) => {
247 let obj = &ind_expr.as_ref().expr;
248 self.visit_expr(obj);
249 let obj_typ = self.tlookup.get_expr_value_type(obj);
250 let ind = &ind_expr.as_ref().index;
251 let pos = ind_expr.as_ref().l_brack;
252
253 let mut index_const = None;
254 let mut index_typ = None;
255 if let Some(const_val) = self.tlookup.get_tc_const_value(ind.id()) {
256 let (ival, _) = const_val.to_int().int_as_i64();
257 if let Ok(i) = OpIndex::try_from(ival) {
258 index_const = Some(i);
259 }
260 }
261 if index_const.is_none() {
262 self.visit_expr(ind);
263 index_typ = Some(self.tlookup.get_expr_value_type(ind));
264 }
265 (
266 LeftHandSide::IndexSelExpr(IndexSelInfo::new(
267 0,
268 index_const,
269 obj_typ,
270 index_typ,
271 IndexSelType::Indexing,
272 )), Some(self.tlookup.get_expr_tc_type(expr)),
274 pos,
275 )
276 }
277 Expr::Selector(sexpr) => {
278 let pos = self.ast_objs.idents[sexpr.sel].pos;
279 match self.tlookup.try_get_pkg_key(&sexpr.expr) {
280 Some(key) => {
281 let pkg = self.pkg_util.get_vm_pkg(key);
282 (
284 LeftHandSide::Primitive(EntIndex::PackageMember(
286 pkg, sexpr.sel,
287 )),
288 Some(self.tlookup.get_expr_tc_type(expr)),
289 pos,
290 )
291 }
292 None => {
293 let t = self.tlookup.get_meta_by_node_id(
294 sexpr.expr.id(),
295 self.objects,
296 self.dummy_gcv,
297 );
298 let name = &self.ast_objs.idents[sexpr.sel].name;
299 let i = t.field_index(name, &self.objects.metas);
300
301 self.visit_expr(&sexpr.expr);
302 let obj_typ = self.tlookup.get_expr_value_type(&sexpr.expr);
303 (
304 LeftHandSide::IndexSelExpr(IndexSelInfo::new(
306 0,
307 Some(i),
308 obj_typ,
309 None,
310 IndexSelType::StructField,
311 )),
312 Some(self.tlookup.get_expr_tc_type(expr)),
313 pos,
314 )
315 }
316 }
317 }
318 Expr::Star(sexpr) => {
319 self.visit_expr(&sexpr.expr);
320 (
321 LeftHandSide::Deref(0), Some(self.tlookup.get_expr_tc_type(expr)),
323 sexpr.star,
324 )
325 }
326 _ => unreachable!(),
327 }
328 })
329 .collect::<Vec<(LeftHandSide, Option<TCTypeKey>, usize)>>();
330
331 match rhs {
332 RightHandSide::Nothing => {
333 let code = match token {
334 Token::INC => Opcode::ADD,
335 Token::DEC => Opcode::SUB,
336 _ => unreachable!(),
337 };
338 let typ = self.tlookup.get_expr_value_type(&lhs_exprs[0]);
339 self.gen_op_assign(&lhs[0].0, (code, None), None, typ, lhs[0].2);
340 None
341 }
342 RightHandSide::Values(rhs_exprs) => {
343 let simple_op = match token {
344 Token::ADD_ASSIGN => Some(Opcode::ADD), Token::SUB_ASSIGN => Some(Opcode::SUB), Token::MUL_ASSIGN => Some(Opcode::MUL), Token::QUO_ASSIGN => Some(Opcode::QUO), Token::REM_ASSIGN => Some(Opcode::REM), Token::AND_ASSIGN => Some(Opcode::AND), Token::OR_ASSIGN => Some(Opcode::OR), Token::XOR_ASSIGN => Some(Opcode::XOR), Token::SHL_ASSIGN => Some(Opcode::SHL), Token::SHR_ASSIGN => Some(Opcode::SHR), Token::AND_NOT_ASSIGN => Some(Opcode::AND_NOT), Token::ASSIGN | Token::DEFINE => None,
356 _ => unreachable!(),
357 };
358 if let Some(code) = simple_op {
359 assert_eq!(lhs_exprs.len(), 1);
360 assert_eq!(rhs_exprs.len(), 1);
361 let ltyp = self.tlookup.get_expr_value_type(&lhs_exprs[0]);
362 let rtyp = match code {
363 Opcode::SHL | Opcode::SHR => {
364 Some(self.tlookup.get_expr_value_type(&rhs_exprs[0]))
365 }
366 _ => None,
367 };
368 self.gen_op_assign(
369 &lhs[0].0,
370 (code, rtyp),
371 Some(&rhs_exprs[0]),
372 ltyp,
373 lhs[0].2,
374 );
375 None
376 } else {
377 self.gen_assign_def_var(&lhs, &None, &rhs)
378 }
379 }
380 _ => self.gen_assign_def_var(&lhs, &None, &rhs),
381 }
382 }
383
384 fn gen_assign_def_var(
385 &mut self,
386 lhs: &Vec<(LeftHandSide, Option<TCTypeKey>, usize)>,
387 typ: &Option<Expr>,
388 rhs: &RightHandSide,
389 ) -> Option<usize> {
390 let mut range_marker = None;
391 let types = match rhs {
393 RightHandSide::Nothing => {
394 let (val, t) = self.get_type_default(&typ.as_ref().unwrap());
396 let mut types = Vec::with_capacity(lhs.len());
397 for (_, _, pos) in lhs.iter() {
398 let mut emitter = current_func_emitter!(self);
399 let i = emitter.add_const(None, val.clone());
400 emitter.emit_load(i, None, self.tlookup.value_type_from_tc(t), Some(*pos));
401 types.push(t);
402 }
403 types
404 }
405 RightHandSide::Values(values) => {
406 let val0 = &values[0];
407 let val0_mode = self.tlookup.get_expr_mode(val0);
408 if values.len() == 1
409 && (val0_mode == &OperandMode::CommaOk || val0_mode == &OperandMode::MapIndex)
410 {
411 let comma_ok = lhs.len() == 2;
412 match val0 {
413 Expr::TypeAssert(tae) => {
414 self.visit_expr(&tae.expr);
415 let t = self.tlookup.get_expr_tc_type(tae.typ.as_ref().unwrap());
416 let meta = self.tlookup.meta_from_tc(t, self.objects, self.dummy_gcv);
417 let func = current_func_mut!(self);
418 let index = func.add_const(None, GosValue::Metadata(meta));
419 func.emit_code_with_flag_imm(
420 Opcode::TYPE_ASSERT,
421 comma_ok,
422 index.into(),
423 Some(tae.l_paren),
424 );
425 }
426 Expr::Index(ie) => {
427 self.gen_map_index(&ie.expr, &ie.index, comma_ok);
428 }
429 Expr::Unary(recv_expr) => {
430 assert_eq!(recv_expr.op, Token::ARROW);
431 self.visit_expr(&recv_expr.expr);
432 let t = self.tlookup.get_expr_value_type(&recv_expr.expr);
433 assert_eq!(t, ValueType::Channel);
434 let comma_ok_flag = comma_ok.then(|| ValueType::FlagA);
435 current_func_mut!(self).emit_code_with_type2(
436 Opcode::RECV,
437 t,
438 comma_ok_flag,
439 Some(recv_expr.op_pos),
440 );
441 }
442 _ => {
443 dbg!(val0, val0_mode);
444 unreachable!()
445 }
446 }
447 if comma_ok {
448 self.tlookup.get_tuple_tc_types(val0)
449 } else {
450 vec![self.tlookup.get_expr_tc_type(val0)]
451 }
452 } else if values.len() == lhs.len() {
453 let mut types = Vec::with_capacity(values.len());
455 for val in values.iter() {
456 self.visit_expr(val);
457 let rhs_type = self.tlookup.get_expr_tc_type(val);
458 types.push(rhs_type);
459 }
460 types
461 } else if values.len() == 1 {
462 let expr = val0;
463 if let Expr::Call(_) = expr {
465 self.visit_expr(expr);
466 } else {
467 unreachable!()
468 }
469 self.tlookup.get_tuple_tc_types(expr)
470 } else {
471 unreachable!();
472 }
473 }
474 RightHandSide::Range(r) => {
475 self.visit_expr(r);
477 let tkv = self.tlookup.get_range_tc_types(r);
478 let types = [
479 Some(self.tlookup.value_type_from_tc(tkv[0])),
480 Some(self.tlookup.value_type_from_tc(tkv[1])),
481 Some(self.tlookup.value_type_from_tc(tkv[2])),
482 ];
483 let pos = Some(r.pos(&self.ast_objs));
484 let func = current_func_mut!(self);
486 func.emit_inst(Opcode::RANGE_INIT, types, None, pos);
487 range_marker = Some(func.next_code_index());
488 func.emit_inst(Opcode::RANGE, types, None, pos);
490 tkv[1..].to_vec()
491 }
492 RightHandSide::SelectRecv(rhs) => {
493 let comma_ok =
494 lhs.len() == 2 && self.tlookup.get_expr_mode(rhs) == &OperandMode::CommaOk;
495 if comma_ok {
496 self.tlookup.get_tuple_tc_types(rhs)
497 } else {
498 vec![self.tlookup.get_expr_tc_type(rhs)]
499 }
500 }
501 };
502
503 let total_lhs_stack_space = lhs.iter().fold(0, |acc, (x, _, _)| match x {
505 LeftHandSide::Primitive(_) => acc,
506 LeftHandSide::IndexSelExpr(info) => acc + info.stack_space(),
507 LeftHandSide::Deref(_) => acc + 1,
508 });
509 let lhs_on_stack_top = if let RightHandSide::SelectRecv(_) = rhs {
511 true
512 } else {
513 false
514 };
515
516 assert_eq!(lhs.len(), types.len());
517 let total_val = types.len() as OpIndex;
518 let total_stack_space = (total_lhs_stack_space + total_val) as OpIndex;
519 let mut current_indexing_deref_index = -if lhs_on_stack_top {
520 total_lhs_stack_space
521 } else {
522 total_stack_space
523 };
524 for (i, (l, _, p)) in lhs.iter().enumerate() {
525 let rhs_index = i as OpIndex
526 - if lhs_on_stack_top {
527 total_stack_space
528 } else {
529 total_val
530 };
531 let typ = self.try_cast_to_iface(lhs[i].1, Some(types[i]), rhs_index, *p);
532 let pos = Some(*p);
533 match l {
534 LeftHandSide::Primitive(_) => {
535 current_func_emitter!(self).emit_store(l, rhs_index, None, None, typ, pos);
536 }
537 LeftHandSide::IndexSelExpr(info) => {
538 current_func_emitter!(self).emit_store(
539 &LeftHandSide::IndexSelExpr(info.with_index(current_indexing_deref_index)),
540 rhs_index,
541 None,
542 None,
543 typ,
544 pos,
545 );
546 current_indexing_deref_index += 2;
548 }
549 LeftHandSide::Deref(_) => {
550 current_func_emitter!(self).emit_store(
551 &LeftHandSide::Deref(current_indexing_deref_index),
552 rhs_index,
553 None,
554 None,
555 typ,
556 pos,
557 );
558 current_indexing_deref_index += 1;
559 }
560 }
561 }
562
563 let mut total_pop = types.iter().count() as OpIndex;
565 for (i, _, _) in lhs.iter().rev() {
567 match i {
568 LeftHandSide::Primitive(_) => {}
569 LeftHandSide::IndexSelExpr(info) => {
570 if let Some(_t) = info.t2 {
571 total_pop += 1;
572 }
573 total_pop += 1;
574 }
575 LeftHandSide::Deref(_) => total_pop += 1,
576 }
577 }
578 let pos = Some(lhs[0].2);
579 current_func_emitter!(self).emit_pop(total_pop, pos);
580 range_marker
581 }
582
583 fn gen_op_assign(
584 &mut self,
585 left: &LeftHandSide,
586 op: (Opcode, Option<ValueType>),
587 right: Option<&Expr>,
588 typ: ValueType,
589 p: usize,
590 ) {
591 let pos = Some(p);
592 if let Some(e) = right {
593 self.visit_expr(e);
594 } else {
595 current_func_emitter!(self).emit_push_imm(typ, 1, pos);
597 }
598 match left {
599 LeftHandSide::Primitive(_) => {
600 let mut emitter = current_func_emitter!(self);
603 let fkey = self.func_stack.last().unwrap();
604 emitter.emit_store(
605 left,
606 -1,
607 Some(op),
608 Some((self.pkg_util.pairs_mut(), *fkey)),
609 typ,
610 pos,
611 );
612 emitter.emit_pop(1, pos);
613 }
614 LeftHandSide::IndexSelExpr(info) => {
615 current_func_emitter!(self).emit_store(
618 &LeftHandSide::IndexSelExpr(info.with_index(-info.stack_space() - 1)),
619 -1,
620 Some(op),
621 None,
622 typ,
623 pos,
624 );
625 let mut total_pop = 2;
626 if let Some(_) = info.t2 {
627 total_pop += 1;
628 }
629 current_func_emitter!(self).emit_pop(total_pop, pos);
630 }
631 LeftHandSide::Deref(_) => {
632 let mut emitter = current_func_emitter!(self);
635 emitter.emit_store(&LeftHandSide::Deref(-2), -1, Some(op), None, typ, pos);
636 emitter.emit_pop(2, pos);
637 }
638 }
639 }
640
641 fn gen_switch_body(&mut self, body: &BlockStmt, tag_type: ValueType) {
642 let mut helper = SwitchHelper::new();
643 let mut has_default = false;
644 for (i, stmt) in body.list.iter().enumerate() {
645 helper.add_case_clause();
646 let cc = SwitchHelper::to_case_clause(stmt);
647 match &cc.list {
648 Some(l) => {
649 for c in l.iter() {
650 let pos = Some(stmt.pos(&self.ast_objs));
651 self.visit_expr(c);
652 let func = current_func_mut!(self);
653 helper.tags.add_case(i, func.next_code_index());
654 func.emit_code_with_type(Opcode::SWITCH, tag_type, pos);
655 }
656 }
657 None => has_default = true,
658 }
659 }
660 if has_default {
661 let func = current_func_mut!(self);
662 helper.tags.add_default(func.next_code_index());
663 func.emit_code(Opcode::JUMP, None);
664 }
665
666 for (i, stmt) in body.list.iter().enumerate() {
667 let cc = SwitchHelper::to_case_clause(stmt);
668 let func = current_func_mut!(self);
669 let default = cc.list.is_none();
670 if default {
671 helper.tags.patch_default(func, func.next_code_index());
672 } else {
673 helper.tags.patch_case(func, i, func.next_code_index());
674 }
675 for s in cc.body.iter() {
676 self.visit_stmt(s);
677 }
678 if !SwitchHelper::has_fall_through(stmt) {
679 let func = current_func_mut!(self);
680 if default {
681 helper.ends.add_default(func.next_code_index());
682 } else {
683 helper.ends.add_case(i, func.next_code_index());
684 }
685 func.emit_code(Opcode::JUMP, None);
686 }
687 }
688 let end = current_func!(self).next_code_index();
689 helper.patch_ends(current_func_mut!(self), end);
690
691 current_func_emitter!(self).emit_pop(1, None);
693 }
694
695 fn gen_func_def(
696 &mut self,
697 tc_type: TCTypeKey, fkey: FuncTypeKey,
699 recv: Option<FieldList>,
700 body: &BlockStmt,
701 ) -> FunctionKey {
702 let typ = &self.ast_objs.ftypes[fkey];
703 let fmeta = self
704 .tlookup
705 .meta_from_tc(tc_type, &mut self.objects, self.dummy_gcv);
706 let f = GosValue::new_function(
707 self.pkg_key,
708 fmeta,
709 self.objects,
710 self.dummy_gcv,
711 FuncFlag::Default,
712 );
713 let fkey = *f.as_function();
714 let mut emitter = Emitter::new(&mut self.objects.functions[fkey]);
715 if let Some(fl) = &typ.results {
716 emitter.add_params(&fl, self.ast_objs);
717 }
718 match recv {
719 Some(recv) => {
720 let mut fields = recv;
721 fields.list.append(&mut typ.params.list.clone());
722 emitter.add_params(&fields, self.ast_objs)
723 }
724 None => emitter.add_params(&typ.params, self.ast_objs),
725 };
726 self.func_stack.push(fkey);
727 self.func_t_stack.push(tc_type);
728 self.visit_stmt_block(body);
730 Emitter::new(&mut self.objects.functions[fkey]).emit_return(None, Some(body.r_brace));
732
733 self.func_stack.pop();
734 self.func_t_stack.pop();
735 fkey
736 }
737
738 fn gen_call(&mut self, func_expr: &Expr, params: &Vec<Expr>, ellipsis: bool, style: CallStyle) {
739 let pos = Some(func_expr.pos(&self.ast_objs));
740 match *self.tlookup.get_expr_mode(func_expr) {
741 OperandMode::Builtin(builtin) => {
743 let opcode = match builtin {
744 Builtin::New => Opcode::NEW,
745 Builtin::Make => Opcode::MAKE,
746 Builtin::Len => Opcode::LEN,
747 Builtin::Cap => Opcode::CAP,
748 Builtin::Append => Opcode::APPEND,
749 Builtin::Close => Opcode::CLOSE,
750 Builtin::Panic => Opcode::PANIC,
751 Builtin::Recover => Opcode::RECOVER,
752 Builtin::Assert => Opcode::ASSERT,
753 Builtin::Ffi => Opcode::FFI,
754 _ => unimplemented!(),
755 };
756 for e in params.iter() {
757 self.visit_expr(e);
758 }
759 if let Some(t) = self.tlookup.try_get_expr_tc_type(func_expr) {
761 self.try_cast_params_to_iface(t, params, ellipsis);
762 if opcode == Opcode::FFI {
763 let meta = self.tlookup.meta_from_tc(t, self.objects, self.dummy_gcv);
765 let mut emitter = current_func_emitter!(self);
766 let i = emitter.add_const(None, GosValue::Metadata(meta));
767 emitter.emit_load(i, None, ValueType::Metadata, pos);
768 }
769 }
770 let (param0t, param_last_t) = if params.len() > 0 {
771 (
772 Some(self.tlookup.get_expr_value_type(¶ms[0])),
773 Some(self.tlookup.get_expr_value_type(params.last().unwrap())),
774 )
775 } else {
776 (None, None)
777 };
778 let bf = self.tc_objs.universe().builtins()[&builtin];
779 let param_count = params.len() as OpIndex;
780 let (t_variadic, count) = if bf.variadic {
781 if ellipsis {
782 (None, Some(0)) } else {
784 (param_last_t, Some(bf.arg_count as OpIndex - param_count))
785 }
786 } else {
787 (None, Some(param_count as OpIndex))
788 };
789 let func = current_func_mut!(self);
790 func.emit_inst(opcode, [param0t, t_variadic, None], count, pos);
791 }
792 OperandMode::TypeExpr => {
812 assert!(params.len() == 1);
813 self.visit_expr(¶ms[0]);
814 let tct0 = self.tlookup.get_expr_tc_type(func_expr);
815 let utct0 = self.tlookup.underlying_tc(tct0);
816 let t0 = self.tlookup.value_type_from_tc(utct0);
817 let tct1 = self.tlookup.get_expr_tc_type(¶ms[0]);
818 let utct1 = self.tlookup.underlying_tc(tct1);
819 let t1 = self.tlookup.value_type_from_tc(utct1);
820 if t1 != ValueType::Nil && !identical(utct0, utct1, self.tc_objs) {
822 let iface_index = match t0 {
823 ValueType::Interface => {
824 if t1 != ValueType::Nil {
825 self.iface_mapping.get_index(
826 &(tct0, Some(tct1)),
827 &mut self.tlookup,
828 self.objects,
829 self.dummy_gcv,
830 )
831 } else {
832 0
833 }
834 }
835 _ => 0,
836 };
837 let tct2 = if t0 == ValueType::Slice {
839 Some(utct0)
840 } else if t1 == ValueType::Slice {
841 Some(utct1)
842 } else {
843 None
844 };
845 let t2 = tct2.map(|x| {
846 self.tlookup.value_type_from_tc(
847 self.tc_objs.types[x].try_as_slice().unwrap().elem(),
848 )
849 });
850 current_func_emitter!(self).emit_cast(t0, t1, t2, -1, iface_index, pos);
851 }
852 }
853 _ => {
855 self.visit_expr(func_expr);
856 current_func_emitter!(self).emit_pre_call(pos);
857 let _ = params.iter().map(|e| self.visit_expr(e)).count();
858 let t = self.tlookup.get_expr_tc_type(func_expr);
859 self.try_cast_params_to_iface(t, params, ellipsis);
860
861 let ftc = self
863 .tlookup
864 .underlying_tc(self.tlookup.get_expr_tc_type(func_expr));
865 let func_detail = self.tc_objs.types[ftc].try_as_signature().unwrap();
866 let variadic = func_detail.variadic();
867 let pack = variadic && !ellipsis;
868 current_func_emitter!(self).emit_call(style, pack, pos);
869 }
870 }
871 }
872
873 fn gen_map_index(&mut self, expr: &Expr, index: &Expr, comma_ok: bool) {
874 let t0 = self.tlookup.get_expr_value_type(expr);
875 let t1 = self.tlookup.get_expr_value_type(index);
876 self.visit_expr(expr);
877 let pos = Some(expr.pos(&self.ast_objs));
878 if let Some(const_val) = self.tlookup.get_tc_const_value(index.id()) {
879 let (ival, _) = const_val.to_int().int_as_i64();
880 if let Ok(i) = OpIndex::try_from(ival) {
881 current_func_emitter!(self).emit_load_index_imm(i, t0, comma_ok, pos);
882 return;
883 }
884 }
885 self.visit_expr(index);
886 current_func_emitter!(self).emit_load_index(t0, t1, comma_ok, pos);
887 }
888
889 fn try_cast_to_iface(
890 &mut self,
891 lhs: Option<TCTypeKey>,
892 rhs: Option<TCTypeKey>,
893 rhs_index: OpIndex,
894 pos: usize,
895 ) -> ValueType {
896 let mut ret_type = None;
897 if let Some(t0) = lhs {
898 if self.tlookup.underlying_value_type_from_tc(t0) == ValueType::Interface {
899 let (cast, typ) = match rhs {
900 Some(t1) => {
901 let vt1 = self.tlookup.underlying_value_type_from_tc(t1);
902 (vt1 != ValueType::Interface && vt1 != ValueType::Nil, vt1)
903 }
904 None => (true, ValueType::Slice), };
906 if cast {
907 let index = self.iface_mapping.get_index(
908 &(t0, rhs),
909 &mut self.tlookup,
910 self.objects,
911 self.dummy_gcv,
912 );
913 current_func_emitter!(self).emit_cast(
914 ValueType::Interface,
915 typ,
916 None,
917 rhs_index,
918 index,
919 Some(pos),
920 );
921 ret_type = Some(ValueType::Interface);
922 }
923 }
924 }
925 ret_type.unwrap_or(self.tlookup.value_type_from_tc(rhs.unwrap()))
926 }
927
928 fn try_cast_params_to_iface(&mut self, func: TCTypeKey, params: &Vec<Expr>, ellipsis: bool) {
929 let (sig_params, variadic) = self.tlookup.get_sig_params_tc_types(func);
930 let non_variadic_params = variadic.map_or(sig_params.len(), |_| sig_params.len() - 1);
931 for (i, v) in sig_params[..non_variadic_params].iter().enumerate() {
932 let rhs_index = i as OpIndex - params.len() as OpIndex;
933 let rhs = if i == params.len() - 1 && ellipsis {
934 None
935 } else {
936 Some(self.tlookup.get_expr_tc_type(¶ms[i]))
937 };
938 let pos = params[i].pos(&self.ast_objs);
939 self.try_cast_to_iface(Some(*v), rhs, rhs_index, pos);
940 }
941 if !ellipsis {
942 if let Some((_, t)) = variadic {
943 if self.tlookup.underlying_value_type_from_tc(t) == ValueType::Interface {
944 for (i, p) in params.iter().enumerate().skip(non_variadic_params) {
945 let rhs_index = i as OpIndex - params.len() as OpIndex;
946 let rhs = self.tlookup.get_expr_tc_type(p);
947 let pos = p.pos(&self.ast_objs);
948 self.try_cast_to_iface(Some(t), Some(rhs), rhs_index, pos);
949 }
950 }
951 }
952 }
953 }
954
955 fn get_type_default(&mut self, expr: &Expr) -> (GosValue, TCTypeKey) {
956 let t = self.tlookup.get_expr_tc_type(expr);
957 let meta = self.tlookup.meta_from_tc(t, self.objects, self.dummy_gcv);
958 let zero_val = zero_val!(meta, self.objects, self.dummy_gcv);
959 (zero_val, t)
960 }
961
962 fn visit_composite_expr(&mut self, expr: &Expr, tctype: TCTypeKey) {
963 match expr {
964 Expr::CompositeLit(clit) => self.gen_composite_literal(clit, tctype),
965 _ => self.visit_expr(expr),
966 }
967 let t = self.tlookup.get_expr_tc_type(expr);
968 self.try_cast_to_iface(Some(tctype), Some(t), -1, expr.pos(self.ast_objs));
969 }
970
971 fn gen_composite_literal(&mut self, clit: &CompositeLit, tctype: TCTypeKey) {
972 let meta = self
973 .tlookup
974 .meta_from_tc(tctype, &mut self.objects, self.dummy_gcv);
975 let pos = Some(clit.l_brace);
976 let typ = &self.tc_objs.types[tctype].underlying_val(&self.tc_objs);
977 let (mkey, mc) = meta.get_underlying(&self.objects.metas).unwrap_non_ptr();
978 let mtype = &self.objects.metas[mkey].clone();
979 match mtype {
980 MetadataType::SliceOrArray(_, _) => {
981 let elem = match mc {
982 MetaCategory::Default => typ.try_as_slice().unwrap().elem(),
983 MetaCategory::Array => typ.try_as_array().unwrap().elem(),
984 _ => unreachable!(),
985 };
986 for expr in clit.elts.iter().rev() {
987 match expr {
988 Expr::KeyValue(kv) => {
989 self.visit_composite_expr(&kv.val, elem);
990 self.visit_expr(&kv.key);
992 }
993 _ => {
994 self.visit_composite_expr(expr, elem);
995 current_func_emitter!(self).emit_push_imm(ValueType::Int, -1, None);
997 }
998 };
999 }
1000 }
1001 MetadataType::Map(_, _) => {
1002 let map_type = typ.try_as_map().unwrap();
1003 for expr in clit.elts.iter() {
1004 match expr {
1005 Expr::KeyValue(kv) => {
1006 self.visit_composite_expr(&kv.val, map_type.elem());
1007 self.visit_composite_expr(&kv.key, map_type.key());
1008 }
1009 _ => unreachable!(),
1010 }
1011 }
1012 }
1013 MetadataType::Struct(f, _) => {
1014 let struct_type = typ.try_as_struct().unwrap();
1015 for (i, expr) in clit.elts.iter().enumerate() {
1016 let field_type = self.tc_objs.lobjs[struct_type.fields()[i]].typ().unwrap();
1017 let index = match expr {
1018 Expr::KeyValue(kv) => {
1019 self.visit_composite_expr(&kv.val, field_type);
1020 let ident = kv.key.try_as_ident().unwrap();
1021 f.mapping[&self.ast_objs.idents[*ident].name]
1022 }
1023 _ => {
1024 self.visit_composite_expr(expr, field_type);
1025 i as OpIndex
1026 }
1027 };
1028 current_func_emitter!(self).emit_push_imm(ValueType::Uint, index, pos);
1029 }
1030 }
1031 _ => {
1032 dbg!(&mtype);
1033 unreachable!()
1034 }
1035 }
1036 current_func_emitter!(self).emit_push_imm(
1037 ValueType::Int32,
1038 clit.elts.len() as OpIndex,
1039 pos,
1040 );
1041
1042 let mut emitter = current_func_emitter!(self);
1043 let i = emitter.add_const(None, GosValue::Metadata(meta));
1044 emitter.emit_literal(ValueType::Metadata, i.into(), pos);
1045 }
1046
1047 fn gen_type_meta(&mut self, typ: &Expr) {
1048 let m = self
1049 .tlookup
1050 .get_meta_by_node_id(typ.id(), self.objects, self.dummy_gcv);
1051 let mut emitter = current_func_emitter!(self);
1052 let i = emitter.add_const(None, GosValue::Metadata(m));
1053 let pos = Some(typ.pos(&self.ast_objs));
1054 emitter.emit_load(i, None, ValueType::Metadata, pos);
1055 }
1056
1057 fn gen_const(&mut self, node: NodeId, pos: Option<Pos>) {
1058 let val = self.tlookup.get_const_value(node);
1059 let mut emitter = current_func_emitter!(self);
1060 let t = val.get_type();
1061 let i = emitter.add_const(None, val);
1062 emitter.emit_load(i, None, t, pos);
1063 }
1064
1065 fn current_func_add_const_def(&mut self, ident: &Ident, cst: GosValue) -> EntIndex {
1066 let func = current_func_mut!(self);
1067 let entity = ident.entity.clone().into_key().unwrap();
1068 let index = func.add_const(Some(entity), cst.clone());
1069 if func.is_ctor() {
1070 let pkg_key = func.package;
1071 drop(func);
1072 let pkg = &mut self.objects.packages[pkg_key];
1073 pkg.add_member(ident.name.clone(), cst);
1074 }
1075 index
1076 }
1077
1078 fn add_pkg_var_member(&mut self, pkey: PackageKey, vars: &Vec<Rc<ValueSpec>>) {
1079 for v in vars.iter() {
1080 for n in v.names.iter() {
1081 let ident = &self.ast_objs.idents[*n];
1082 let meta = self
1083 .tlookup
1084 .gen_def_type_meta(*n, self.objects, self.dummy_gcv);
1085 let val = zero_val!(meta, self.objects, self.dummy_gcv);
1086 self.objects.packages[pkey].add_member(ident.name.clone(), val);
1087 }
1088 }
1089 }
1090
1091 pub fn gen_with_files(&mut self, files: &Vec<File>, tcpkg: TCPackageKey, index: OpIndex) {
1092 let pkey = self.pkg_key;
1093 let fmeta = self.objects.metadata.default_sig;
1094 let f =
1095 GosValue::new_function(pkey, fmeta, self.objects, self.dummy_gcv, FuncFlag::PkgCtor);
1096 let fkey = *f.as_function();
1097 self.objects.packages[pkey].add_member(
1099 String::new(),
1100 GosValue::new_closure(fkey, &self.objects.functions),
1101 );
1102 self.pkg_key = pkey;
1103 self.func_stack.push(fkey);
1104
1105 let vars = self
1106 .pkg_util
1107 .sort_var_decls(files, self.tlookup.type_info());
1108 self.add_pkg_var_member(pkey, &vars);
1109
1110 self.pkg_util.gen_imports(tcpkg, current_func_mut!(self));
1111
1112 for f in files.iter() {
1113 for d in f.decls.iter() {
1114 self.visit_decl(d)
1115 }
1116 }
1117 for v in vars.iter() {
1118 self.gen_def_var(v);
1119 }
1120
1121 let mut emitter = Emitter::new(&mut self.objects.functions[fkey]);
1122 emitter.emit_return(Some(index), None);
1123 self.func_stack.pop();
1124 }
1125}
1126
1127impl<'a> ExprVisitor for CodeGen<'a> {
1128 type Result = ();
1129
1130 fn visit_expr(&mut self, expr: &Expr) {
1131 if let Some(mode) = self.tlookup.try_get_expr_mode(expr) {
1132 if let OperandMode::Constant(_) = mode {
1133 self.gen_const(expr.id(), Some(expr.pos(&self.ast_objs)));
1134 return;
1135 }
1136 }
1137 walk_expr(self, expr);
1138 }
1139
1140 fn visit_expr_ident(&mut self, expr: &Expr, ident: &IdentKey) {
1141 let index = self.resolve_any_ident(ident, Some(expr));
1142 let t = self.tlookup.get_use_value_type(*ident);
1143 let fkey = self.func_stack.last().unwrap();
1144 let p = Some(self.ast_objs.idents[*ident].pos);
1145 current_func_emitter!(self).emit_load(
1146 index,
1147 Some((self.pkg_util.pairs_mut(), *fkey)),
1148 t,
1149 p,
1150 );
1151 }
1152
1153 fn visit_expr_ellipsis(&mut self, _: &Expr, _els: &Option<Expr>) {
1154 unreachable!();
1155 }
1156
1157 fn visit_expr_basic_lit(&mut self, this: &Expr, blit: &BasicLit) {
1158 self.gen_const(this.id(), Some(blit.pos));
1159 }
1160
1161 fn visit_expr_func_lit(&mut self, this: &Expr, flit: &FuncLit) {
1163 let tc_type = self.tlookup.get_node_tc_type(this.id());
1164 let fkey = self.gen_func_def(tc_type, flit.typ, None, &flit.body);
1165 let mut emitter = current_func_emitter!(self);
1166 let i = emitter.add_const(None, GosValue::Function(fkey));
1167 let pos = Some(flit.body.l_brace);
1168 emitter.emit_literal(ValueType::Function, i.into(), pos);
1169 }
1170
1171 fn visit_expr_composit_lit(&mut self, _: &Expr, clit: &CompositeLit) {
1172 let tctype = self.tlookup.get_expr_tc_type(clit.typ.as_ref().unwrap());
1173 self.gen_composite_literal(clit, tctype);
1174 }
1175
1176 fn visit_expr_paren(&mut self, _: &Expr, expr: &Expr) {
1177 self.visit_expr(expr)
1178 }
1179
1180 fn visit_expr_selector(&mut self, this: &Expr, expr: &Expr, ident: &IdentKey) {
1181 let pos = Some(expr.pos(&self.ast_objs));
1182 if let Some(key) = self.tlookup.try_get_pkg_key(expr) {
1183 let pkg = self.pkg_util.get_vm_pkg(key);
1184 let t = self.tlookup.get_use_value_type(*ident);
1185 let fkey = self.func_stack.last().unwrap();
1186 current_func_emitter!(self).emit_load(
1187 EntIndex::PackageMember(pkg, *ident),
1188 Some((self.pkg_util.pairs_mut(), *fkey)),
1189 t,
1190 pos,
1191 );
1192 return;
1193 }
1194
1195 let (t0, t1) = self.tlookup.get_selection_value_types(this.id());
1196 let meta = self
1197 .tlookup
1198 .get_meta_by_node_id(expr.id(), self.objects, self.dummy_gcv);
1199 let name = &self.ast_objs.idents[*ident].name;
1200 if t1 == ValueType::Closure {
1201 if meta
1202 .get_underlying(&self.objects.metas)
1203 .get_value_type(&self.objects.metas)
1204 == ValueType::Interface
1205 {
1206 let i = meta.iface_method_index(name, &self.objects.metas);
1207 self.visit_expr(expr);
1208 current_func_mut!(self).emit_code_with_type_imm(
1209 Opcode::BIND_INTERFACE_METHOD,
1210 meta.get_value_type(&self.objects.metas),
1211 i,
1212 pos,
1213 );
1214 } else {
1215 let i = meta.method_index(name, &self.objects.metas);
1216 let method = meta.get_method(i, &self.objects.metas);
1217 if method.borrow().pointer_recv {
1218 self.visit_expr_unary(this, expr, &Token::AND);
1220 } else {
1221 self.visit_expr(expr);
1222 }
1223 let func = current_func_mut!(self);
1224 let mi = func.add_const(None, GosValue::Function(method.borrow().func.unwrap()));
1226 func.emit_code_with_type_imm(Opcode::BIND_METHOD, t0, mi.into(), pos);
1227 }
1228 } else {
1229 self.visit_expr(expr);
1230 let i = meta.field_index(name, &self.objects.metas);
1231 current_func_emitter!(self).emit_load_struct_field(i, t0, pos);
1232 }
1233 }
1234
1235 fn visit_expr_index(&mut self, _: &Expr, expr: &Expr, index: &Expr) {
1236 self.gen_map_index(expr, index, false);
1237 }
1238
1239 fn visit_expr_slice(
1240 &mut self,
1241 _: &Expr,
1242 expr: &Expr,
1243 low: &Option<Expr>,
1244 high: &Option<Expr>,
1245 max: &Option<Expr>,
1246 ) -> Self::Result {
1247 self.visit_expr(expr);
1248 let t = self.tlookup.get_expr_value_type(expr);
1249 let pos = Some(expr.pos(&self.ast_objs));
1250 match low {
1251 None => current_func_emitter!(self).emit_push_imm(ValueType::Int, 0, pos),
1252 Some(e) => self.visit_expr(e),
1253 }
1254 match high {
1255 None => current_func_emitter!(self).emit_push_imm(ValueType::Int, -1, pos),
1256 Some(e) => self.visit_expr(e),
1257 }
1258 match max {
1259 None => current_func_mut!(self).emit_code_with_type(Opcode::SLICE, t, pos),
1260 Some(e) => {
1261 self.visit_expr(e);
1262 current_func_mut!(self).emit_code_with_type(Opcode::SLICE_FULL, t, pos);
1263 }
1264 }
1265 }
1266
1267 fn visit_expr_type_assert(&mut self, _: &Expr, _expr: &Expr, _typ: &Option<Expr>) {
1268 unimplemented!();
1269 }
1270
1271 fn visit_expr_call(&mut self, _: &Expr, func_expr: &Expr, params: &Vec<Expr>, ellipsis: bool) {
1272 self.gen_call(func_expr, params, ellipsis, CallStyle::Default);
1273 }
1274
1275 fn visit_expr_star(&mut self, _: &Expr, expr: &Expr) {
1276 let pos = Some(expr.pos(&self.ast_objs));
1277 match self.tlookup.get_expr_mode(expr) {
1278 OperandMode::TypeExpr => {
1279 let m = self
1280 .tlookup
1281 .meta_from_tc(
1282 self.tlookup.get_expr_tc_type(expr),
1283 self.objects,
1284 self.dummy_gcv,
1285 )
1286 .ptr_to();
1287 let mut emitter = current_func_emitter!(self);
1288 let index = emitter.add_const(None, GosValue::Metadata(m));
1289 emitter.emit_load(index, None, ValueType::Metadata, pos);
1290 }
1291 _ => {
1292 self.visit_expr(expr);
1293 let t = self.tlookup.get_expr_value_type(expr);
1294 current_func_mut!(self).emit_code_with_type(Opcode::DEREF, t, pos);
1295 }
1296 }
1297 }
1298
1299 fn visit_expr_unary(&mut self, this: &Expr, expr: &Expr, op: &Token) {
1300 let pos = Some(expr.pos(&self.ast_objs));
1301 if op == &Token::AND {
1302 match expr {
1303 Expr::Ident(ikey) => {
1304 let index = self.resolve_any_ident(ikey, None);
1305 match index {
1306 EntIndex::LocalVar(i) => {
1307 let meta = self.tlookup.get_meta_by_node_id(
1308 expr.id(),
1309 self.objects,
1310 self.dummy_gcv,
1311 );
1312 let t = meta.get_value_type(&self.objects.metas);
1313 let ut = meta
1314 .get_underlying(&self.objects.metas)
1315 .get_value_type(&self.objects.metas);
1316 if ut == ValueType::Struct
1317 || ut == ValueType::Array
1318 || ut == ValueType::Slice
1319 || ut == ValueType::Map
1320 {
1321 let func = current_func_mut!(self);
1322 func.emit_inst(
1323 Opcode::REF_LOCAL,
1324 [Some(t), None, None],
1325 Some(i),
1326 pos,
1327 );
1328 } else {
1329 let ident = &self.ast_objs.idents[*ikey];
1330 let entity_key = ident.entity_key().unwrap();
1331 let func = current_func_mut!(self);
1332 let ind = *func.entity_index(&entity_key).unwrap();
1333 let desc = ValueDesc::new(
1334 *self.func_stack.last().unwrap(),
1335 ind.into(),
1336 t,
1337 false,
1338 );
1339 let index = func.try_add_upvalue(&entity_key, desc);
1340 func.emit_inst(
1341 Opcode::REF_UPVALUE,
1342 [Some(t), None, None],
1343 Some(index.into()),
1344 pos,
1345 );
1346 }
1347 }
1348 EntIndex::UpValue(i) => {
1349 let t = self.tlookup.get_expr_value_type(expr);
1350 let func = current_func_mut!(self);
1351 func.emit_inst(
1352 Opcode::REF_UPVALUE,
1353 [Some(t), None, None],
1354 Some(i),
1355 pos,
1356 );
1357 }
1358 EntIndex::PackageMember(pkg, ident) => {
1359 let func = current_func_mut!(self);
1360 func.emit_inst(
1361 Opcode::REF_PKG_MEMBER,
1362 [None, None, None],
1363 Some(0),
1364 pos,
1365 );
1366 func.emit_raw_inst(key_to_u64(self.pkg_key), pos);
1367 let fkey = self.func_stack.last().unwrap();
1368 let i = current_func!(self).next_code_index() - 2;
1369 self.pkg_util.add_pair(pkg, ident, *fkey, i, false);
1370 }
1371 _ => unreachable!(),
1372 }
1373 }
1374 Expr::Index(iexpr) => {
1375 let t0 = self.tlookup.get_expr_value_type(&iexpr.expr);
1376 let t1 = self.tlookup.get_expr_value_type(&iexpr.index);
1377 self.visit_expr(&iexpr.expr);
1378 self.visit_expr(&iexpr.index);
1379 let pos = Some(iexpr.index.pos(&self.ast_objs));
1380 current_func_mut!(self).emit_inst(
1381 Opcode::REF_SLICE_MEMBER,
1382 [Some(t0), Some(t1), None],
1383 None,
1384 pos,
1385 );
1386 }
1387 Expr::Selector(sexpr) => match self.tlookup.try_get_pkg_key(&sexpr.expr) {
1388 Some(key) => {
1389 let pkey = self.pkg_util.get_vm_pkg(key);
1390 let func = current_func_mut!(self);
1391 func.emit_inst(Opcode::REF_PKG_MEMBER, [None, None, None], Some(0), pos);
1392 func.emit_raw_inst(key_to_u64(pkey), pos);
1393 let fkey = self.func_stack.last().unwrap();
1394 let i = current_func!(self).next_code_index() - 2;
1395 self.pkg_util.add_pair(pkey, sexpr.sel, *fkey, i, false);
1396 }
1397 None => {
1398 self.visit_expr(&sexpr.expr);
1399 let t0 = self.tlookup.get_meta_by_node_id(
1400 sexpr.expr.id(),
1401 &mut self.objects,
1402 self.dummy_gcv,
1403 );
1404 let name = &self.ast_objs.idents[sexpr.sel].name;
1405 let i = t0.field_index(name, &self.objects.metas);
1406 current_func_mut!(self).emit_code_with_type_imm(
1407 Opcode::REF_STRUCT_FIELD,
1408 t0.get_value_type(&self.objects.metas),
1409 i,
1410 pos,
1411 );
1412 }
1413 },
1414 Expr::CompositeLit(clit) => {
1415 self.visit_expr_composit_lit(this, clit);
1416 let typ = self.tlookup.get_expr_value_type(expr);
1417 current_func_mut!(self).emit_inst(
1418 Opcode::REF_LOCAL,
1419 [Some(typ), None, None],
1420 Some(-1),
1421 pos,
1422 );
1423 }
1424 _ => {
1425 dbg!(&expr);
1426 unimplemented!()
1427 }
1428 }
1429 return;
1430 }
1431
1432 self.visit_expr(expr);
1433 let code = match op {
1434 Token::ADD => Opcode::UNARY_ADD,
1435 Token::SUB => Opcode::UNARY_SUB,
1436 Token::XOR => Opcode::UNARY_XOR,
1437 Token::NOT => Opcode::NOT,
1438 Token::ARROW => Opcode::RECV,
1439 _ => {
1440 dbg!(op);
1441 unreachable!()
1442 }
1443 };
1444 let t = self.tlookup.get_expr_value_type(expr);
1445 current_func_mut!(self).emit_code_with_type(code, t, pos);
1446 }
1447
1448 fn visit_expr_binary(&mut self, _: &Expr, left: &Expr, op: &Token, right: &Expr) {
1449 self.visit_expr(left);
1450 let t = self.tlookup.get_expr_value_type(left);
1451 let code = match op {
1452 Token::ADD => Opcode::ADD,
1453 Token::SUB => Opcode::SUB,
1454 Token::MUL => Opcode::MUL,
1455 Token::QUO => Opcode::QUO,
1456 Token::REM => Opcode::REM,
1457 Token::AND => Opcode::AND,
1458 Token::OR => Opcode::OR,
1459 Token::XOR => Opcode::XOR,
1460 Token::SHL => Opcode::SHL,
1461 Token::SHR => Opcode::SHR,
1462 Token::AND_NOT => Opcode::AND_NOT,
1463 Token::LAND => Opcode::PUSH_FALSE,
1464 Token::LOR => Opcode::PUSH_TRUE,
1465 Token::NOT => Opcode::NOT,
1466 Token::EQL => Opcode::EQL,
1467 Token::LSS => Opcode::LSS,
1468 Token::GTR => Opcode::GTR,
1469 Token::NEQ => Opcode::NEQ,
1470 Token::LEQ => Opcode::LEQ,
1471 Token::GEQ => Opcode::GEQ,
1472 _ => unreachable!(),
1473 };
1474 let pos = Some(left.pos(&self.ast_objs));
1475 let mark_code = match op {
1477 Token::LAND => {
1478 let func = current_func_mut!(self);
1479 func.emit_code(Opcode::JUMP_IF_NOT, pos);
1480 Some((func.next_code_index(), code))
1481 }
1482 Token::LOR => {
1483 let func = current_func_mut!(self);
1484 func.emit_code(Opcode::JUMP_IF, pos);
1485 Some((func.next_code_index(), code))
1486 }
1487 _ => None,
1488 };
1489 self.visit_expr(right);
1490
1491 if let Some((i, c)) = mark_code {
1492 let func = current_func_mut!(self);
1493 func.emit_code_with_imm(Opcode::JUMP, 1, pos);
1494 func.emit_code_with_type(c, t, pos);
1495 let diff = func.next_code_index() - i - 1;
1496 func.instruction_mut(i - 1).set_imm(diff as OpIndex);
1497 } else {
1498 let t1 = if code == Opcode::SHL || code == Opcode::SHR {
1499 Some(self.tlookup.get_expr_value_type(right))
1500 } else {
1501 None
1502 };
1503 current_func_mut!(self).emit_code_with_type2(code, t, t1, pos);
1504 }
1505 }
1506
1507 fn visit_expr_key_value(&mut self, e: &Expr, _key: &Expr, _val: &Expr) {
1508 dbg!(e);
1509 unimplemented!();
1510 }
1511
1512 fn visit_expr_array_type(&mut self, this: &Expr, _: &Option<Expr>, _: &Expr) {
1513 self.gen_type_meta(this)
1514 }
1515
1516 fn visit_expr_struct_type(&mut self, this: &Expr, _s: &StructType) {
1517 self.gen_type_meta(this)
1518 }
1519
1520 fn visit_expr_func_type(&mut self, this: &Expr, _s: &FuncTypeKey) {
1521 self.gen_type_meta(this)
1522 }
1523
1524 fn visit_expr_interface_type(&mut self, this: &Expr, _s: &InterfaceType) {
1525 self.gen_type_meta(this)
1526 }
1527
1528 fn visit_map_type(&mut self, this: &Expr, _: &Expr, _: &Expr, _map: &Expr) {
1529 self.gen_type_meta(this)
1530 }
1531
1532 fn visit_chan_type(&mut self, this: &Expr, _chan: &Expr, _dir: &ChanDir) {
1533 self.gen_type_meta(this)
1534 }
1535
1536 fn visit_bad_expr(&mut self, _: &Expr, _e: &BadExpr) {
1537 unreachable!();
1538 }
1539}
1540
1541impl<'a> StmtVisitor for CodeGen<'a> {
1542 type Result = ();
1543
1544 fn visit_stmt(&mut self, stmt: &Stmt) {
1545 walk_stmt(self, stmt)
1546 }
1547
1548 fn visit_decl(&mut self, decl: &Decl) {
1549 walk_decl(self, decl)
1550 }
1551
1552 fn visit_stmt_decl_gen(&mut self, gdecl: &GenDecl) {
1553 for s in gdecl.specs.iter() {
1554 let spec = &self.ast_objs.specs[*s];
1555 match spec {
1556 Spec::Import(_) => {
1557 }
1559 Spec::Type(ts) => {
1560 let ident = self.ast_objs.idents[ts.name].clone();
1561 let m = self
1562 .tlookup
1563 .gen_def_type_meta(ts.name, self.objects, self.dummy_gcv);
1564 self.current_func_add_const_def(&ident, GosValue::Metadata(m));
1565 }
1566 Spec::Value(vs) => match &gdecl.token {
1567 Token::VAR => {
1568 if !current_func!(self).is_ctor() {
1570 self.gen_def_var(vs);
1571 }
1572 }
1573 Token::CONST => self.gen_def_const(&vs.names, &vs.values),
1574 _ => unreachable!(),
1575 },
1576 }
1577 }
1578 }
1579
1580 fn visit_stmt_decl_func(&mut self, fdecl: &FuncDeclKey) -> Self::Result {
1581 let decl = &self.ast_objs.fdecls[*fdecl];
1582 if decl.body.is_none() {
1583 unimplemented!()
1584 }
1585 let tc_type = self.tlookup.get_def_tc_type(decl.name);
1586 let stmt = decl.body.as_ref().unwrap();
1587 let fkey = self.gen_func_def(tc_type, decl.typ, decl.recv.clone(), stmt);
1588 let cls = GosValue::new_closure(fkey, &self.objects.functions);
1589 if let Some(self_ident) = &decl.recv {
1591 let field = &self.ast_objs.fields[self_ident.list[0]];
1592 let name = &self.ast_objs.idents[decl.name].name;
1593 let meta =
1594 self.tlookup
1595 .get_meta_by_node_id(field.typ.id(), self.objects, self.dummy_gcv);
1596 meta.set_method_code(name, fkey, &mut self.objects.metas);
1597 } else {
1598 let ident = &self.ast_objs.idents[decl.name];
1599 let pkg = &mut self.objects.packages[self.pkg_key];
1600 pkg.add_member(ident.name.clone(), cls);
1601 }
1602 }
1603
1604 fn visit_stmt_labeled(&mut self, lstmt: &LabeledStmtKey) {
1605 let stmt = &self.ast_objs.l_stmts[*lstmt];
1606 let offset = current_func!(self).code().len();
1607 let entity = self.ast_objs.idents[stmt.label].entity_key().unwrap();
1608 let is_breakable = match &stmt.stmt {
1609 Stmt::For(_) | Stmt::Range(_) | Stmt::Select(_) | Stmt::Switch(_) => true,
1610 _ => false,
1611 };
1612 self.branch.add_label(entity, offset, is_breakable);
1613 self.visit_stmt(&stmt.stmt);
1614 }
1615
1616 fn visit_stmt_send(&mut self, sstmt: &SendStmt) {
1617 self.visit_expr(&sstmt.chan);
1618 self.visit_expr(&sstmt.val);
1619 let t = self.tlookup.get_expr_value_type(&sstmt.val);
1620 current_func_mut!(self).emit_code_with_type(Opcode::SEND, t, Some(sstmt.arrow));
1621 }
1622
1623 fn visit_stmt_incdec(&mut self, idcstmt: &IncDecStmt) {
1624 self.gen_assign(&idcstmt.token, &vec![&idcstmt.expr], RightHandSide::Nothing);
1625 }
1626
1627 fn visit_stmt_assign(&mut self, astmt: &AssignStmtKey) {
1628 let stmt = &self.ast_objs.a_stmts[*astmt];
1629 self.gen_assign(
1630 &stmt.token,
1631 &stmt.lhs.iter().map(|x| x).collect(),
1632 RightHandSide::Values(&stmt.rhs),
1633 );
1634 }
1635
1636 fn visit_stmt_go(&mut self, gostmt: &GoStmt) {
1637 match &gostmt.call {
1638 Expr::Call(call) => {
1639 self.gen_call(
1640 &call.func,
1641 &call.args,
1642 call.ellipsis.is_some(),
1643 CallStyle::Async,
1644 );
1645 }
1646 _ => unreachable!(),
1647 }
1648 }
1649
1650 fn visit_stmt_defer(&mut self, dstmt: &DeferStmt) {
1651 current_func_mut!(self).flag = FuncFlag::HasDefer;
1652 match &dstmt.call {
1653 Expr::Call(call) => {
1654 self.gen_call(
1655 &call.func,
1656 &call.args,
1657 call.ellipsis.is_some(),
1658 CallStyle::Defer,
1659 );
1660 }
1661 _ => unreachable!(),
1662 }
1663 }
1664
1665 fn visit_stmt_return(&mut self, rstmt: &ReturnStmt) {
1666 let pos = Some(rstmt.ret);
1667 let types = self
1668 .tlookup
1669 .get_sig_returns_tc_types(*self.func_t_stack.last().unwrap());
1670 for (i, expr) in rstmt.results.iter().enumerate() {
1671 self.visit_expr(expr);
1672 let tc_type = self.tlookup.get_expr_tc_type(expr);
1673 let t =
1674 self.try_cast_to_iface(Some(types[i]), Some(tc_type), -1, expr.pos(&self.ast_objs));
1675 let mut emitter = current_func_emitter!(self);
1676 emitter.emit_store(
1677 &LeftHandSide::Primitive(EntIndex::LocalVar(i as OpIndex)),
1678 -1,
1679 None,
1680 None,
1681 t,
1682 pos,
1683 );
1684 emitter.emit_pop(1, pos);
1685 }
1686 current_func_emitter!(self).emit_return(None, pos);
1687 }
1688
1689 fn visit_stmt_branch(&mut self, bstmt: &BranchStmt) {
1690 match bstmt.token {
1691 Token::BREAK | Token::CONTINUE => {
1692 let entity = bstmt
1693 .label
1694 .map(|x| self.ast_objs.idents[x].entity_key().unwrap());
1695 self.branch.add_point(
1696 current_func_mut!(self),
1697 bstmt.token.clone(),
1698 entity,
1699 bstmt.token_pos,
1700 );
1701 }
1702 Token::GOTO => {
1703 let func = current_func_mut!(self);
1704 let label = bstmt.label.unwrap();
1705 let entity = self.ast_objs.idents[label].entity_key().unwrap();
1706 self.branch.go_to(func, &entity, bstmt.token_pos);
1707 }
1708 Token::FALLTHROUGH => {
1709 }
1711 _ => unreachable!(),
1712 }
1713 }
1714
1715 fn visit_stmt_block(&mut self, bstmt: &BlockStmt) {
1716 for stmt in bstmt.list.iter() {
1717 self.visit_stmt(stmt);
1718 }
1719 }
1720
1721 fn visit_stmt_if(&mut self, ifstmt: &IfStmt) {
1722 if let Some(init) = &ifstmt.init {
1723 self.visit_stmt(init);
1724 }
1725 self.visit_expr(&ifstmt.cond);
1726 let func = current_func_mut!(self);
1727 func.emit_code(Opcode::JUMP_IF_NOT, Some(ifstmt.if_pos));
1728 let top_marker = func.next_code_index();
1729
1730 drop(func);
1731 self.visit_stmt_block(&ifstmt.body);
1732 let marker_if_arm_end = if ifstmt.els.is_some() {
1733 let func = current_func_mut!(self);
1734 func.emit_code(Opcode::JUMP, Some(ifstmt.if_pos));
1736 Some(func.next_code_index())
1737 } else {
1738 None
1739 };
1740
1741 let func = current_func_mut!(self);
1743 let offset = func.offset(top_marker);
1744 func.instruction_mut(top_marker - 1).set_imm(offset);
1745
1746 if let Some(els) = &ifstmt.els {
1747 self.visit_stmt(els);
1748 let func = current_func_mut!(self);
1750 let marker = marker_if_arm_end.unwrap();
1751 let offset = func.offset(marker);
1752 func.instruction_mut(marker - 1).set_imm(offset);
1753 }
1754 }
1755
1756 fn visit_stmt_case(&mut self, _cclause: &CaseClause) {
1757 unreachable!(); }
1759
1760 fn visit_stmt_switch(&mut self, sstmt: &SwitchStmt) {
1761 self.branch.enter_block();
1762
1763 if let Some(init) = &sstmt.init {
1764 self.visit_stmt(init);
1765 }
1766 let tag_type = match &sstmt.tag {
1767 Some(e) => {
1768 self.visit_expr(e);
1769 self.tlookup.get_expr_value_type(e)
1770 }
1771 None => {
1772 current_func_mut!(self).emit_code(Opcode::PUSH_TRUE, None);
1773 ValueType::Bool
1774 }
1775 };
1776
1777 self.gen_switch_body(&*sstmt.body, tag_type);
1778
1779 self.branch.leave_block(current_func_mut!(self), None);
1780 }
1781
1782 fn visit_stmt_type_switch(&mut self, tstmt: &TypeSwitchStmt) {
1783 if let Some(init) = &tstmt.init {
1784 self.visit_stmt(init);
1785 }
1786
1787 let (ident_expr, assert) = match &tstmt.assign {
1788 Stmt::Assign(ass_key) => {
1789 let ass = &self.ast_objs.a_stmts[*ass_key];
1790 (Some(&ass.lhs[0]), &ass.rhs[0])
1791 }
1792 Stmt::Expr(e) => (None, &**e),
1793 _ => unreachable!(),
1794 };
1795 let (v, pos) = match assert {
1796 Expr::TypeAssert(ta) => (&ta.expr, Some(ta.l_paren)),
1797 _ => unreachable!(),
1798 };
1799
1800 if let Some(iexpr) = ident_expr {
1801 let ident = &self.ast_objs.idents[*iexpr.try_as_ident().unwrap()];
1802 let ident_key = ident.entity.clone().into_key();
1803 let func = current_func_mut!(self);
1804 let index = func.add_local(ident_key);
1805 func.add_local_zero(GosValue::new_nil());
1806 self.visit_expr(v);
1807 let func = current_func_mut!(self);
1808 func.emit_code_with_flag_imm(Opcode::TYPE, true, index.into(), pos);
1809 } else {
1810 self.visit_expr(v);
1811 current_func_mut!(self).emit_code(Opcode::TYPE, pos);
1812 }
1813
1814 self.gen_switch_body(&*tstmt.body, ValueType::Metadata);
1815 }
1816
1817 fn visit_stmt_comm(&mut self, _cclause: &CommClause) {
1818 unimplemented!();
1819 }
1820
1821 fn visit_stmt_select(&mut self, sstmt: &SelectStmt) {
1822 self.branch.enter_block();
1847
1848 let mut helper = SelectHelper::new();
1849 let comms: Vec<&CommClause> = sstmt
1850 .body
1851 .list
1852 .iter()
1853 .map(|s| SelectHelper::to_comm_clause(s))
1854 .collect();
1855 for c in comms.iter() {
1856 let (typ, pos) = match &c.comm {
1857 Some(comm) => match comm {
1858 Stmt::Send(send_stmt) => {
1859 self.visit_expr(&send_stmt.chan);
1860 self.visit_expr(&send_stmt.val);
1861 let t = self.tlookup.get_expr_value_type(&send_stmt.val);
1862 (CommType::Send(t), send_stmt.arrow)
1863 }
1864 Stmt::Assign(ass_key) => {
1865 let ass = &self.ast_objs.a_stmts[*ass_key];
1866 let (e, pos) = SelectHelper::unwrap_recv(&ass.rhs[0]);
1867 self.visit_expr(e);
1868 let t = match &ass.lhs.len() {
1869 1 => CommType::Recv(&ass),
1870 2 => CommType::RecvCommaOk(&ass),
1871 _ => unreachable!(),
1872 };
1873 (t, pos)
1874 }
1875 Stmt::Expr(expr_stmt) => {
1876 let (e, pos) = SelectHelper::unwrap_recv(expr_stmt);
1877 self.visit_expr(e);
1878 (CommType::RecvNoLhs, pos)
1879 }
1880 _ => unreachable!(),
1881 },
1882 None => (CommType::Default, c.colon),
1883 };
1884 helper.add_comm(typ, pos);
1885 }
1886
1887 helper.emit_select(current_func_mut!(self));
1888
1889 let last_index = comms.len() - 1;
1890 for (i, c) in comms.iter().enumerate() {
1891 let begin = current_func!(self).next_code_index();
1892
1893 match helper.comm_type(i) {
1894 CommType::Recv(ass) | CommType::RecvCommaOk(ass) => {
1895 self.gen_assign(
1896 &ass.token,
1897 &ass.lhs.iter().map(|x| x).collect(),
1898 RightHandSide::SelectRecv(&ass.rhs[0]),
1899 );
1900 }
1901 _ => {}
1902 }
1903
1904 for stmt in c.body.iter() {
1905 self.visit_stmt(stmt);
1906 }
1907 let func = current_func_mut!(self);
1908 let mut end = func.next_code_index();
1909 if i < last_index {
1911 func.emit_code(Opcode::JUMP, None);
1912 } else {
1913 end -= 1;
1914 }
1915
1916 helper.set_block_begin_end(i, begin, end);
1917 }
1918
1919 helper.patch_select(current_func_mut!(self));
1920
1921 self.branch.leave_block(current_func_mut!(self), None);
1922 }
1923
1924 fn visit_stmt_for(&mut self, fstmt: &ForStmt) {
1925 self.branch.enter_block();
1926
1927 if let Some(init) = &fstmt.init {
1928 self.visit_stmt(init);
1929 }
1930 let top_marker = current_func!(self).next_code_index();
1931 let out_marker = if let Some(cond) = &fstmt.cond {
1932 self.visit_expr(&cond);
1933 let func = current_func_mut!(self);
1934 func.emit_code(Opcode::JUMP_IF_NOT, Some(fstmt.for_pos));
1935 Some(func.next_code_index())
1936 } else {
1937 None
1938 };
1939 self.visit_stmt_block(&fstmt.body);
1940 let continue_marker = if let Some(post) = &fstmt.post {
1941 let m = current_func!(self).next_code_index();
1943 self.visit_stmt(post);
1944 m
1945 } else {
1946 top_marker
1948 };
1949
1950 let func = current_func_mut!(self);
1952 let offset = -func.offset(top_marker) - 1;
1953 func.emit_code_with_imm(Opcode::JUMP, offset, Some(fstmt.for_pos));
1954
1955 if let Some(m) = out_marker {
1957 let func = current_func_mut!(self);
1958 let offset = func.offset(m);
1959 func.instruction_mut(m - 1).set_imm(offset);
1960 }
1961
1962 self.branch
1963 .leave_block(current_func_mut!(self), Some(continue_marker));
1964 }
1965
1966 fn visit_stmt_range(&mut self, rstmt: &RangeStmt) {
1967 self.branch.enter_block();
1968
1969 let blank = Expr::Ident(self.blank_ident);
1970 let lhs = vec![
1971 rstmt.key.as_ref().unwrap_or(&blank),
1972 rstmt.val.as_ref().unwrap_or(&blank),
1973 ];
1974 let marker = self
1975 .gen_assign(&rstmt.token, &lhs, RightHandSide::Range(&rstmt.expr))
1976 .unwrap();
1977
1978 self.visit_stmt_block(&rstmt.body);
1979 let func = current_func_mut!(self);
1981 let offset = -func.offset(marker) - 1;
1982 let end_offset = func.offset(marker);
1984 func.instruction_mut(marker).set_imm(end_offset);
1985 func.emit_code_with_imm(Opcode::JUMP, offset, Some(rstmt.token_pos));
1986
1987 self.branch
1988 .leave_block(current_func_mut!(self), Some(marker));
1989 }
1990
1991 fn visit_empty_stmt(&mut self, _e: &EmptyStmt) {}
1992
1993 fn visit_bad_stmt(&mut self, _b: &BadStmt) {
1994 unreachable!();
1995 }
1996
1997 fn visit_bad_decl(&mut self, _b: &BadDecl) {
1998 unreachable!();
1999 }
2000}