calling functions

This commit is contained in:
Janis 2024-09-02 16:03:12 +02:00
parent 4424ef875d
commit 568c3b2fa4
9 changed files with 413 additions and 54 deletions

View file

@ -325,6 +325,16 @@ impl Register {
rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15,
]
};
pub const SYSV_ARG_GPR: [Register; 6] = {
use Register::*;
[rdi, rsi, rdx, rcx, r8, r9]
};
pub const SYSV_ARG_SSE: [Register; 8] = {
use Register::*;
[xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7]
};
pub const SSE: [Register; 16] = {
use Register::*;
[

View file

@ -84,7 +84,7 @@ pub enum Tag {
},
ArgumentList {
/// [Argument]
parameters: Vec<Node>,
arguments: Vec<Node>,
},
Argument {
/// Ident
@ -348,6 +348,13 @@ impl Type {
}
}
pub fn return_type(&self) -> Option<&Type> {
match self {
Self::Fn { return_type, .. } => Some(&return_type),
_ => None,
}
}
pub fn equal_type(&self, rhs: &Self) -> Option<Type> {
match (self, rhs) {
(Self::ComptimeNumber, Self::Floating(_))

View file

@ -181,6 +181,7 @@ impl<'a> TokenIterator<'a> {
pub fn is_next_token(&mut self, token: Token) -> bool {
self.clone().next_if(|item| item.token() == token).is_some()
}
/// looks at the token 2 positions ahead and checks if it is equal to `token`.
pub fn is_next_token2(&mut self, token: Token) -> bool {
self.clone()
.skip(1)

View file

@ -15,6 +15,7 @@ pub mod ast;
pub mod common;
pub mod comptime;
pub mod error;
//pub mod intern_pool;
pub mod lexer;
pub mod mir;
pub mod parser;

View file

@ -148,6 +148,10 @@ pub enum Inst {
/// src, idx,
GetElementPtr(Type),
Parameter(Type),
/// src
Argument(Type),
/// start(func), end
Call(Type),
/// lhs, rhs
Add(Type),
/// lhs, rhs
@ -237,9 +241,11 @@ impl Inst {
| Inst::ConstantDoublePrecision
| Inst::Cmp(_)
| Inst::Branch(_)
| Inst::Argument(_)
| Inst::Jump
| Inst::Return => None,
Inst::Phi2(ty)
| Inst::Call(ty)
| Inst::GetElementPtr(ty)
| Inst::Load(ty)
| Inst::LoadRegister(ty)
@ -281,6 +287,7 @@ impl Inst {
match self {
Inst::Label
| Inst::Branch(_)
| Inst::Argument(_)
| Inst::Jump
| Inst::ConstantBytes
| Inst::ConstantByte
@ -325,6 +332,7 @@ impl Inst {
| Inst::IsGe(_)
| Inst::IsLe(_)
| Inst::Phi2(_)
| Inst::Call(_)
| Inst::ShiftLeft(_)
| Inst::ShiftRightSigned(_)
| Inst::ShiftRightUnsigned(_) => true,
@ -967,6 +975,33 @@ impl Mir {
pub fn gen_param(&mut self, ty: Type) -> u32 {
self.push(Inst::Parameter(ty), Data::none())
}
fn gen_arg(&mut self, ty: Type, src: u32) -> u32 {
self.push(Inst::Argument(ty), Data::node(src))
}
pub fn gen_call(
&mut self,
ty: Type,
func: u32,
args: impl IntoIterator<Item = (Type, u32)>,
) -> u32 {
let args = args
.into_iter()
.map(|(ty, mut arg)| {
if self.is_imm(arg) {
arg = self.gen_load_register(ty, arg);
}
(ty, arg)
})
.collect::<Vec<_>>();
let start = self.gen_arg(ty, func);
for (ty, arg) in args {
self.gen_arg(ty, arg);
}
let end = self.nodes.len() as u32;
self.push(Inst::Call(ty), Data::binary(start, end))
}
/// truncates a value `src` of `mir::Type` `ty` to `bits` bits, while preserving the sign
pub fn gen_truncate_integer(&mut self, src: u32, ty: Type, signed: bool, bits: u16) -> u32 {
@ -1217,6 +1252,17 @@ impl Mir {
Inst::Parameter(ty) => {
writeln!(w, "%{node} = param {ty}")
}
Inst::Argument(_) => Ok(()),
Inst::Call(ty) => {
let (start, end) = data.as_binary();
let func = self.data[start as usize].as_node();
write!(w, "%{node} = {ty} call %{func} (")?;
for arg in (start + 1)..end {
let arg = self.data[arg as usize].as_node();
write!(w, "%{arg}, ")?;
}
writeln!(w, ")")
}
Inst::Add(ty) => {
let (lhs, rhs) = data.as_binary();
writeln!(w, "%{node} = add {ty} %{lhs}, {ty} %{rhs}")
@ -2005,6 +2051,13 @@ impl Mir {
let (src, _) = data.as_binary_noderefs();
references.insert((src, node));
}
Inst::Call(_) => {
let (lhs, rhs) = data.as_binary();
for arg in lhs..rhs {
let arg = self.data[arg as usize].as_noderef();
references.insert((arg, node));
}
}
// these instructions have no inputs
// don't want a wildcard match here to make sure new instructions
// are handled here when they are added.
@ -2020,6 +2073,7 @@ impl Mir {
| Inst::ConstantSinglePrecision
| Inst::ConstantDoublePrecision
| Inst::ExternRef(_)
| Inst::Argument(_)
| Inst::Alloca => {}
}
}
@ -2060,6 +2114,7 @@ impl Mir {
Some(lhs)
}
Inst::Parameter(_)
| Inst::Call(_)
| Inst::GetElementPtr(_)
| Inst::LoadRegister(_)
| Inst::Load(_)
@ -2088,6 +2143,7 @@ impl Mir {
| Inst::Cmp(_)
| Inst::Branch(_)
| Inst::Phi2(_)
| Inst::Argument(_)
| Inst::IsEq(_)
| Inst::IsNeq(_)
| Inst::IsGt(_)
@ -2188,6 +2244,7 @@ impl core::fmt::Display for ImmRegMem {
#[derive(Debug, PartialEq, Eq)]
enum RipRelative {
Reference(String),
Label(Type, String),
#[allow(dead_code)]
Offset(Type, i32),
@ -2196,6 +2253,7 @@ enum RipRelative {
impl RipRelative {
fn ty(&self) -> Type {
match self {
Self::Reference(_) => Type::QWord,
RipRelative::Label(ty, _) => *ty,
RipRelative::Offset(ty, _) => *ty,
}
@ -2205,6 +2263,7 @@ impl RipRelative {
impl core::fmt::Display for RipRelative {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Reference(label) => write!(f, "{label}"),
RipRelative::Label(ty, label) => write!(f, "{} ptr [rip + {label}]", ty.int_repr()),
RipRelative::Offset(ty, offset) => {
write!(f, "{} ptr [rip + {offset}]", ty.int_repr())
@ -2251,7 +2310,7 @@ impl Function {
let mut buf = String::new();
let w = &mut buf;
let name = strings.get_str(self.name).to_owned();
writeln!(w, ".{name}:")?;
writeln!(w, "{name}:")?;
for (_, contents) in self.constants {
writeln!(w, "{contents}")?;
@ -2337,15 +2396,12 @@ impl Function {
writeln!(w, "push {reg}")?;
}
let needs_frame = !saved_registers.is_empty() && self.stack_offset != 0;
if needs_frame {
writeln!(w, "push rbp")?;
writeln!(w, "mov rbp, rsp")?;
if self.stack_offset != 0 {
writeln!(w, "sub rsp, {}", self.stack_offset)?;
}
// zero rax because we might only return into some of it
writeln!(w, "test rax, rax")?;
write!(w, "{}", self.branches.remove(&NodeRef::MIN).unwrap())?;
for (branch, content) in &self.branches {
@ -2355,14 +2411,12 @@ impl Function {
writeln!(w, ".{name}__epilogue:")?;
if needs_frame {
writeln!(w, "mov rsp, rbp")?;
writeln!(w, "pop rbp")?;
for reg in saved_registers.iter().rev() {
writeln!(w, "pop {reg}")?;
}
}
writeln!(w, "ret")?;
@ -2411,6 +2465,7 @@ impl Mir {
}
Inst::GetElementPtr(ty) => liveness.get_register(node.into()).unwrap().into(),
Inst::Parameter(ty)
| Inst::Call(ty)
| Inst::Phi2(ty)
| Inst::Add(ty)
| Inst::Sub(ty)
@ -2453,11 +2508,11 @@ impl Mir {
ImmRegMem::Mem(StackMem::new(offset, size))
}
Inst::ExternRef(ty) => {
let ty = ty.unwrap_or(Type::QWord);
ImmRegMem::Rip(RipRelative::Label(
ty,
format!(".{}", strings.get_str(data.as_index())),
))
// let ty = ty.unwrap_or(Type::QWord);
ImmRegMem::Rip(RipRelative::Reference(format!(
"{}",
strings.get_str(data.as_index())
)))
}
_ => {
unreachable!()
@ -2623,6 +2678,74 @@ impl Mir {
}
}
}
Inst::Argument(_) => {}
Inst::Call(ty) => {
let (start, end) = data.as_binary();
let length = end - start + 1;
let mut spilled_registers = vec![];
let mut gprs = Register::SYSV_ARG_GPR.into_iter().rev().collect::<Vec<_>>();
let mut sses = Register::SYSV_ARG_SSE.into_iter().rev().collect::<Vec<_>>();
if liveness.is_register_in_use_at_node(NodeRef(node), Register::rax) {
writeln!(func.current_branch(), "push rax")?;
spilled_registers.push(Register::rax);
}
for arg in (start + 1)..end {
variant!(self.nodes[arg as usize] => Inst::Argument(ty));
let arg = self.data[arg as usize].as_node();
let src =
self.node_as_operand(&liveness, &mapping, &mut func, strings, arg);
if ty.is_floating() {
let reg = sses.pop().unwrap();
if liveness.is_register_in_use_at_node(NodeRef(node), reg) {
writeln!(func.current_branch(), "push {reg}")?;
spilled_registers.push(reg);
}
writeln!(func.current_branch(), "movss {reg}, {src}")?;
} else {
let reg = gprs.pop().unwrap();
if liveness.is_register_in_use_at_node(NodeRef(node), reg) {
writeln!(func.current_branch(), "push {reg}")?;
spilled_registers.push(reg);
}
let reg = ty.register_width(reg);
writeln!(func.current_branch(), "mov {reg}, {src}")?;
}
}
let f = self.data[start as usize].as_node();
let f = self.node_as_operand(&liveness, &mapping, &mut func, strings, f);
writeln!(func.current_branch(), "test rax, rax")?;
writeln!(func.current_branch(), "call {f}")?;
let dst = ty.register_width(liveness.get_register(node.into()).unwrap());
if ty.is_floating() {
if dst.parent_reg() != Register::xmm0 {
writeln!(func.current_branch(), "movss {dst}, xmm0")?;
}
} else {
if dst.parent_reg() != Register::rax {
writeln!(
func.current_branch(),
"mov {dst}, {}",
ty.register_width(Register::rax)
)?;
}
};
for reg in spilled_registers.into_iter().rev() {
if reg.parent_reg() == Register::rax {
continue;
}
writeln!(func.current_branch(), "pop {reg}")?;
}
}
Inst::Add(ty) => {
let dst = ty.register_width(liveness.get_register(node.into()).unwrap());
let (lhs, rhs) = data.as_binary();

View file

@ -775,34 +775,34 @@ impl Tree {
}
/// PREFIX_EXPR <-
/// PRIMARY_EXPR
/// ! PRIMARY_EXPR
/// - PRIMARY_EXPR
/// & PRIMARY_EXPR
/// * PRIMARY_EXPR
/// POSTFIX_EXPR
/// ! POSTFIX_EXPR
/// - POSTFIX_EXPR
/// & POSTFIX_EXPR
/// * POSTFIX_EXPR
pub fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
match tokens.peek_token_or_err()?.token() {
Token::Bang => {
_ = tokens.next();
let lhs = self.parse_primary_expr(tokens)?;
let lhs = self.parse_postfix_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Not { lhs }))
}
Token::Minus => {
_ = tokens.next();
let lhs = self.parse_primary_expr(tokens)?;
let lhs = self.parse_postfix_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Negate { lhs }))
}
Token::Ampersand => {
_ = tokens.next();
let lhs = self.parse_primary_expr(tokens)?;
let lhs = self.parse_postfix_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Ref { lhs }))
}
Token::Star => {
_ = tokens.next();
let lhs = self.parse_primary_expr(tokens)?;
let lhs = self.parse_postfix_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Deref { lhs }))
}
_ => self.parse_primary_expr(tokens),
_ => self.parse_postfix_expr(tokens),
}
}
@ -823,9 +823,69 @@ impl Tree {
}
}
/// ARGUMENT <-
/// IDENT : EXPR
/// EXPR
pub fn parse_argument(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
if tokens.is_next_token2(Token::Colon) {
let name = self.parse_ident(tokens)?;
_ = tokens.expect_token(Token::Colon)?;
let expr = self.parse_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Argument {
name: Some(name),
expr,
}))
} else {
let expr = self.parse_expr(tokens)?;
Ok(self.nodes.push_tag(Tag::Argument { name: None, expr }))
}
}
/// ARGUMENT_LIST <-
/// ARGUMENT
/// ARGUMENT_LIST , ARGUMENT
pub fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
let mut arguments = Vec::new();
loop {
// PARAMETER
arguments.push(self.parse_argument(tokens)?);
// COMMA
if !tokens.is_next_token(Token::Comma) {
break;
}
if tokens.is_next_token2(Token::CloseParens) {
break;
}
// skip comma
_ = tokens.next();
}
Ok(self.nodes.push_tag(Tag::ArgumentList { arguments }))
}
/// POSTFIX_EXPR <-
/// PRIMARY_EXPR
/// PRIMARY_EXPR ( )
/// PRIMARY_EXPR ( ARGUMENT_LIST )
pub fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
// TODO
self.parse_primary_expr(tokens)
let lhs = self.parse_primary_expr(tokens)?;
if tokens.eat_token(Token::OpenParens).is_some() {
let rhs = if !tokens.is_next_token(Token::CloseParens) {
let arguments = self.parse_argument_list(tokens)?;
_ = tokens.eat_token(Token::Comma);
Some(arguments)
} else {
None
};
_ = tokens.expect_token(Token::CloseParens)?;
Ok(self.nodes.push_tag(Tag::CallExpr { lhs, rhs }))
} else {
Ok(lhs)
}
}
/// PRIMARY_EXPR <-
@ -1121,7 +1181,9 @@ impl Tree {
vec![lhs]
}
}
Tag::ArgumentList { parameters } => parameters.clone(),
Tag::ArgumentList {
arguments: parameters,
} => parameters.clone(),
&Tag::Argument { name, expr } => {
if let Some(name) = name {
vec![name, expr]
@ -1323,9 +1385,36 @@ impl Tree {
writeln!(writer, ");")?;
Ok(())
}
Tag::CallExpr { .. } => todo!(),
Tag::ArgumentList { .. } => todo!(),
Tag::Argument { .. } => todo!(),
Tag::CallExpr { lhs, rhs } => {
self.render_node(writer, lhs, indent)?;
if let Some(rhs) = rhs {
self.render_node(writer, rhs, indent)?;
writeln_indented!(indent, writer, "%{node} = call (%{lhs})(%{rhs})")
} else {
writeln_indented!(indent, writer, "%{node} = call (%{lhs})()")
}
}
Tag::ArgumentList { arguments } => {
writeln_indented!(indent, writer, "%{} = ArgumentList [", node.get())?;
for args in arguments {
self.render_node(writer, args, indent + 1)?;
}
writeln_indented!(indent, writer, "]")
}
Tag::Argument { name, expr } => {
if let Some(name) = name {
writeln_indented!(
indent,
writer,
"%{} = {}: %{expr},",
node.get(),
self.get_ident_str(name).unwrap(),
)
} else {
writeln_indented!(indent, writer, "%{} = %{expr},", node.get(),)
}
}
Tag::ExplicitCast { lhs, typename } => {
self.render_node(writer, lhs, indent)?;
writeln_indented!(
@ -1788,7 +1877,7 @@ impl Tree {
ty
}
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs),
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs).return_type().unwrap().clone(),
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
@ -2340,7 +2429,9 @@ impl Tree {
Tag::DeclRef(_) => todo!(),
Tag::GlobalRef(_) => todo!(),
Tag::CallExpr { lhs, rhs } => todo!(),
Tag::ArgumentList { parameters } => todo!(),
Tag::ArgumentList {
arguments: parameters,
} => todo!(),
Tag::Argument { name, expr } => todo!(),
Tag::ExplicitCast { lhs, typename } => todo!(),
Tag::Deref { lhs } => todo!(),

View file

@ -2,14 +2,14 @@
use std::{
cmp::Ordering,
collections::{BTreeMap, BTreeSet, HashMap},
collections::{BTreeMap, BTreeSet, HashMap, VecDeque},
};
use crate::{
ast::{IntegralType, Node as AstNode, Tag, Type},
parser::Tree,
string_table::{ImmOrIndex, Index as StringsIndex, StringTable},
variant, writeln_indented,
variant, write_indented, writeln_indented,
};
type Node = u32;
@ -119,6 +119,7 @@ impl From<&Type> for Type2 {
crate::ast::FloatingType::Binary64 => Type2::Binary64,
},
Type::Pointer { .. } => Type2::Pointer,
Type::Fn { .. } => Type2::Pointer,
_ => {
unimplemented!("conversion from {value:?} to triples type not implemented")
}
@ -130,10 +131,18 @@ impl From<&Type> for Type2 {
pub enum Inst {
/// index
Label,
/// ast-node -> index
ExternRef(Type2),
/// index
FunctionStart,
/// None
FunctionEnd, // marker
/// lhs
Argument(Type2),
InlineType(Type2),
/// list of arguments
/// start, (inlinetype)end
Call(Node),
/// Value
/// lhs
GlobalConstant(StringsIndex, Type2),
@ -143,8 +152,6 @@ pub enum Inst {
ConstantU64,
/// index
ConstantMultiByte,
/// ast-node
ExternRef,
/// size, align
Alloca,
/// src
@ -286,6 +293,7 @@ pub struct IRBuilder<'tree, 'ir> {
tree: &'tree mut Tree,
type_map: HashMap<AstNode, Type>,
lookup: HashMap<AstNode, NodeOrList>,
fixup: Vec<Node>,
}
impl core::ops::Index<Node> for IR {
@ -303,6 +311,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
tree,
type_map: HashMap::new(),
lookup: HashMap::new(),
fixup: vec![],
}
}
@ -382,6 +391,40 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
self.ir.push(Inst::FunctionEnd, None)
}
Tag::CallExpr { lhs, rhs } => {
let ty = self.tree.type_of_node(*lhs).return_type().unwrap().clone();
let args =
if let Some(args) = *rhs {
variant!(
self.tree.nodes.get_node(args) => Tag::ArgumentList { arguments }
);
let args = arguments.clone().iter().map(|arg| {
variant!(*self.tree.nodes.get_node(*arg) => Tag::Argument { expr ,..});
(self.visit(expr), self.tree.type_of_node(expr))
}).collect::<Vec<_>>();
let start = self.ir.nodes.len();
for (arg, ty) in args {
_ = self
.ir
.push(Inst::Argument(ty.into()), Some(Data::lhs(arg)));
}
let end = self.ir.nodes.len();
Some((start as u32, end as u32))
} else {
None
};
let (start, end) =
args.unwrap_or((self.ir.nodes.len() as u32, self.ir.nodes.len() as u32));
self.ir.push(Inst::InlineType(ty.into()), None);
let func = self.visit(*lhs);
self.ir
.push(Inst::Call(func), Some(Data::new(start, end + 1)))
}
Tag::Block {
statements,
trailing_expr,
@ -431,14 +474,11 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
global
}
Tag::GlobalRef(decl) => {
let node = match self.lookup.get_mut(decl) {
Some(NodeOrList::Node(decl)) => *decl,
lookup => {
println!("lookup for ast decl %{}", decl.get());
println!("{lookup:?}");
panic!("should not have any unresolved lookups")
}
};
let ty = self.tree.type_of_node(*decl);
let node = self
.ir
.push(Inst::ExternRef(ty.into()), Some(Data::lhs(decl.get())));
self.fixup.push(node);
node
}
Tag::DeclRef(decl) => match self.lookup.get_mut(decl) {
@ -680,6 +720,27 @@ impl IR {
for node in &global_decls {
builder.visit(*node);
}
for &fix in builder.fixup.iter() {
let ast_node = builder.ir.data[fix as usize].unwrap().lhs;
let idx = match builder.tree.nodes.get_node(AstNode::new(ast_node).unwrap()) {
Tag::FunctionDecl { proto, .. } => {
variant!(builder.tree.nodes.get_node(*proto) => Tag::FunctionProto { name,..});
variant!(builder.tree.nodes.get_node(*name) => Tag::Ident { name });
*name
}
Tag::GlobalDecl { name, .. } => {
variant!(builder.tree.nodes.get_node(*name) => Tag::Ident { name });
*name
}
_ => {
unreachable!()
}
};
builder.ir.data[fix as usize] = Some(idx.into());
}
builder
}
}
@ -718,6 +779,25 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
align
)?;
}
Inst::Argument(ty) => {
let lhs = data.lhs;
writeln_indented!(indent, w, "%{node} = argument {ty} %{lhs}",)?;
}
Inst::InlineType(_) => {}
Inst::Call(func) => {
let (start, end) = data.as_lhs_rhs();
variant!(&self.ir.nodes[end as usize -1] => Inst::InlineType(ty));
write_indented!(indent, w, "%{node} = {ty} call %{func}(",)?;
if start + 1 == end {
} else {
for arg in start..(end - 1) {
let arg = self.ir.data[arg as usize].unwrap().lhs;
write_indented!(indent, w, "%{arg}, ")?;
}
}
writeln_indented!(indent, w, ")")?;
}
Inst::ConstantU32 => {
writeln_indented!(indent, w, "%{} = const i32 {}", node, data.as_u32())?;
}
@ -821,9 +901,14 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> {
let (src, dst) = data.as_lhs_rhs();
writeln_indented!(indent, w, "%{} = store {ty}, ptr %{dst}, %{src}", node)?;
}
Inst::ExternRef => {
let ast = data.lhs;
writeln_indented!(indent, w, "%{} = extern reference ast-node %{}", node, ast)?;
Inst::ExternRef(ty) => {
let idx = data.as_index();
writeln_indented!(
indent,
w,
"%{node} = extern reference {ty} '{}'",
self.tree.strings.get_str(idx)
)?;
}
Inst::Branch(condition) => {
let (lhs, rhs) = data.as_lhs_rhs();
@ -1169,6 +1254,7 @@ impl<'a> IrToMirMapping<'a> {
match self.ir.nodes[ir as usize] {
Inst::GlobalConstant(name, ty) => {
eprintln!("does this even get hit anymore???????????????????//");
let ext = mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name));
self.insert(ir, ext);
Some(ext)
@ -1291,7 +1377,6 @@ impl<'a> MirBuilder<'a> {
}
}
}
Inst::ExternRef => todo!(),
Inst::Alloca => {
let (l, r) = data.unwrap().as_lhs_rhs();
mir.gen_alloca(l, r)
@ -1674,6 +1759,25 @@ impl<'a> MirBuilder<'a> {
br
}
Inst::Call(func) => {
let f = mapping.get(&mut mir, func).unwrap().0;
let ir = self.ir.ir;
let (start, end) = data.unwrap().as_lhs_rhs();
variant!(&ir.nodes[end as usize -1] => Inst::InlineType(ty));
let args = (start..(end - 1))
.map(|arg| {
variant!(&ir.nodes[arg as usize] => Inst::Argument(ty));
let arg = ir.data[arg as usize].unwrap().lhs;
let arg = mapping.get(&mut mir, arg).unwrap().0;
(ty.mir_type(), arg)
})
.collect::<Vec<_>>();
mir.gen_call(ty.mir_type(), f, args)
}
Inst::Phi2(ty) => {
let (src, dst) = data.unwrap().as_lhs_rhs();
let lhs = mapping.get(&mut mir, src).unwrap().0;
@ -1686,6 +1790,12 @@ impl<'a> MirBuilder<'a> {
ext
}
Inst::Argument(_) | Inst::InlineType(_) => {
continue;
}
Inst::ExternRef(ty) => {
mir.gen_extern(Some(ty.mir_type()), data.unwrap().as_index())
}
#[allow(unreachable_patterns)]
_ => {
eprintln!("ir inst {inst:?} not supported in mir translation");

11
tests/legal/call.sea Normal file
View file

@ -0,0 +1,11 @@
fn square_of_greater(a: i32, b: i32) -> i32 {
if (a > b)
a * a
else
b * b
}
fn main() -> i32 {
return square_of_greater(2i32 + 2, 5i32);
}

View file

@ -0,0 +1,5 @@
fn main() -> i32 {
return RANDOM;
}
const RANDOM: i32 = 4 + (1 << 3);