forked from M-Labs/nac3
nac3core/toplevel: impl scalar conversion
Implemented scalar conversion functions as builtin functions. `round` for int64 is now implemented as `round64`.
This commit is contained in:
parent
07a9229d52
commit
1d2a32b140
|
@ -36,7 +36,13 @@ impl TopLevelComposer {
|
|||
pub fn new(
|
||||
builtins: Vec<(StrRef, FunSignature)>,
|
||||
) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) {
|
||||
let primitives = Self::make_primitives();
|
||||
let mut primitives = Self::make_primitives();
|
||||
|
||||
let int32 = primitives.0.int32;
|
||||
let int64 = primitives.0.int64;
|
||||
let float = primitives.0.float;
|
||||
let num_ty = primitives.1.get_fresh_var_with_range(&[int32, int64, float]);
|
||||
let var_map: HashMap<_, _> = vec![(num_ty.1, num_ty.0)].into_iter().collect();
|
||||
|
||||
let mut definition_ast_list = {
|
||||
let top_level_def_list = vec![
|
||||
|
@ -60,8 +66,213 @@ impl TopLevelComposer {
|
|||
))),
|
||||
Arc::new(RwLock::new(Self::make_top_level_class_def(3, None, "bool".into(), None))),
|
||||
Arc::new(RwLock::new(Self::make_top_level_class_def(4, None, "none".into(), None))),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "int32".into(),
|
||||
simple_name: "int32".into(),
|
||||
signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature {
|
||||
args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }],
|
||||
ret: int32,
|
||||
vars: var_map.clone(),
|
||||
}))),
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, fun, args| {
|
||||
let int32 = ctx.primitives.int32;
|
||||
let int64 = ctx.primitives.int64;
|
||||
let float = ctx.primitives.float;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1;
|
||||
if ctx.unifier.unioned(arg_ty, int32) {
|
||||
Some(arg)
|
||||
} else if ctx.unifier.unioned(arg_ty, int64) {
|
||||
Some(
|
||||
ctx.builder
|
||||
.build_int_truncate(
|
||||
arg.into_int_value(),
|
||||
ctx.ctx.i32_type(),
|
||||
"trunc",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
} else if ctx.unifier.unioned(arg_ty, float) {
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_float_to_signed_int(
|
||||
arg.into_float_value(),
|
||||
ctx.ctx.i32_type(),
|
||||
"fptosi",
|
||||
)
|
||||
.into();
|
||||
Some(val)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
)))),
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "int64".into(),
|
||||
simple_name: "int64".into(),
|
||||
signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature {
|
||||
args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }],
|
||||
ret: int64,
|
||||
vars: var_map.clone(),
|
||||
}))),
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, fun, args| {
|
||||
let int32 = ctx.primitives.int32;
|
||||
let int64 = ctx.primitives.int64;
|
||||
let float = ctx.primitives.float;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1;
|
||||
if ctx.unifier.unioned(arg_ty, int32) {
|
||||
Some(
|
||||
ctx.builder
|
||||
.build_int_s_extend(
|
||||
arg.into_int_value(),
|
||||
ctx.ctx.i64_type(),
|
||||
"sext",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
} else if ctx.unifier.unioned(arg_ty, int64) {
|
||||
Some(arg)
|
||||
} else if ctx.unifier.unioned(arg_ty, float) {
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_float_to_signed_int(
|
||||
arg.into_float_value(),
|
||||
ctx.ctx.i64_type(),
|
||||
"fptosi",
|
||||
)
|
||||
.into();
|
||||
Some(val)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
)))),
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "float".into(),
|
||||
simple_name: "float".into(),
|
||||
signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature {
|
||||
args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }],
|
||||
ret: float,
|
||||
vars: var_map,
|
||||
}))),
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, fun, args| {
|
||||
let int32 = ctx.primitives.int32;
|
||||
let int64 = ctx.primitives.int64;
|
||||
let float = ctx.primitives.float;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1;
|
||||
if ctx.unifier.unioned(arg_ty, int32)
|
||||
|| ctx.unifier.unioned(arg_ty, int64)
|
||||
{
|
||||
let arg = args[0].1.into_int_value();
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp")
|
||||
.into();
|
||||
Some(val)
|
||||
} else if ctx.unifier.unioned(arg_ty, float) {
|
||||
Some(arg)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
)))),
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "round".into(),
|
||||
simple_name: "round".into(),
|
||||
signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature {
|
||||
args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }],
|
||||
ret: int32,
|
||||
vars: Default::default(),
|
||||
}))),
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
||||
let arg = args[0].1;
|
||||
let round_intrinsic =
|
||||
ctx.module.get_function("llvm.rint.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
let fn_type = float.fn_type(&[float.into()], false);
|
||||
ctx.module.add_function("llvm.rint.f64", fn_type, None)
|
||||
});
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_call(round_intrinsic, &[arg], "round")
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
Some(
|
||||
ctx.builder
|
||||
.build_float_to_signed_int(
|
||||
val.into_float_value(),
|
||||
ctx.ctx.i32_type(),
|
||||
"fptosi",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
})))),
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "round64".into(),
|
||||
simple_name: "round64".into(),
|
||||
signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature {
|
||||
args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }],
|
||||
ret: int64,
|
||||
vars: Default::default(),
|
||||
}))),
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
||||
let arg = args[0].1;
|
||||
let round_intrinsic =
|
||||
ctx.module.get_function("llvm.rint.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
let fn_type = float.fn_type(&[float.into()], false);
|
||||
ctx.module.add_function("llvm.rint.f64", fn_type, None)
|
||||
});
|
||||
let val = ctx
|
||||
.builder
|
||||
.build_call(round_intrinsic, &[arg], "round")
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap();
|
||||
Some(
|
||||
ctx.builder
|
||||
.build_float_to_signed_int(
|
||||
val.into_float_value(),
|
||||
ctx.ctx.i64_type(),
|
||||
"fptosi",
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
})))),
|
||||
})),
|
||||
];
|
||||
let ast_list: Vec<Option<ast::Stmt<()>>> = vec![None, None, None, None, None];
|
||||
let ast_list: Vec<Option<ast::Stmt<()>>> =
|
||||
(0..top_level_def_list.len()).map(|_| None).collect();
|
||||
izip!(top_level_def_list, ast_list).collect_vec()
|
||||
};
|
||||
let primitives_ty = primitives.0;
|
||||
|
@ -87,6 +298,19 @@ impl TopLevelComposer {
|
|||
let mut built_in_id: HashMap<StrRef, DefinitionId> = Default::default();
|
||||
let mut built_in_ty: HashMap<StrRef, Type> = Default::default();
|
||||
|
||||
for (id, name) in ["int32", "int64", "float", "round", "round64"].iter().rev().enumerate() {
|
||||
let name = (**name).into();
|
||||
let id = definition_ast_list.len() - id - 1;
|
||||
let def = definition_ast_list[id].0.read();
|
||||
if let TopLevelDef::Function { simple_name, signature, .. } = &*def {
|
||||
assert!(name == *simple_name);
|
||||
built_in_ty.insert(name, *signature);
|
||||
built_in_id.insert(name, DefinitionId(id));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
for (name, sig) in builtins {
|
||||
let fun_sig = unifier.add_ty(TypeEnum::TFunc(RefCell::new(sig)));
|
||||
built_in_ty.insert(name, fun_sig);
|
||||
|
@ -133,7 +357,7 @@ impl TopLevelComposer {
|
|||
self.unifier.get_shared_unifier(),
|
||||
self.primitives_ty,
|
||||
)])),
|
||||
personality_symbol: None
|
||||
personality_symbol: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -816,17 +1040,7 @@ impl TopLevelComposer {
|
|||
} = &mut *class_def
|
||||
{
|
||||
if let ast::StmtKind::ClassDef { name, bases, body, .. } = &class_ast {
|
||||
(
|
||||
*object_id,
|
||||
*name,
|
||||
bases,
|
||||
body,
|
||||
ancestors,
|
||||
fields,
|
||||
methods,
|
||||
type_vars,
|
||||
resolver,
|
||||
)
|
||||
(*object_id, *name, bases, body, ancestors, fields, methods, type_vars, resolver)
|
||||
} else {
|
||||
unreachable!("here must be class def ast");
|
||||
}
|
||||
|
@ -1087,8 +1301,7 @@ impl TopLevelComposer {
|
|||
let mut is_override: HashSet<StrRef> = HashSet::new();
|
||||
for (anc_method_name, anc_method_ty, anc_method_def_id) in methods {
|
||||
// find if there is a method with same name in the child class
|
||||
let mut to_be_added =
|
||||
(*anc_method_name, *anc_method_ty, *anc_method_def_id);
|
||||
let mut to_be_added = (*anc_method_name, *anc_method_ty, *anc_method_def_id);
|
||||
for (class_method_name, class_method_ty, class_method_defid) in
|
||||
class_methods_def.iter()
|
||||
{
|
||||
|
@ -1107,11 +1320,8 @@ impl TopLevelComposer {
|
|||
}
|
||||
// mark it as added
|
||||
is_override.insert(*class_method_name);
|
||||
to_be_added = (
|
||||
*class_method_name,
|
||||
*class_method_ty,
|
||||
*class_method_defid,
|
||||
);
|
||||
to_be_added =
|
||||
(*class_method_name, *class_method_ty, *class_method_defid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue