1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
13 use ir::MemberOpBuilder;
15 use ir::StringInterner;
18 use crate::func::MethodInfo;
20 pub(crate) fn lower_func<'a>(
22 method_info: Option<Arc<MethodInfo<'_>>>,
23 strings: Arc<StringInterner>,
27 ir::print::DisplayFunc::new(&func, true, &strings)
30 // In a closure we implicitly load all the properties as locals - so start
31 // with that as a prelude to all entrypoints.
32 if let Some(method_info) = method_info.as_ref() {
33 if method_info.flags.contains(MethodFlags::IS_CLOSURE_BODY) {
34 load_closure_vars(&mut func, method_info, &strings);
38 // Start by 'unasync'ing the Func.
39 ir::passes::unasync(&mut func);
42 ir::print::DisplayFunc::new(&func, true, &strings)
45 let mut builder = FuncBuilder::with_func(func, Arc::clone(&strings));
47 // Simplify various Instrs.
48 super::instrs::lower_instrs(&mut builder, method_info);
50 // Write the complex constants out as a prelude to the function.
51 super::constants::write_constants(&mut builder);
53 let mut func = builder.finish();
55 ir::passes::split_critical_edges(&mut func, true);
57 ir::passes::clean::run(&mut func);
61 ir::print::DisplayFunc::new(&func, true, &strings)
67 fn load_closure_vars(func: &mut Func<'_>, method_info: &MethodInfo<'_>, strings: &StringInterner) {
68 let mut instrs = Vec::new();
70 let loc = func.loc_id;
72 for prop in &method_info.class.properties {
73 // Property names are the variable names without the '$'.
74 let prop_str = strings.lookup_bstr(prop.name.id);
75 let mut var = prop_str.to_vec();
77 let lid = LocalId::Named(strings.intern_bytes(var));
79 let iid = func.alloc_instr(Instr::MemberOp(
80 MemberOpBuilder::base_h(loc).query_pt(prop.name),
83 instrs.push(func.alloc_instr(Instr::Hhbc(Hhbc::SetL(iid.into(), lid, loc))));
86 func.block_mut(Func::ENTRY_BID).iids.splice(0..0, instrs);