Make codegen return StackValues instead of instructions
This commit is contained in:
parent
bcad156ef0
commit
d64cf750b1
@ -99,21 +99,42 @@ pub struct StackFunction<'ctx> {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct StackValue(StackValueKind, TypeKind);
|
pub struct StackValue(StackValueKind, TypeKind);
|
||||||
|
|
||||||
|
impl StackValue {
|
||||||
|
fn instr(&self) -> InstructionValue {
|
||||||
|
self.0.instr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum StackValueKind {
|
pub enum StackValueKind {
|
||||||
Immutable(InstructionValue),
|
Immutable(InstructionValue),
|
||||||
Mutable(InstructionValue),
|
Mutable(InstructionValue),
|
||||||
Any(InstructionValue),
|
Literal(InstructionValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackValueKind {
|
impl StackValueKind {
|
||||||
unsafe fn get_inner(&self) -> InstructionValue {
|
fn instr(&self) -> InstructionValue {
|
||||||
match &self {
|
match &self {
|
||||||
StackValueKind::Immutable(val) => *val,
|
StackValueKind::Immutable(val) => *val,
|
||||||
StackValueKind::Mutable(val) => *val,
|
StackValueKind::Mutable(val) => *val,
|
||||||
StackValueKind::Any(val) => *val,
|
StackValueKind::Literal(val) => *val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn derive(&self, instr: InstructionValue) -> StackValueKind {
|
||||||
|
match &self {
|
||||||
|
StackValueKind::Immutable(_) => StackValueKind::Immutable(instr),
|
||||||
|
StackValueKind::Mutable(_) => StackValueKind::Mutable(instr),
|
||||||
|
StackValueKind::Literal(_) => StackValueKind::Literal(instr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map<F>(&self, lambda: F) -> StackValueKind
|
||||||
|
where
|
||||||
|
F: FnOnce(InstructionValue) -> InstructionValue,
|
||||||
|
{
|
||||||
|
self.derive(lambda(self.instr()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, 'a> Scope<'ctx, 'a> {
|
impl<'ctx, 'a> Scope<'ctx, 'a> {
|
||||||
@ -369,7 +390,7 @@ impl mir::Module {
|
|||||||
mir::FunctionDefinitionKind::Local(block, _) => {
|
mir::FunctionDefinitionKind::Local(block, _) => {
|
||||||
let state = State::default();
|
let state = State::default();
|
||||||
if let Some(ret) = block.codegen(&mut scope, &state) {
|
if let Some(ret) = block.codegen(&mut scope, &state) {
|
||||||
scope.block.terminate(Term::Ret(ret)).unwrap();
|
scope.block.terminate(Term::Ret(ret.instr())).unwrap();
|
||||||
} else {
|
} else {
|
||||||
if !scope.block.delete_if_unused().unwrap() {
|
if !scope.block.delete_if_unused().unwrap() {
|
||||||
// Add a void return just in case if the block
|
// Add a void return just in case if the block
|
||||||
@ -397,13 +418,13 @@ impl mir::Block {
|
|||||||
&self,
|
&self,
|
||||||
mut scope: &mut Scope<'ctx, 'a>,
|
mut scope: &mut Scope<'ctx, 'a>,
|
||||||
state: &State,
|
state: &State,
|
||||||
) -> Option<InstructionValue> {
|
) -> Option<StackValue> {
|
||||||
for stmt in &self.statements {
|
for stmt in &self.statements {
|
||||||
stmt.codegen(&mut scope, state).map(|s| {
|
stmt.codegen(&mut scope, state).map(|s| {
|
||||||
if let Some(debug) = &scope.debug {
|
if let Some(debug) = &scope.debug {
|
||||||
let location = stmt.1.into_debug(scope.tokens).unwrap();
|
let location = stmt.1.into_debug(scope.tokens).unwrap();
|
||||||
let loc_val = debug.info.location(&debug.scope, location);
|
let loc_val = debug.info.location(&debug.scope, location);
|
||||||
s.with_location(&mut scope.block, loc_val);
|
s.instr().with_location(&mut scope.block, loc_val);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -412,7 +433,7 @@ impl mir::Block {
|
|||||||
match kind {
|
match kind {
|
||||||
mir::ReturnKind::Hard => {
|
mir::ReturnKind::Hard => {
|
||||||
let ret = expr.codegen(&mut scope, &state)?;
|
let ret = expr.codegen(&mut scope, &state)?;
|
||||||
scope.block.terminate(Term::Ret(ret)).unwrap();
|
scope.block.terminate(Term::Ret(ret.instr())).unwrap();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
mir::ReturnKind::Soft => expr.codegen(&mut scope, state),
|
mir::ReturnKind::Soft => expr.codegen(&mut scope, state),
|
||||||
@ -424,11 +445,7 @@ impl mir::Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Statement {
|
impl mir::Statement {
|
||||||
fn codegen<'ctx, 'a>(
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> {
|
||||||
&self,
|
|
||||||
scope: &mut Scope<'ctx, 'a>,
|
|
||||||
state: &State,
|
|
||||||
) -> Option<InstructionValue> {
|
|
||||||
let location = self.1.into_debug(scope.tokens).unwrap();
|
let location = self.1.into_debug(scope.tokens).unwrap();
|
||||||
let location = scope
|
let location = scope
|
||||||
.debug
|
.debug
|
||||||
@ -450,7 +467,7 @@ impl mir::Statement {
|
|||||||
|
|
||||||
let store = scope
|
let store = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Store(alloca, value))
|
.build(Instr::Store(alloca, value.instr()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
@ -483,12 +500,12 @@ impl mir::Statement {
|
|||||||
InstructionDebugRecordData {
|
InstructionDebugRecordData {
|
||||||
variable: var,
|
variable: var,
|
||||||
location,
|
location,
|
||||||
kind: DebugRecordKind::Declare(value),
|
kind: DebugRecordKind::Declare(value.instr()),
|
||||||
scope: debug.scope,
|
scope: debug.scope,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
StackValueKind::Any(_) => {}
|
StackValueKind::Literal(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -500,13 +517,23 @@ impl mir::Statement {
|
|||||||
|
|
||||||
let rhs_value = rhs.codegen(scope, state)?;
|
let rhs_value = rhs.codegen(scope, state)?;
|
||||||
|
|
||||||
Some(
|
match lhs_value.0 {
|
||||||
|
StackValueKind::Immutable(_) => {
|
||||||
|
panic!("Tried to assign to immutable!")
|
||||||
|
}
|
||||||
|
StackValueKind::Mutable(instr) => {
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Store(lhs_value, rhs_value))
|
.build(Instr::Store(instr, rhs_value.instr()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location),
|
.maybe_location(&mut scope.block, location);
|
||||||
)
|
}
|
||||||
|
StackValueKind::Literal(_) => {
|
||||||
|
panic!("Tried to assign to a literal!")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
mir::StmtKind::Import(_) => todo!(),
|
mir::StmtKind::Import(_) => todo!(),
|
||||||
mir::StmtKind::Expression(expression) => expression.codegen(scope, state),
|
mir::StmtKind::Expression(expression) => expression.codegen(scope, state),
|
||||||
@ -515,11 +542,7 @@ impl mir::Statement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl mir::Expression {
|
impl mir::Expression {
|
||||||
fn codegen<'ctx, 'a>(
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> {
|
||||||
&self,
|
|
||||||
scope: &mut Scope<'ctx, 'a>,
|
|
||||||
state: &State,
|
|
||||||
) -> Option<InstructionValue> {
|
|
||||||
let location = if let Some(debug) = &scope.debug {
|
let location = if let Some(debug) = &scope.debug {
|
||||||
Some(
|
Some(
|
||||||
debug
|
debug
|
||||||
@ -530,7 +553,7 @@ impl mir::Expression {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
match &self.0 {
|
let value = match &self.0 {
|
||||||
mir::ExprKind::Variable(varref) => {
|
mir::ExprKind::Variable(varref) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
varref.0.known().expect("variable type unknown");
|
||||||
let v = scope
|
let v = scope
|
||||||
@ -538,18 +561,23 @@ impl mir::Expression {
|
|||||||
.get(&varref.1)
|
.get(&varref.1)
|
||||||
.expect("Variable reference not found?!");
|
.expect("Variable reference not found?!");
|
||||||
dbg!(varref);
|
dbg!(varref);
|
||||||
Some(match v.0 {
|
Some(StackValue(
|
||||||
StackValueKind::Immutable(val) | StackValueKind::Mutable(val) => scope
|
v.0.map(|val| {
|
||||||
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Load(
|
.build(Instr::Load(
|
||||||
val,
|
val,
|
||||||
v.1.get_type(scope.type_values, scope.types),
|
v.1.get_type(scope.type_values, scope.types),
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap()
|
||||||
_ => panic!("Found an unknown-mutable variable!"),
|
}),
|
||||||
})
|
varref.0.clone(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Literal(lit) => Some(lit.as_const(&mut scope.block)),
|
mir::ExprKind::Literal(lit) => Some(StackValue(
|
||||||
|
StackValueKind::Literal(lit.as_const(&mut scope.block)),
|
||||||
|
lit.as_type(),
|
||||||
|
)),
|
||||||
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
|
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
|
||||||
lhs_exp
|
lhs_exp
|
||||||
.return_type()
|
.return_type()
|
||||||
@ -566,41 +594,58 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let lhs = lhs_exp
|
let lhs = lhs_exp
|
||||||
.codegen(scope, state)
|
.codegen(scope, state)
|
||||||
.expect("lhs has no return value");
|
.expect("lhs has no return value")
|
||||||
|
.instr();
|
||||||
let rhs = rhs_exp
|
let rhs = rhs_exp
|
||||||
.codegen(scope, state)
|
.codegen(scope, state)
|
||||||
.expect("rhs has no return value");
|
.expect("rhs has no return value")
|
||||||
Some(match binop {
|
.instr();
|
||||||
mir::BinaryOperator::Add => scope.block.build(Instr::Add(lhs, rhs)).unwrap(),
|
Some(StackValue(
|
||||||
mir::BinaryOperator::Minus => scope.block.build(Instr::Sub(lhs, rhs)).unwrap(),
|
StackValueKind::Immutable(match binop {
|
||||||
mir::BinaryOperator::Mult => scope.block.build(Instr::Mult(lhs, rhs)).unwrap(),
|
mir::BinaryOperator::Add => {
|
||||||
mir::BinaryOperator::And => scope.block.build(Instr::And(lhs, rhs)).unwrap(),
|
scope.block.build(Instr::Add(lhs, rhs)).unwrap()
|
||||||
|
}
|
||||||
|
mir::BinaryOperator::Minus => {
|
||||||
|
scope.block.build(Instr::Sub(lhs, rhs)).unwrap()
|
||||||
|
}
|
||||||
|
mir::BinaryOperator::Mult => {
|
||||||
|
scope.block.build(Instr::Mult(lhs, rhs)).unwrap()
|
||||||
|
}
|
||||||
|
mir::BinaryOperator::And => {
|
||||||
|
scope.block.build(Instr::And(lhs, rhs)).unwrap()
|
||||||
|
}
|
||||||
mir::BinaryOperator::Cmp(l) => scope
|
mir::BinaryOperator::Cmp(l) => scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::ICmp(l.int_predicate(), lhs, rhs))
|
.build(Instr::ICmp(l.int_predicate(), lhs, rhs))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
})
|
}),
|
||||||
|
TypeKind::U32,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::FunctionCall(call) => {
|
mir::ExprKind::FunctionCall(call) => {
|
||||||
call.return_type
|
let ret_type = call
|
||||||
|
.return_type
|
||||||
.known()
|
.known()
|
||||||
.expect("function return type unknown");
|
.expect("function return type unknown");
|
||||||
|
|
||||||
let params = call
|
let params = call
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.codegen(scope, state).unwrap())
|
.map(|e| e.codegen(scope, state).unwrap().instr())
|
||||||
.collect();
|
.collect();
|
||||||
let callee = scope
|
let callee = scope
|
||||||
.functions
|
.functions
|
||||||
.get(&call.name)
|
.get(&call.name)
|
||||||
.expect("function not found!");
|
.expect("function not found!");
|
||||||
Some(
|
Some(StackValue(
|
||||||
|
StackValueKind::Immutable(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::FunctionCall(callee.ir.value(), params))
|
.build(Instr::FunctionCall(callee.ir.value(), params))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
),
|
||||||
|
ret_type,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state),
|
mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state),
|
||||||
mir::ExprKind::Block(block) => {
|
mir::ExprKind::Block(block) => {
|
||||||
@ -616,16 +661,17 @@ impl mir::Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::ExprKind::Indexed(expression, val_t, idx_expr) => {
|
mir::ExprKind::Indexed(expression, val_t, idx_expr) => {
|
||||||
let array = expression
|
let StackValue(kind, ty) = expression
|
||||||
.codegen(scope, &state.load(true))
|
.codegen(scope, &state.load(true))
|
||||||
.expect("array returned none!");
|
.expect("array returned none!");
|
||||||
let idx = idx_expr
|
let idx = idx_expr
|
||||||
.codegen(scope, &state.load(true))
|
.codegen(scope, &state.load(true))
|
||||||
.expect("index returned none!");
|
.expect("index returned none!")
|
||||||
|
.instr();
|
||||||
|
|
||||||
let mut ptr = scope
|
let mut ptr = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::GetElemPtr(array, vec![idx]))
|
.build(Instr::GetElemPtr(kind.instr(), vec![idx]))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
@ -640,16 +686,25 @@ impl mir::Expression {
|
|||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ptr)
|
let TypeKind::Array(elem_ty, _) = ty else {
|
||||||
|
panic!();
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(StackValue(kind.derive(ptr), *elem_ty))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Array(expressions) => {
|
mir::ExprKind::Array(expressions) => {
|
||||||
let instr_list = expressions
|
let stack_value_list = expressions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.codegen(scope, state).unwrap())
|
.map(|e| e.codegen(scope, state).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let instr_t = expressions
|
let instr_list = stack_value_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.return_type().unwrap().1)
|
.map(|s| s.instr())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let instr_t = stack_value_list
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.1.clone())
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or(TypeKind::Void);
|
.unwrap_or(TypeKind::Void);
|
||||||
|
|
||||||
@ -679,28 +734,27 @@ impl mir::Expression {
|
|||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(array)
|
Some(StackValue(
|
||||||
|
StackValueKind::Literal(array),
|
||||||
|
TypeKind::Array(Box::new(instr_t), instr_list.len() as u64),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Accessed(expression, type_kind, field) => {
|
mir::ExprKind::Accessed(expression, type_kind, field) => {
|
||||||
let struct_val = expression.codegen(scope, &mut state.load(true)).unwrap();
|
let struct_val = expression.codegen(scope, &mut state.load(true)).unwrap();
|
||||||
|
|
||||||
let struct_ty = expression
|
let TypeKind::CustomType(name) = struct_val.1.deref_borrow() else {
|
||||||
.return_type()
|
|
||||||
.map(|r| r.1.known())
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let TypeKind::CustomType(name) = struct_ty.deref_borrow() else {
|
|
||||||
panic!("tried accessing non-custom-type");
|
panic!("tried accessing non-custom-type");
|
||||||
};
|
};
|
||||||
let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&name).unwrap();
|
let TypeDefinitionKind::Struct(struct_ty) =
|
||||||
|
scope.get_typedef(&name).unwrap().clone();
|
||||||
let idx = struct_ty.find_index(field).unwrap();
|
let idx = struct_ty.find_index(field).unwrap();
|
||||||
|
|
||||||
let mut value = scope
|
let mut value = scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::GetStructElemPtr(struct_val, idx as u32))
|
.build(Instr::GetStructElemPtr(struct_val.instr(), idx as u32))
|
||||||
.unwrap()
|
.unwrap();
|
||||||
.maybe_location(&mut scope.block, location);
|
|
||||||
|
// value.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
if state.should_load {
|
if state.should_load {
|
||||||
value = scope
|
value = scope
|
||||||
@ -712,7 +766,10 @@ impl mir::Expression {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(value)
|
Some(StackValue(
|
||||||
|
struct_val.0.derive(value),
|
||||||
|
struct_ty.get_field_ty(&field).unwrap().clone(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Struct(name, items) => {
|
mir::ExprKind::Struct(name, items) => {
|
||||||
let struct_ptr = scope
|
let struct_ptr = scope
|
||||||
@ -733,25 +790,27 @@ impl mir::Expression {
|
|||||||
if let Some(val) = exp.codegen(scope, state) {
|
if let Some(val) = exp.codegen(scope, state) {
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build(Instr::Store(elem_ptr, val))
|
.build(Instr::Store(elem_ptr, val.instr()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(struct_ptr)
|
Some(StackValue(
|
||||||
|
StackValueKind::Literal(struct_ptr),
|
||||||
|
TypeKind::CustomType(name.clone()),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if let Some(value) = &value {
|
||||||
|
value.instr().maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
.map(|i| i.maybe_location(&mut scope.block, location))
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl mir::IfExpression {
|
impl mir::IfExpression {
|
||||||
fn codegen<'ctx, 'a>(
|
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Option<StackValue> {
|
||||||
&self,
|
|
||||||
scope: &mut Scope<'ctx, 'a>,
|
|
||||||
state: &State,
|
|
||||||
) -> Option<InstructionValue> {
|
|
||||||
let condition = self.0.codegen(scope, state).unwrap();
|
let condition = self.0.codegen(scope, state).unwrap();
|
||||||
|
|
||||||
// Create blocks
|
// Create blocks
|
||||||
@ -792,7 +851,7 @@ impl mir::IfExpression {
|
|||||||
|
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.terminate(Term::CondBr(condition, then_bb, else_bb))
|
.terminate(Term::CondBr(condition.instr(), then_bb, else_bb))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let opt = else_block.codegen(&mut else_scope, state);
|
let opt = else_block.codegen(&mut else_scope, state);
|
||||||
@ -807,7 +866,7 @@ impl mir::IfExpression {
|
|||||||
else_b.terminate(Term::Br(after_bb)).unwrap();
|
else_b.terminate(Term::Br(after_bb)).unwrap();
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.terminate(Term::CondBr(condition, then_bb, after_bb))
|
.terminate(Term::CondBr(condition.instr(), then_bb, after_bb))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -819,8 +878,29 @@ impl mir::IfExpression {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut incoming = Vec::from(then_res.as_slice());
|
let mut incoming = Vec::from(then_res.as_slice());
|
||||||
incoming.extend(else_res);
|
incoming.extend(else_res.clone());
|
||||||
Some(scope.block.build(Instr::Phi(incoming)).unwrap())
|
let instr = scope
|
||||||
|
.block
|
||||||
|
.build(Instr::Phi(incoming.iter().map(|i| i.instr()).collect()))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
use StackValueKind::*;
|
||||||
|
let value = match (then_res, else_res) {
|
||||||
|
(None, None) => StackValue(StackValueKind::Immutable(instr), TypeKind::Void),
|
||||||
|
(Some(val), None) | (None, Some(val)) => StackValue(val.0.derive(instr), val.1),
|
||||||
|
(Some(lhs_val), Some(rhs_val)) => match (lhs_val.0, rhs_val.0) {
|
||||||
|
(Immutable(_), Immutable(_))
|
||||||
|
| (Immutable(_), Mutable(_))
|
||||||
|
| (Mutable(_), Immutable(_))
|
||||||
|
| (Immutable(_), Literal(_))
|
||||||
|
| (Literal(_), Immutable(_))
|
||||||
|
| (Mutable(_), Literal(_))
|
||||||
|
| (Literal(_), Mutable(_))
|
||||||
|
| (Literal(_), Literal(_)) => StackValue(Immutable(instr), lhs_val.1),
|
||||||
|
(Mutable(_), Mutable(_)) => StackValue(Mutable(instr), lhs_val.1),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Some(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user