1use super::branch::BranchHelper;
6use super::codegen::*;
7use super::consts::*;
8use super::context::*;
9use super::package::PkgHelper;
10use super::types::{TypeCache, TypeLookup};
11use go_parser::ast::Ident;
12use go_parser::{AstObjects, ErrorList, FileSet, IdentKey, Map};
13use go_types::{
14 check::TypeInfo, ImportKey, Importer, PackageKey as TCPackageKey, SourceRead, TCObjects,
15 TraceConfig,
16};
17use go_vm::types::*;
18use go_vm::*;
19use std::path::Path;
20use std::vec;
21
22pub fn parse_check_gen<S: SourceRead>(
23 path: &Path,
24 tconfig: &TraceConfig,
25 reader: &S,
26 debug_info: bool,
27) -> Result<Bytecode, ErrorList> {
28 let mut fset = FileSet::new();
29
30 let ast_objs = &mut AstObjects::new();
31 let tc_objs = &mut TCObjects::new();
32 let results = &mut Map::new();
33 let pkgs = &mut Map::new();
34 let el = ErrorList::new();
35
36 let importer = &mut Importer::new(
37 &tconfig, reader, &mut fset, pkgs, results, ast_objs, tc_objs, &el, 0,
38 );
39 let key = ImportKey::new(
40 path.to_str().unwrap(),
41 reader.working_dir().to_str().unwrap(),
42 );
43 let main_pkg = importer.import(&key);
44 if el.len() > 0 {
45 Err(el)
46 } else {
47 let blank_ident = ast_objs.idents.insert(Ident::blank(0));
48 let main_ident = ast_objs.idents.insert(Ident::with_str(0, "main"));
49 Ok(gen_byte_code(
50 ast_objs,
51 tc_objs,
52 results,
53 main_pkg.unwrap(),
54 main_ident,
55 blank_ident,
56 debug_info.then_some(fset),
57 ))
58 }
59}
60
61fn gen_byte_code(
62 ast_objs: &AstObjects,
63 tc_objs: &TCObjects,
64 checker_result: &Map<TCPackageKey, TypeInfo>,
65 tc_main_pkg: TCPackageKey,
66 main_ident: IdentKey,
67 blank_ident: IdentKey,
68 fset: Option<FileSet>,
69) -> Bytecode {
70 let vm_objs = VMObjects::new();
71 let mut vmctx = CodeGenVMCtx::new(vm_objs);
72 let consts = Consts::new();
73 let mut iface_selector = IfaceSelector::new();
74 let mut struct_selector = StructSelector::new();
75 let mut pkg_map = Map::new();
76 let mut type_cache: TypeCache = Map::new();
77 let mut branch_helper = BranchHelper::new();
78 let mut result_funcs = vec![];
79
80 for (&tcpkg, _) in checker_result.iter() {
81 let name = tc_objs.pkgs[tcpkg].name().clone().unwrap();
82 let pkey = vmctx.packages_mut().insert(PackageObj::new(name));
83 pkg_map.insert(tcpkg, pkey);
84 }
85
86 let main_pkg = pkg_map[&tc_main_pkg];
87 let entry = gen_entry_func(&mut vmctx, &consts, main_pkg, main_ident);
88 let entry_key = entry.f_key;
89 result_funcs.push(entry);
90
91 for (tcpkg, ti) in checker_result.iter() {
92 let mut pkg_helper = PkgHelper::new(ast_objs, tc_objs, &pkg_map);
93 let cgen = CodeGen::new(
94 &mut vmctx,
95 &consts,
96 ast_objs,
97 tc_objs,
98 &ti,
99 &mut type_cache,
100 &mut iface_selector,
101 &mut struct_selector,
102 &mut branch_helper,
103 &mut pkg_helper,
104 pkg_map[tcpkg],
105 blank_ident,
106 );
107 result_funcs.append(&mut cgen.gen_with_files(&ti.ast_files, *tcpkg));
108 }
109
110 let (consts, cst_map) = consts.get_runtime_consts(&mut vmctx);
111 for f in result_funcs.into_iter() {
112 f.into_runtime_func(ast_objs, &mut vmctx, branch_helper.labels(), &cst_map);
113 }
114
115 let dummy_ti = TypeInfo::new();
116 let mut lookup = TypeLookup::new(tc_objs, &dummy_ti, &mut type_cache);
117 let iface_binding = iface_selector
118 .result()
119 .into_iter()
120 .map(|x| lookup.iface_binding_info(x, &mut vmctx))
121 .collect();
122
123 Bytecode::new(
124 vmctx.into_vmo(),
125 consts,
126 iface_binding,
127 struct_selector.result(),
128 entry_key,
129 main_pkg,
130 fset,
131 )
132}
133
134fn gen_entry_func<'a, 'c>(
136 vmctx: &'a mut CodeGenVMCtx,
137 consts: &'c Consts,
138 pkg: PackageKey,
139 main_ident: IdentKey,
140) -> FuncCtx<'c> {
141 let fmeta = vmctx.prim_meta().default_sig;
142 let fobj = vmctx.function_with_meta(None, fmeta.clone(), FuncFlag::Default);
143 let fkey = *fobj.as_function();
144 let mut fctx = FuncCtx::new(fkey, None, consts);
145 fctx.emit_import(pkg, None);
146 let pkg_addr = fctx.add_package(pkg);
147 let index = Addr::PkgMemberIndex(pkg, main_ident);
148 fctx.emit_load_pkg(Addr::Regsiter(0), pkg_addr, index, None);
149 fctx.emit_call(Addr::Regsiter(0), 0, CallStyle::Default, None);
150 fctx.emit_return(None, None, vmctx.functions());
151 fctx
152}