mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 11:22:19 +00:00
for referenced values, use allocas instead of phi nodes
This commit is contained in:
parent
ee7f1e39c7
commit
c5a74bdc12
3 changed files with 87 additions and 16 deletions
|
@ -3292,14 +3292,18 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
layout_interner.get_repr(param.layout),
|
||||
);
|
||||
|
||||
let phi_type = if layout_interner.is_passed_by_reference(param.layout) {
|
||||
basic_type.ptr_type(AddressSpace::default()).into()
|
||||
use crate::llvm::scope::JoinPointArg::*;
|
||||
let joinpoint_arg = if layout_interner.is_passed_by_reference(param.layout) {
|
||||
Alloca(create_entry_block_alloca(
|
||||
env,
|
||||
basic_type,
|
||||
"joinpoint_arg_alloca",
|
||||
))
|
||||
} else {
|
||||
basic_type
|
||||
Phi(env.builder.new_build_phi(basic_type, "joinpointarg"))
|
||||
};
|
||||
|
||||
let phi_node = env.builder.new_build_phi(phi_type, "joinpointarg");
|
||||
joinpoint_args.push(phi_node);
|
||||
joinpoint_args.push(joinpoint_arg);
|
||||
}
|
||||
|
||||
builder.position_at_end(current);
|
||||
|
@ -3351,14 +3355,30 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
Jump(join_point, arguments) => {
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
let (cont_block, argument_phi_values) = scope.get_join_point(*join_point).unwrap();
|
||||
let (cont_block, joinpoint_args) = scope.get_join_point(*join_point).unwrap();
|
||||
|
||||
let current_block = builder.get_insert_block().unwrap();
|
||||
|
||||
for (phi_value, argument) in argument_phi_values.iter().zip(arguments.iter()) {
|
||||
let (value, _) = scope.load_symbol_and_layout(argument);
|
||||
for (joinpoint_arg, argument) in joinpoint_args.iter().zip(arguments.iter()) {
|
||||
let (value, layout) = scope.load_symbol_and_layout(argument);
|
||||
|
||||
phi_value.add_incoming(&[(&value, current_block)]);
|
||||
match joinpoint_arg {
|
||||
crate::llvm::scope::JoinPointArg::Alloca(alloca) => {
|
||||
let (size, alignment) = layout_interner.stack_size_and_alignment(layout);
|
||||
builder
|
||||
.build_memcpy(
|
||||
*alloca,
|
||||
alignment,
|
||||
value.into_pointer_value(),
|
||||
alignment,
|
||||
env.ptr_int().const_int(size as _, false),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
crate::llvm::scope::JoinPointArg::Phi(phi) => {
|
||||
phi.add_incoming(&[(&value, current_block)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.new_build_unconditional_branch(*cont_block);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use inkwell::{
|
||||
basic_block::BasicBlock,
|
||||
values::{BasicValueEnum, FunctionValue, PhiValue},
|
||||
values::{BasicValue, BasicValueEnum, FunctionValue, PhiValue, PointerValue},
|
||||
};
|
||||
use roc_collections::ImMap;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
|
@ -13,12 +13,18 @@ use roc_mono::{
|
|||
pub(crate) struct Scope<'a, 'ctx> {
|
||||
symbols: ImMap<Symbol, (InLayout<'a>, BasicValueEnum<'ctx>)>,
|
||||
top_level_thunks: ImMap<Symbol, (ProcLayout<'a>, FunctionValue<'ctx>)>,
|
||||
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, Vec<PhiValue<'ctx>>)>,
|
||||
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, Vec<JoinPointArg<'ctx>>)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct JoinPointNotFound;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) enum JoinPointArg<'ctx> {
|
||||
Alloca(PointerValue<'ctx>),
|
||||
Phi(PhiValue<'ctx>),
|
||||
}
|
||||
|
||||
impl<'a, 'ctx> Scope<'a, 'ctx> {
|
||||
pub fn insert(&mut self, symbol: Symbol, layout: InLayout<'a>, value: BasicValueEnum<'ctx>) {
|
||||
self.symbols.insert(symbol, (layout, value));
|
||||
|
@ -62,7 +68,7 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
|
|||
&mut self,
|
||||
join_point_id: JoinPointId,
|
||||
bb: BasicBlock<'ctx>,
|
||||
phis: Vec<PhiValue<'ctx>>,
|
||||
phis: Vec<JoinPointArg<'ctx>>,
|
||||
) {
|
||||
self.join_points.insert(join_point_id, (bb, phis));
|
||||
}
|
||||
|
@ -74,7 +80,7 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
|
|||
pub fn get_join_point(
|
||||
&self,
|
||||
join_point_id: JoinPointId,
|
||||
) -> Option<&(BasicBlock<'ctx>, Vec<PhiValue<'ctx>>)> {
|
||||
) -> Option<&(BasicBlock<'ctx>, Vec<JoinPointArg<'ctx>>)> {
|
||||
self.join_points.get(&join_point_id)
|
||||
}
|
||||
|
||||
|
@ -89,9 +95,17 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
|
|||
.ok_or(JoinPointNotFound)?
|
||||
.1;
|
||||
|
||||
for (phi_value, param) in ref_join_points.iter().zip(parameters.into_iter()) {
|
||||
let value = phi_value.as_basic_value();
|
||||
self.symbols.insert(param.symbol, (param.layout, value));
|
||||
for (joinpoint_arg, param) in ref_join_points.iter().zip(parameters.into_iter()) {
|
||||
match joinpoint_arg {
|
||||
crate::llvm::scope::JoinPointArg::Alloca(alloca) => {
|
||||
self.symbols
|
||||
.insert(param.symbol, (param.layout, alloca.as_basic_value_enum()));
|
||||
}
|
||||
crate::llvm::scope::JoinPointArg::Phi(phi) => {
|
||||
self.symbols
|
||||
.insert(param.symbol, (param.layout, phi.as_basic_value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -4664,3 +4664,40 @@ fn multiple_uses_of_bool_true_tag_union() {
|
|||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn issue_6139() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
buggy = \node, seen ->
|
||||
if List.contains seen node then
|
||||
seen
|
||||
else
|
||||
# node = "B"
|
||||
nextNode = stepNode node
|
||||
|
||||
# node = "C"
|
||||
buggy nextNode (List.append seen node)
|
||||
|
||||
stepNode = \node ->
|
||||
when node is
|
||||
"A" -> "B"
|
||||
"B" -> "C"
|
||||
"C" -> "D"
|
||||
"D" -> "A"
|
||||
_ -> crash ""
|
||||
|
||||
buggy "A" []
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&[
|
||||
RocStr::from("A"),
|
||||
RocStr::from("B"),
|
||||
RocStr::from("C"),
|
||||
RocStr::from("D"),
|
||||
]),
|
||||
RocList<RocStr>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue