Get llvm value with expected type (#256) #259
|
@ -68,7 +68,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||
let result = gen_call(self, ctx, obj, fun, params)?;
|
||||
if let Some(end) = self.end.clone() {
|
||||
let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self)?;
|
||||
let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self, end.custom.unwrap())?;
|
||||
let now = self.timeline.emit_now_mu(ctx);
|
||||
let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| {
|
||||
let i64 = ctx.ctx.i64_type();
|
||||
|
@ -88,7 +88,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||
ctx.builder.build_store(end_store, max);
|
||||
}
|
||||
if let Some(start) = self.start.clone() {
|
||||
let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self)?;
|
||||
let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self, start.custom.unwrap())?;
|
||||
self.timeline.emit_at_mu(ctx, start_val);
|
||||
}
|
||||
Ok(result)
|
||||
|
@ -120,7 +120,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||
let old_start = self.start.take();
|
||||
let old_end = self.end.take();
|
||||
let now = if let Some(old_start) = &old_start {
|
||||
self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self)?
|
||||
self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self, old_start.custom.unwrap())?
|
||||
} else {
|
||||
self.timeline.emit_now_mu(ctx)
|
||||
};
|
||||
|
@ -174,8 +174,10 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||
};
|
||||
// set duration
|
||||
let end_expr = self.end.take().unwrap();
|
||||
let end_val =
|
||||
self.gen_expr(ctx, &end_expr)?.unwrap().to_basic_value_enum(ctx, self)?;
|
||||
let end_val = self
|
||||
.gen_expr(ctx, &end_expr)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, self, end_expr.custom.unwrap())?;
|
||||
|
||||
// inside a sequential block
|
||||
if old_start.is_none() {
|
||||
|
@ -186,7 +188,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||
let outer_end_val = self
|
||||
.gen_expr(ctx, old_end)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, self)?;
|
||||
.to_basic_value_enum(ctx, self, old_end.custom.unwrap())?;
|
||||
let smax =
|
||||
ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| {
|
||||
let i64 = ctx.ctx.i64_type();
|
||||
|
@ -371,7 +373,7 @@ fn rpc_codegen_callback_fn<'ctx, 'a>(
|
|||
.0
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| mapping.remove(&arg.name).unwrap().to_basic_value_enum(ctx, generator))
|
||||
.map(|arg| mapping.remove(&arg.name).unwrap().to_basic_value_enum(ctx, generator, arg.ty))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
if let Some(obj) = obj {
|
||||
if let ValueEnum::Static(obj) = obj.1 {
|
||||
|
@ -511,11 +513,13 @@ pub fn attributes_writeback<'ctx, 'a>(
|
|||
}
|
||||
let ty = ty.unwrap();
|
||||
match &*ctx.unifier.get_ty(ty) {
|
||||
TypeEnum::TObj { fields, .. } => {
|
||||
TypeEnum::TObj { fields, obj_id, .. }
|
||||
if *obj_id != ctx.primitives.option.get_obj_id(&ctx.unifier) =>
|
||||
{
|
||||
// we only care about primitive attributes
|
||||
// for non-primitive attributes, they should be in another global
|
||||
let mut attributes = Vec::new();
|
||||
let obj = inner_resolver.get_obj_value(py, val, ctx, generator)?.unwrap();
|
||||
let obj = inner_resolver.get_obj_value(py, val, ctx, generator, ty)?.unwrap();
|
||||
for (name, (field_ty, is_mutable)) in fields.iter() {
|
||||
if !is_mutable {
|
||||
continue
|
||||
|
@ -540,7 +544,7 @@ pub fn attributes_writeback<'ctx, 'a>(
|
|||
let pydict = PyDict::new(py);
|
||||
pydict.set_item("obj", val)?;
|
||||
host_attributes.append(pydict)?;
|
||||
values.push((ty, inner_resolver.get_obj_value(py, val, ctx, generator)?.unwrap()));
|
||||
values.push((ty, inner_resolver.get_obj_value(py, val, ctx, generator, ty)?.unwrap()));
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
|
|
|
@ -328,8 +328,9 @@ impl Nac3 {
|
|||
ret: primitive.none,
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap();
|
||||
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap();
|
||||
time_fns.emit_at_mu(ctx, arg);
|
||||
Ok(None)
|
||||
}))),
|
||||
|
@ -345,8 +346,9 @@ impl Nac3 {
|
|||
ret: primitive.none,
|
||||
vars: HashMap::new(),
|
||||
},
|
||||
Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap();
|
||||
Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| {
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap();
|
||||
time_fns.emit_delay_mu(ctx, arg);
|
||||
Ok(None)
|
||||
}))),
|
||||
|
|
|
@ -131,6 +131,7 @@ impl StaticValue for PythonValue {
|
|||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
if let Some(val) = self.resolver.id_to_primitive.read().get(&self.id) {
|
||||
return Ok(match val {
|
||||
|
@ -150,7 +151,7 @@ impl StaticValue for PythonValue {
|
|||
|
||||
Python::with_gil(|py| -> PyResult<BasicValueEnum<'ctx>> {
|
||||
self.resolver
|
||||
.get_obj_value(py, self.value.as_ref(py), ctx, generator)
|
||||
.get_obj_value(py, self.value.as_ref(py), ctx, generator, expected_ty)
|
||||
.map(Option::unwrap)
|
||||
}).map_err(|e| e.to_string())
|
||||
}
|
||||
|
@ -544,7 +545,7 @@ impl InnerResolver {
|
|||
let len: usize = self.helper.len_fn.call1(py, (obj,))?.extract(py)?;
|
||||
if len == 0 {
|
||||
assert!(matches!(
|
||||
&*unifier.get_ty(extracted_ty),
|
||||
&*unifier.get_ty(*ty),
|
||||
TypeEnum::TVar { fields: None, range, .. }
|
||||
if range.is_empty()
|
||||
));
|
||||
|
@ -692,6 +693,7 @@ impl InnerResolver {
|
|||
obj: &PyAny,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
expected_ty: Type,
|
||||
) -> PyResult<Option<BasicValueEnum<'ctx>>> {
|
||||
let ty_id: u64 =
|
||||
self.helper.id_fn.call1(py, (self.helper.type_fn.call1(py, (obj,))?,))?.extract(py)?;
|
||||
|
@ -734,20 +736,14 @@ impl InnerResolver {
|
|||
}
|
||||
|
||||
let len: usize = self.helper.len_fn.call1(py, (obj,))?.extract(py)?;
|
||||
let ty = if len == 0 {
|
||||
ctx.primitives.int32
|
||||
let elem_ty =
|
||||
if let TypeEnum::TList { ty } = ctx.unifier.get_ty_immutable(expected_ty).as_ref()
|
||||
{
|
||||
*ty
|
||||
} else {
|
||||
self.get_list_elem_type(
|
||||
py,
|
||||
obj,
|
||||
len,
|
||||
&mut ctx.unifier,
|
||||
&ctx.top_level.definitions.read(),
|
||||
&ctx.primitives,
|
||||
)?
|
||||
.unwrap()
|
||||
unreachable!("must be list")
|
||||
};
|
||||
let ty = ctx.get_llvm_type(generator, ty);
|
||||
let ty = ctx.get_llvm_type(generator, elem_ty);
|
||||
let size_t = generator.get_size_type(ctx.ctx);
|
||||
let arr_ty = ctx
|
||||
.ctx
|
||||
|
@ -766,8 +762,13 @@ impl InnerResolver {
|
|||
|
||||
let arr: Result<Option<Vec<_>>, _> = (0..len)
|
||||
.map(|i| {
|
||||
obj.get_item(i).and_then(|elem| self.get_obj_value(py, elem, ctx, generator).map_err(
|
||||
|e| super::CompileError::new_err(format!("Error getting element {}: {}", i, e))))
|
||||
obj
|
||||
.get_item(i)
|
||||
.and_then(|elem| self.get_obj_value(py, elem, ctx, generator, elem_ty)
|
||||
.map_err(
|
||||
|e| super::CompileError::new_err(
|
||||
format!("Error getting element {}: {}", i, e))
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
let arr = arr?.unwrap();
|
||||
|
@ -808,21 +809,48 @@ impl InnerResolver {
|
|||
|
||||
Ok(Some(global.as_pointer_value().into()))
|
||||
} else if ty_id == self.primitive_ids.tuple {
|
||||
let elements: &PyTuple = obj.cast_as()?;
|
||||
let val: Result<Option<Vec<_>>, _> =
|
||||
elements.iter().enumerate().map(|(i, elem)| self.get_obj_value(py, elem, ctx, generator).map_err(|e|
|
||||
super::CompileError::new_err(format!("Error getting element {}: {}", i, e)))).collect();
|
||||
let val = val?.unwrap();
|
||||
let val = ctx.ctx.const_struct(&val, false);
|
||||
Ok(Some(val.into()))
|
||||
if let TypeEnum::TTuple { ty } = ctx.unifier.get_ty_immutable(expected_ty).as_ref() {
|
||||
let tup_tys = ty.iter();
|
||||
let elements: &PyTuple = obj.cast_as()?;
|
||||
assert_eq!(elements.len(), tup_tys.len());
|
||||
let val: Result<Option<Vec<_>>, _> =
|
||||
elements
|
||||
.iter()
|
||||
.enumerate()
|
||||
.zip(tup_tys)
|
||||
.map(|((i, elem), ty)| self
|
||||
.get_obj_value(py, elem, ctx, generator, *ty).map_err(|e|
|
||||
super::CompileError::new_err(
|
||||
format!("Error getting element {}: {}", i, e)
|
||||
)
|
||||
)
|
||||
).collect();
|
||||
let val = val?.unwrap();
|
||||
let val = ctx.ctx.const_struct(&val, false);
|
||||
Ok(Some(val.into()))
|
||||
} else {
|
||||
unreachable!("must expect tuple type")
|
||||
}
|
||||
} else if ty_id == self.primitive_ids.option {
|
||||
let option_val_ty = match ctx.unifier.get_ty_immutable(expected_ty).as_ref() {
|
||||
TypeEnum::TObj { obj_id, params, .. }
|
||||
if *obj_id == ctx.primitives.option.get_obj_id(&ctx.unifier) =>
|
||||
{
|
||||
*params.iter().next().unwrap().1
|
||||
}
|
||||
_ => unreachable!("must be option type")
|
||||
};
|
||||
if id == self.primitive_ids.none {
|
||||
// for option type, just a null ptr, whose type needs to be casted in codegen
|
||||
// according to the type info attached in the ast
|
||||
Ok(Some(ctx.ctx.i8_type().ptr_type(AddressSpace::Generic).const_null().into()))
|
||||
// for option type, just a null ptr
|
||||
Ok(Some(
|
||||
ctx.get_llvm_type(generator, option_val_ty)
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
.const_null()
|
||||
.into(),
|
||||
))
|
||||
} else {
|
||||
match self
|
||||
.get_obj_value(py, obj.getattr("_nac3_option").unwrap(), ctx, generator)
|
||||
.get_obj_value(py, obj.getattr("_nac3_option").unwrap(), ctx, generator, option_val_ty)
|
||||
.map_err(|e| {
|
||||
super::CompileError::new_err(format!(
|
||||
"Error getting value of Option object: {}",
|
||||
|
@ -881,23 +909,8 @@ impl InnerResolver {
|
|||
let values: Result<Option<Vec<_>>, _> = fields
|
||||
.iter()
|
||||
.map(|(name, ty, _)| {
|
||||
let v = self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx, generator)
|
||||
.map_err(|e| super::CompileError::new_err(format!("Error getting field {}: {}", name, e)));
|
||||
match (v, ctx.unifier.get_ty_immutable(*ty).as_ref()) {
|
||||
(Ok(Some(v)), TypeEnum::TObj { obj_id, params, .. })
|
||||
if *obj_id == ctx.primitives.option.get_obj_id(&ctx.unifier) =>
|
||||
{
|
||||
let actual_ptr_ty = ctx
|
||||
.get_llvm_type(generator, *params.iter().next().unwrap().1)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
Ok(Some(ctx.builder.build_bitcast(
|
||||
v,
|
||||
actual_ptr_ty,
|
||||
"option_none_ptr_cast",
|
||||
)))
|
||||
}
|
||||
(v, _) => v,
|
||||
}
|
||||
self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx, generator, *ty)
|
||||
.map_err(|e| super::CompileError::new_err(format!("Error getting field {}: {}", name, e)))
|
||||
})
|
||||
.collect();
|
||||
let values = values?;
|
||||
|
|
|
@ -150,11 +150,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
};
|
||||
let actual_ptr_type =
|
||||
self.get_llvm_type(generator, ty).ptr_type(AddressSpace::Generic);
|
||||
self.builder.build_bitcast(
|
||||
self.ctx.i8_type().ptr_type(AddressSpace::Generic).const_null(),
|
||||
actual_ptr_type,
|
||||
"default_opt_none",
|
||||
)
|
||||
actual_ptr_type.const_null().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -643,14 +639,14 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
// reorder the parameters
|
||||
let mut real_params =
|
||||
fun.0.args.iter().map(|arg| mapping.remove(&arg.name).unwrap()).collect_vec();
|
||||
fun.0.args.iter().map(|arg| (mapping.remove(&arg.name).unwrap(), arg.ty)).collect_vec();
|
||||
if let Some(obj) = &obj {
|
||||
real_params.insert(0, obj.1.clone());
|
||||
real_params.insert(0, (obj.1.clone(), obj.0));
|
||||
}
|
||||
let static_params = real_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, v)| {
|
||||
.filter_map(|(i, (v, _))| {
|
||||
if let ValueEnum::Static(s) = v {
|
||||
Some((i, s.clone()))
|
||||
} else {
|
||||
|
@ -682,7 +678,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
};
|
||||
param_vals = real_params
|
||||
.into_iter()
|
||||
.map(|p| p.to_basic_value_enum(ctx, generator))
|
||||
.map(|(p, t)| p.to_basic_value_enum(ctx, generator, t))
|
||||
.collect::<Result<Vec<_>, String>>()?;
|
||||
instance_to_symbol.get(&key).cloned().ok_or_else(|| "".into())
|
||||
}
|
||||
|
@ -795,7 +791,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
let cont_bb = ctx.ctx.append_basic_block(current, "cont");
|
||||
|
||||
let Comprehension { target, iter, ifs, .. } = &generators[0];
|
||||
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator, iter.custom.unwrap())?;
|
||||
let int32 = ctx.ctx.i32_type();
|
||||
let size_t = generator.get_size_type(ctx.ctx);
|
||||
let zero_size_t = size_t.const_zero();
|
||||
|
@ -900,7 +896,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
let result = generator
|
||||
.gen_expr(ctx, cond)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?
|
||||
.into_int_value();
|
||||
let succ = ctx.ctx.append_basic_block(current, "then");
|
||||
ctx.builder.build_conditional_branch(result, succ, test_bb);
|
||||
|
@ -909,7 +905,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
let elem = generator.gen_expr(ctx, elt)?.unwrap();
|
||||
let i = ctx.builder.build_load(index, "i").into_int_value();
|
||||
let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
|
||||
let val = elem.to_basic_value_enum(ctx, generator)?;
|
||||
let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?;
|
||||
ctx.builder.build_store(elem_ptr, val);
|
||||
ctx.builder
|
||||
.build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc"));
|
||||
|
@ -934,8 +930,8 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
) -> Result<ValueEnum<'ctx>, String> {
|
||||
let ty1 = ctx.unifier.get_representative(left.custom.unwrap());
|
||||
let ty2 = ctx.unifier.get_representative(right.custom.unwrap());
|
||||
let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator, left.custom.unwrap())?;
|
||||
let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator, right.custom.unwrap())?;
|
||||
|
||||
// we can directly compare the types, because we've got their representatives
|
||||
// which would be unchanged until further unification, which we would never do
|
||||
|
@ -999,25 +995,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()),
|
||||
None => {
|
||||
let resolver = ctx.resolver.clone();
|
||||
let val = resolver.get_symbol_value(*id, ctx).unwrap();
|
||||
// if is option, need to cast pointer to handle None
|
||||
match &*ctx.unifier.get_ty(expr.custom.unwrap()) {
|
||||
TypeEnum::TObj { obj_id, params, .. }
|
||||
if *obj_id == ctx.primitives.option.get_obj_id(&ctx.unifier) =>
|
||||
{
|
||||
if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? {
|
||||
let actual_ptr_ty = ctx.get_llvm_type(
|
||||
generator,
|
||||
*params.iter().next().unwrap().1,
|
||||
)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
ctx.builder.build_bitcast(ptr, actual_ptr_ty, "option_ptr_cast").into()
|
||||
} else {
|
||||
unreachable!("option obj must be ptr")
|
||||
}
|
||||
}
|
||||
_ => val,
|
||||
}
|
||||
resolver.get_symbol_value(*id, ctx).unwrap()
|
||||
}
|
||||
},
|
||||
ExprKind::List { elts, .. } => {
|
||||
|
@ -1028,7 +1006,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.map(|x| {
|
||||
generator
|
||||
.gen_expr(ctx, x)
|
||||
.map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator))
|
||||
.map_or_else(
|
||||
Err,
|
||||
|v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap())
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let ty = if elements.is_empty() {
|
||||
|
@ -1061,7 +1042,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.map(|x| {
|
||||
generator
|
||||
.gen_expr(ctx, x)
|
||||
.map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator))
|
||||
.map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
|
||||
|
@ -1083,7 +1064,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
// note that we would handle class methods directly in calls
|
||||
match generator.gen_expr(ctx, value)?.unwrap() {
|
||||
ValueEnum::Static(v) => v.get_field(*attr, ctx).map_or_else(|| {
|
||||
let v = v.to_basic_value_enum(ctx, generator)?;
|
||||
let v = v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?;
|
||||
let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
|
||||
Ok(ValueEnum::Dynamic(ctx.build_gep_and_load(
|
||||
v.into_pointer_value(),
|
||||
|
@ -1104,7 +1085,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let left = generator
|
||||
.gen_expr(ctx, &values[0])?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())?
|
||||
.into_int_value();
|
||||
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
|
||||
let a_bb = ctx.ctx.append_basic_block(current, "a");
|
||||
|
@ -1120,7 +1101,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let b = generator
|
||||
.gen_expr(ctx, &values[1])?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
|
||||
.into_int_value();
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
(a, b)
|
||||
|
@ -1130,7 +1111,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let a = generator
|
||||
.gen_expr(ctx, &values[1])?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
|
||||
.into_int_value();
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
ctx.builder.position_at_end(b_bb);
|
||||
|
@ -1148,7 +1129,9 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
ExprKind::UnaryOp { op, operand } => {
|
||||
let ty = ctx.unifier.get_representative(operand.custom.unwrap());
|
||||
let val =
|
||||
generator.gen_expr(ctx, operand)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
generator.gen_expr(ctx, operand)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?;
|
||||
if ty == ctx.primitives.bool {
|
||||
let val = val.into_int_value();
|
||||
match op {
|
||||
|
@ -1208,11 +1191,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
generator
|
||||
.gen_expr(ctx, lhs)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?,
|
||||
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
|
||||
generator
|
||||
.gen_expr(ctx, rhs)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?,
|
||||
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
|
||||
) {
|
||||
(lhs, rhs)
|
||||
} else {
|
||||
|
@ -1236,11 +1219,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
generator
|
||||
.gen_expr(ctx, lhs)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?,
|
||||
.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
|
||||
generator
|
||||
.gen_expr(ctx, rhs)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?,
|
||||
.to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?,
|
||||
) {
|
||||
(lhs, rhs)
|
||||
} else {
|
||||
|
@ -1268,7 +1251,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let test = generator
|
||||
.gen_expr(ctx, test)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
|
||||
.into_int_value();
|
||||
let body_ty = body.custom.unwrap();
|
||||
let is_none = ctx.unifier.get_representative(body_ty) == ctx.primitives.none;
|
||||
|
@ -1288,7 +1271,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
match result {
|
||||
None => None,
|
||||
Some(v) => {
|
||||
let a = a.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let a = a.unwrap().to_basic_value_enum(ctx, generator, body.custom.unwrap())?;
|
||||
Some(ctx.builder.build_store(v, a))
|
||||
}
|
||||
};
|
||||
|
@ -1298,7 +1281,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
match result {
|
||||
None => None,
|
||||
Some(v) => {
|
||||
let b = b.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let b = b.unwrap().to_basic_value_enum(ctx, generator, orelse.custom.unwrap())?;
|
||||
Some(ctx.builder.build_store(v, b))
|
||||
}
|
||||
};
|
||||
|
@ -1375,7 +1358,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
if attr == &"unwrap".into()
|
||||
&& id == ctx.primitives.option.get_obj_id(&ctx.unifier)
|
||||
{
|
||||
if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? {
|
||||
if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator, value.custom.unwrap())? {
|
||||
let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null");
|
||||
ctx.make_assert(
|
||||
generator,
|
||||
|
@ -1407,7 +1390,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let v = generator
|
||||
.gen_expr(ctx, value)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let ty = ctx.get_llvm_type(generator, *ty);
|
||||
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value();
|
||||
|
@ -1454,7 +1437,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let raw_index = generator
|
||||
.gen_expr(ctx, slice)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?
|
||||
.into_int_value();
|
||||
let raw_index = ctx.builder.build_int_s_extend(
|
||||
raw_index,
|
||||
|
@ -1495,7 +1478,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let v = generator
|
||||
.gen_expr(ctx, value)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
|
||||
.into_struct_value();
|
||||
let index: u32 =
|
||||
if let ExprKind::Constant { value: ast::Constant::Int(v), .. } = &slice.node {
|
||||
|
|
|
@ -183,7 +183,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
|
|||
let step = generator
|
||||
.gen_expr(ctx, step)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?
|
||||
.into_int_value();
|
||||
// assert step != 0, throw exception if not
|
||||
let not_zero = ctx.builder.build_int_compare(
|
||||
|
@ -261,7 +261,7 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>(
|
|||
ctx.module.add_function(SYMBOL, fn_t, None)
|
||||
});
|
||||
|
||||
let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator, i.custom.unwrap())?;
|
||||
Ok(ctx
|
||||
.builder
|
||||
.build_call(func, &[i.into(), length.into()], "bounded_ind")
|
||||
|
|
|
@ -54,7 +54,11 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
ExprKind::Attribute { value, attr, .. } => {
|
||||
let index = ctx.get_attr_index(value.custom.unwrap(), *attr);
|
||||
let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
value.custom.unwrap(),
|
||||
)?;
|
||||
let ptr = if let BasicValueEnum::PointerValue(v) = val {
|
||||
v
|
||||
} else {
|
||||
|
@ -81,7 +85,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
let v = generator
|
||||
.gen_expr(ctx, value)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let len = ctx
|
||||
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)])
|
||||
|
@ -89,7 +93,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
let raw_index = generator
|
||||
.gen_expr(ctx, slice)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?
|
||||
.into_int_value();
|
||||
let raw_index = ctx.builder.build_int_s_extend(
|
||||
raw_index,
|
||||
|
@ -143,7 +147,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
) -> Result<(), String> {
|
||||
match &target.node {
|
||||
ExprKind::Tuple { elts, .. } => {
|
||||
if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator)? {
|
||||
if let BasicValueEnum::StructValue(v) =
|
||||
value.to_basic_value_enum(ctx, generator, target.custom.unwrap())?
|
||||
{
|
||||
for (i, elt) in elts.iter().enumerate() {
|
||||
let v = ctx
|
||||
.builder
|
||||
|
@ -162,11 +168,13 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
let ls = generator
|
||||
.gen_expr(ctx, ls)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator)?
|
||||
.to_basic_value_enum(ctx, generator, ls.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let (start, end, step) =
|
||||
handle_slice_indices(lower, upper, step, ctx, generator, ls)?;
|
||||
let value = value.to_basic_value_enum(ctx, generator)?.into_pointer_value();
|
||||
let value = value
|
||||
.to_basic_value_enum(ctx, generator, target.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let ty =
|
||||
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(target.custom.unwrap()) {
|
||||
ctx.get_llvm_type(generator, *ty)
|
||||
|
@ -174,15 +182,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
unreachable!()
|
||||
};
|
||||
let src_ind = handle_slice_indices(&None, &None, &None, ctx, generator, value)?;
|
||||
list_slice_assignment(
|
||||
generator,
|
||||
ctx,
|
||||
ty,
|
||||
ls,
|
||||
(start, end, step),
|
||||
value,
|
||||
src_ind,
|
||||
)
|
||||
list_slice_assignment(generator, ctx, ty, ls, (start, end, step), value, src_ind)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
*static_value = Some(s.clone());
|
||||
}
|
||||
}
|
||||
let val = value.to_basic_value_enum(ctx, generator)?;
|
||||
let val = value.to_basic_value_enum(ctx, generator, target.custom.unwrap())?;
|
||||
ctx.builder.build_store(ptr, val);
|
||||
}
|
||||
};
|
||||
|
@ -226,7 +226,11 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
|||
// store loop bb information and restore it later
|
||||
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
|
||||
|
||||
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
iter.custom.unwrap(),
|
||||
)?;
|
||||
if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) {
|
||||
// setup
|
||||
let iter_val = iter_val.into_pointer_value();
|
||||
|
@ -339,7 +343,11 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
|||
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
ctx.builder.position_at_end(test_bb);
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
test.custom.unwrap(),
|
||||
)?;
|
||||
if let BasicValueEnum::IntValue(test) = test {
|
||||
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||
} else {
|
||||
|
@ -400,7 +408,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
|
|||
};
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
ctx.builder.position_at_end(test_bb);
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
test.custom.unwrap(),
|
||||
)?;
|
||||
if let BasicValueEnum::IntValue(test) = test {
|
||||
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||
} else {
|
||||
|
@ -497,7 +509,7 @@ pub fn exn_constructor<'ctx, 'a>(
|
|||
generator: &mut dyn CodeGenerator,
|
||||
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||
let (zelf_ty, zelf) = obj.unwrap();
|
||||
let zelf = zelf.to_basic_value_enum(ctx, generator)?.into_pointer_value();
|
||||
let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value();
|
||||
let int32 = ctx.ctx.i32_type();
|
||||
let zero = int32.const_zero();
|
||||
let zelf_id = {
|
||||
|
@ -520,14 +532,14 @@ pub fn exn_constructor<'ctx, 'a>(
|
|||
let ptr =
|
||||
ctx.builder.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg");
|
||||
let msg = if !args.is_empty() {
|
||||
args.remove(0).1.to_basic_value_enum(ctx, generator)?
|
||||
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)?
|
||||
} else {
|
||||
empty_string
|
||||
};
|
||||
ctx.builder.build_store(ptr, msg);
|
||||
for i in [6, 7, 8].iter() {
|
||||
let value = if !args.is_empty() {
|
||||
args.remove(0).1.to_basic_value_enum(ctx, generator)?
|
||||
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.int64)?
|
||||
} else {
|
||||
ctx.ctx.i64_type().const_zero().into()
|
||||
};
|
||||
|
@ -949,7 +961,11 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
|
|||
) -> Result<(), String> {
|
||||
let value = value
|
||||
.as_ref()
|
||||
.map(|v| generator.gen_expr(ctx, v).and_then(|v| v.unwrap().to_basic_value_enum(ctx, generator)))
|
||||
.map(|v_expr| {
|
||||
generator.gen_expr(ctx, v_expr).and_then(|v| {
|
||||
v.unwrap().to_basic_value_enum(ctx, generator, v_expr.custom.unwrap())
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
if let Some(return_target) = ctx.return_target {
|
||||
if let Some(value) = value {
|
||||
|
@ -1010,20 +1026,28 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
|
|||
StmtKind::Try { .. } => gen_try(generator, ctx, stmt)?,
|
||||
StmtKind::Raise { exc, .. } => {
|
||||
if let Some(exc) = exc {
|
||||
let exc =
|
||||
generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let exc = generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
exc.custom.unwrap(),
|
||||
)?;
|
||||
gen_raise(generator, ctx, Some(&exc), stmt.location);
|
||||
} else {
|
||||
gen_raise(generator, ctx, None, stmt.location);
|
||||
}
|
||||
}
|
||||
StmtKind::Assert { test, msg, .. } => {
|
||||
let test =
|
||||
generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?;
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
test.custom.unwrap(),
|
||||
)?;
|
||||
let err_msg = match msg {
|
||||
Some(msg) => {
|
||||
generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum(ctx, generator)?
|
||||
}
|
||||
Some(msg) => generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
msg.custom.unwrap(),
|
||||
)?,
|
||||
None => ctx.gen_string(generator, ""),
|
||||
};
|
||||
ctx.make_assert_impl(
|
||||
|
|
|
@ -71,6 +71,7 @@ pub trait StaticValue {
|
|||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String>;
|
||||
|
||||
fn get_field<'ctx, 'a>(
|
||||
|
@ -121,9 +122,10 @@ impl<'ctx> ValueEnum<'ctx> {
|
|||
self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
match self {
|
||||
ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator),
|
||||
ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator, expected_ty),
|
||||
ValueEnum::Dynamic(v) => Ok(v),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,7 +224,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, obj, _, _, generator| {
|
||||
let obj_val = obj.unwrap().1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let expect_ty = obj.clone().unwrap().0;
|
||||
let obj_val = obj.unwrap().1.clone().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
expect_ty,
|
||||
)?;
|
||||
if let BasicValueEnum::PointerValue(ptr) = obj_val {
|
||||
Ok(Some(ctx.builder.build_is_not_null(ptr, "is_some").into()))
|
||||
} else {
|
||||
|
@ -244,7 +249,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, obj, _, _, generator| {
|
||||
let obj_val = obj.unwrap().1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let expect_ty = obj.clone().unwrap().0;
|
||||
let obj_val = obj.unwrap().1.clone().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
expect_ty,
|
||||
)?;
|
||||
if let BasicValueEnum::PointerValue(ptr) = obj_val {
|
||||
Ok(Some(ctx.builder.build_is_null(ptr, "is_none").into()))
|
||||
} else {
|
||||
|
@ -290,7 +300,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let float = ctx.primitives.float;
|
||||
let boolean = ctx.primitives.bool;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
Ok(if ctx.unifier.unioned(arg_ty, boolean) {
|
||||
Some(
|
||||
ctx.builder
|
||||
|
@ -355,7 +365,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let float = ctx.primitives.float;
|
||||
let boolean = ctx.primitives.bool;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
Ok(
|
||||
if ctx.unifier.unioned(arg_ty, boolean)
|
||||
|| ctx.unifier.unioned(arg_ty, uint32)
|
||||
|
@ -422,7 +432,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let float = ctx.primitives.float;
|
||||
let boolean = ctx.primitives.bool;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
let res = if ctx.unifier.unioned(arg_ty, boolean) {
|
||||
ctx.builder
|
||||
.build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext")
|
||||
|
@ -474,7 +484,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let float = ctx.primitives.float;
|
||||
let boolean = ctx.primitives.bool;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
let res = if ctx.unifier.unioned(arg_ty, int32)
|
||||
|| ctx.unifier.unioned(arg_ty, uint32)
|
||||
|| ctx.unifier.unioned(arg_ty, boolean)
|
||||
|
@ -521,7 +531,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let boolean = ctx.primitives.bool;
|
||||
let float = ctx.primitives.float;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
Ok(
|
||||
if ctx.unifier.unioned(arg_ty, boolean)
|
||||
|| ctx.unifier.unioned(arg_ty, int32)
|
||||
|
@ -557,7 +567,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let round_intrinsic =
|
||||
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -597,7 +607,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let round_intrinsic =
|
||||
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -655,19 +665,20 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let mut step = None;
|
||||
let int32 = ctx.ctx.i32_type();
|
||||
let zero = int32.const_zero();
|
||||
let ty_i32 = ctx.primitives.int32;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
if arg.0 == Some("start".into()) {
|
||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
} else if arg.0 == Some("stop".into()) {
|
||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
} else if arg.0 == Some("step".into()) {
|
||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
} else if i == 0 {
|
||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
} else if i == 1 {
|
||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
} else if i == 2 {
|
||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?);
|
||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
||||
}
|
||||
}
|
||||
let step = match step {
|
||||
|
@ -734,8 +745,9 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator)?))
|
||||
|ctx, _, fun, args, generator| {
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?))
|
||||
},
|
||||
)))),
|
||||
loc: None,
|
||||
|
@ -759,7 +771,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let float = ctx.primitives.float;
|
||||
let boolean = ctx.primitives.bool;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
Ok(if ctx.unifier.unioned(arg_ty, boolean) {
|
||||
Some(arg)
|
||||
} else if ctx.unifier.unioned(arg_ty, int32) {
|
||||
|
@ -817,7 +829,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let floor_intrinsic =
|
||||
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -857,7 +869,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let floor_intrinsic =
|
||||
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -897,7 +909,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let ceil_intrinsic =
|
||||
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -937,7 +949,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _, args, generator| {
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?;
|
||||
let ceil_intrinsic =
|
||||
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
||||
let float = ctx.ctx.f64_type();
|
||||
|
@ -989,7 +1001,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
|ctx, _, fun, args, generator| {
|
||||
let range_ty = ctx.primitives.range;
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
Ok(if ctx.unifier.unioned(arg_ty, range_ty) {
|
||||
let arg = arg.into_pointer_value();
|
||||
let (start, end, step) = destructure_range(ctx, arg);
|
||||
|
@ -1043,8 +1055,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum();
|
||||
let m_ty = fun.0.args[0].ty;
|
||||
let n_ty = fun.0.args[1].ty;
|
||||
let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator, m_ty)?;
|
||||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?;
|
||||
let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b);
|
||||
let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) {
|
||||
("llvm.umin.i1", llvm_i1)
|
||||
|
@ -1105,8 +1117,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum();
|
||||
let m_ty = fun.0.args[0].ty;
|
||||
let n_ty = fun.0.args[1].ty;
|
||||
let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator, m_ty)?;
|
||||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?;
|
||||
let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b);
|
||||
let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) {
|
||||
("llvm.umax.i1", llvm_i1)
|
||||
|
@ -1163,7 +1175,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let llvm_i64 = ctx.ctx.i64_type().as_basic_type_enum();
|
||||
let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum();
|
||||
let n_ty = fun.0.args[0].ty;
|
||||
let n_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
let n_val = args[0].1.clone().to_basic_value_enum(ctx, generator, n_ty)?;
|
||||
let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b);
|
||||
let mut is_float = false;
|
||||
let (fun_name, arg_ty) =
|
||||
|
@ -1220,8 +1232,9 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, _, _fun, args, generator| {
|
||||
let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?;
|
||||
|ctx, _, fun, args, generator| {
|
||||
let arg_ty = fun.0.args[0].ty;
|
||||
let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
|
||||
let alloca = ctx.builder.build_alloca(arg_val.get_type(), "alloca_some");
|
||||
ctx.builder.build_store(alloca, arg_val);
|
||||
Ok(Some(alloca.into()))
|
||||
|
|
Loading…
Reference in New Issue