go_codegen/
entry.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5use 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
134// generate the entry function for Bytecode
135fn 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}