uptimizing a bit more, inline calls
This commit is contained in:
parent
641be15703
commit
ad3fc1190c
|
@ -239,7 +239,7 @@ main := fn(): int {
|
||||||
align_of_Type_in_bytes := @alignof(foo.Type)
|
align_of_Type_in_bytes := @alignof(foo.Type)
|
||||||
hardcoded_pointer := @as(^u8, @bitcast(10))
|
hardcoded_pointer := @as(^u8, @bitcast(10))
|
||||||
ecall_that_returns_int := @eca(int, 1, foo.Type.(10, 20), 5, 6)
|
ecall_that_returns_int := @eca(int, 1, foo.Type.(10, 20), 5, 6)
|
||||||
return 0
|
return @inline(foo.foo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// in module: foo.hb
|
// in module: foo.hb
|
||||||
|
@ -248,6 +248,8 @@ Type := struct {
|
||||||
brah: int,
|
brah: int,
|
||||||
blah: int,
|
blah: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foo := fn(): int return 0
|
||||||
```
|
```
|
||||||
|
|
||||||
- `@use(<string>)`: imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax:
|
- `@use(<string>)`: imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax:
|
||||||
|
@ -257,7 +259,8 @@ Type := struct {
|
||||||
- `@intcast(<expr>)`: needs to be used when conversion of `@TypeOf(<expr>)` would loose precision (widening of integers is implicit)
|
- `@intcast(<expr>)`: needs to be used when conversion of `@TypeOf(<expr>)` would loose precision (widening of integers is implicit)
|
||||||
- `@sizeof(<ty>), @alignof(<ty>)`: I think explaining this would insult your intelligence
|
- `@sizeof(<ty>), @alignof(<ty>)`: I think explaining this would insult your intelligence
|
||||||
- `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size and alignment did not change
|
- `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size and alignment did not change
|
||||||
- `@eca(<ty>, <expr>...)`: invoke `eca` instruction, where `<ty>` is the type this will return and `<expr>...` are arguments passed to the call
|
- `@eca(<ty>, ...<expr>)`: invoke `eca` instruction, where `<ty>` is the type this will return and `<expr>...` are arguments passed to the call
|
||||||
|
- `@inline(<func>, ...<args>)`: equivalent to `<func>(...<args>)` but function is guaranteed to inline, compiler will otherwise never inline
|
||||||
|
|
||||||
#### c_strings
|
#### c_strings
|
||||||
```hb
|
```hb
|
||||||
|
@ -324,6 +327,17 @@ pass := fn(arr: ^[int; 3]): int {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### inline
|
||||||
|
```hb
|
||||||
|
main := fn(): int {
|
||||||
|
return @inline(foo, 1, 2, 3) - 6
|
||||||
|
}
|
||||||
|
|
||||||
|
foo := fn(a: int, b: int, c: int): int {
|
||||||
|
return a + b + c
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Incomplete Examples
|
### Incomplete Examples
|
||||||
|
|
||||||
#### comptime_pointers
|
#### comptime_pointers
|
||||||
|
|
|
@ -8,8 +8,7 @@ use {
|
||||||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||||
HashMap,
|
HashMap,
|
||||||
},
|
},
|
||||||
core::panic,
|
std::{ops::Range, rc::Rc, usize},
|
||||||
std::{ops::Range, rc::Rc},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Offset = u32;
|
type Offset = u32;
|
||||||
|
@ -635,6 +634,13 @@ impl Loc {
|
||||||
Self::Rt { stack: Some(stack), reg: reg::STACK_PTR.into(), derefed: true, offset: 0 }
|
Self::Rt { stack: Some(stack), reg: reg::STACK_PTR.into(), derefed: true, offset: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_reg(&self) -> reg::Id {
|
||||||
|
match self {
|
||||||
|
Self::Rt { reg, .. } => reg.as_ref(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn reg(reg: impl Into<reg::Id>) -> Self {
|
fn reg(reg: impl Into<reg::Id>) -> Self {
|
||||||
let reg = reg.into();
|
let reg = reg.into();
|
||||||
assert!(reg.get() != 0);
|
assert!(reg.get() != 0);
|
||||||
|
@ -779,6 +785,15 @@ impl ItemCtx {
|
||||||
debug_assert!(reloc.offset < len);
|
debug_assert!(reloc.offset < len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(last_ret) = self.ret_relocs.last()
|
||||||
|
&& last_ret.offset as usize == output.code.len() - 5
|
||||||
|
{
|
||||||
|
output.code.truncate(output.code.len() - 5);
|
||||||
|
self.ret_relocs.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = output.code.len() as Offset;
|
||||||
|
|
||||||
self.stack.finalize_leaked();
|
self.stack.finalize_leaked();
|
||||||
for rel in self.stack_relocs.drain(..) {
|
for rel in self.stack_relocs.drain(..) {
|
||||||
rel.apply_stack_offset(&mut output.code[base as usize..], &self.stack)
|
rel.apply_stack_offset(&mut output.code[base as usize..], &self.stack)
|
||||||
|
@ -1046,6 +1061,24 @@ pub struct Snapshot {
|
||||||
strings: usize,
|
strings: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Snapshot {
|
||||||
|
fn _sub(&mut self, other: &Self) {
|
||||||
|
self.code -= other.code;
|
||||||
|
self.string_data -= other.string_data;
|
||||||
|
self.funcs -= other.funcs;
|
||||||
|
self.globals -= other.globals;
|
||||||
|
self.strings -= other.strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _add(&mut self, other: &Self) {
|
||||||
|
self.code += other.code;
|
||||||
|
self.string_data += other.string_data;
|
||||||
|
self.funcs += other.funcs;
|
||||||
|
self.globals += other.globals;
|
||||||
|
self.strings += other.strings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Output {
|
struct Output {
|
||||||
code: Vec<u8>,
|
code: Vec<u8>,
|
||||||
|
@ -1348,6 +1381,7 @@ impl Codegen {
|
||||||
pub fn generate(&mut self) {
|
pub fn generate(&mut self) {
|
||||||
self.output.emit_entry_prelude();
|
self.output.emit_entry_prelude();
|
||||||
self.find_or_declare(0, 0, Err("main"), "");
|
self.find_or_declare(0, 0, Err("main"), "");
|
||||||
|
self.make_func_reachable(0);
|
||||||
self.complete_call_graph_low();
|
self.complete_call_graph_low();
|
||||||
self.link();
|
self.link();
|
||||||
}
|
}
|
||||||
|
@ -1474,6 +1508,53 @@ impl Codegen {
|
||||||
let val = self.ty(val);
|
let val = self.ty(val);
|
||||||
Some(Value::ty(self.tys.make_ptr(val)))
|
Some(Value::ty(self.tys.make_ptr(val)))
|
||||||
}
|
}
|
||||||
|
E::Directive { name: "inline", args: [func_ast, args @ ..], .. } => {
|
||||||
|
let ty::Kind::Func(mut func) = self.ty(func_ast).expand() else {
|
||||||
|
self.report(func_ast.pos(), "first argument of inline needs to be a function");
|
||||||
|
};
|
||||||
|
|
||||||
|
let fuc = self.tys.funcs[func as usize];
|
||||||
|
let fast = self.files[fuc.file as usize].clone();
|
||||||
|
let E::BinOp { right: &E::Closure { args: cargs, body, .. }, .. } =
|
||||||
|
fuc.expr.get(&fast).unwrap()
|
||||||
|
else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let scope = self.ci.vars.len();
|
||||||
|
let sig = self.compute_signature(&mut func, func_ast.pos(), args)?;
|
||||||
|
|
||||||
|
if scope == self.ci.vars.len() {
|
||||||
|
for ((arg, ty), carg) in
|
||||||
|
args.iter().zip(sig.args.view(&self.tys.args).to_owned()).zip(cargs)
|
||||||
|
{
|
||||||
|
let loc = self.expr_ctx(arg, Ctx::default().with_ty(ty))?.loc;
|
||||||
|
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret_reloc_base = self.ci.ret_relocs.len();
|
||||||
|
|
||||||
|
let loc = self.alloc_ret(sig.ret, ctx, false);
|
||||||
|
let prev_ret_reg = std::mem::replace(&mut self.ci.ret_reg, loc.get_reg());
|
||||||
|
self.expr(body);
|
||||||
|
self.ci.ret_reg = prev_ret_reg;
|
||||||
|
|
||||||
|
//if let Some(last_ret) = self.ci.ret_relocs.last()
|
||||||
|
// && last_ret.offset as usize + self.ci.snap.code == self.output.code.len() - 5
|
||||||
|
//{
|
||||||
|
// self.output.code.truncate(self.output.code.len() - 5);
|
||||||
|
// self.ci.ret_relocs.pop();
|
||||||
|
//}
|
||||||
|
let len = self.output.code.len() as u32;
|
||||||
|
for mut rel in self.ci.ret_relocs.drain(ret_reloc_base..) {
|
||||||
|
rel.offset += self.ci.snap.code as u32;
|
||||||
|
rel.shifted = true;
|
||||||
|
rel.apply_jump(&mut self.output.code, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(Value { ty: sig.ret, loc });
|
||||||
|
}
|
||||||
E::Directive { name: "TypeOf", args: [expr], .. } => {
|
E::Directive { name: "TypeOf", args: [expr], .. } => {
|
||||||
let snap = self.output.snap();
|
let snap = self.output.snap();
|
||||||
let value = self.expr(expr).unwrap();
|
let value = self.expr(expr).unwrap();
|
||||||
|
@ -1495,7 +1576,7 @@ impl Codegen {
|
||||||
self.ci.free_loc(value);
|
self.ci.free_loc(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let loc = self.alloc_ret(ty, ctx);
|
let loc = self.alloc_ret(ty, ctx, false);
|
||||||
|
|
||||||
self.output.emit(eca());
|
self.output.emit(eca());
|
||||||
|
|
||||||
|
@ -1797,72 +1878,27 @@ impl Codegen {
|
||||||
self.report(fast.pos(), "can't call this, maybe in the future");
|
self.report(fast.pos(), "can't call this, maybe in the future");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: this will be usefull but not now
|
||||||
|
let scope = self.ci.vars.len();
|
||||||
|
//let mut snap = self.output.snap();
|
||||||
|
//snap.sub(&self.ci.snap);
|
||||||
|
//let prev_stack_rel = self.ci.stack_relocs.len();
|
||||||
|
//let prev_ret_rel = self.ci.ret_relocs.len();
|
||||||
|
let sig = self.compute_signature(&mut func, expr.pos(), args)?;
|
||||||
|
//self.ci.ret_relocs.truncate(prev_ret_rel);
|
||||||
|
//self.ci.stack_relocs.truncate(prev_stack_rel);
|
||||||
|
//snap.add(&self.ci.snap);
|
||||||
|
//self.output.trunc(&snap);
|
||||||
|
self.ci.vars.truncate(scope);
|
||||||
|
|
||||||
let fuc = self.tys.funcs[func as usize];
|
let fuc = self.tys.funcs[func as usize];
|
||||||
let ast = self.files[fuc.file as usize].clone();
|
let ast = self.files[fuc.file as usize].clone();
|
||||||
let E::BinOp { right: &E::Closure { args: cargs, ret, .. }, .. } =
|
let E::BinOp { right: &E::Closure { args: cargs, .. }, .. } =
|
||||||
fuc.expr.get(&ast).unwrap()
|
fuc.expr.get(&ast).unwrap()
|
||||||
else {
|
else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
|
||||||
let sig = if let Some(sig) = fuc.sig {
|
|
||||||
sig
|
|
||||||
} else {
|
|
||||||
let scope = self.ci.vars.len();
|
|
||||||
let arg_base = self.tys.args.len();
|
|
||||||
|
|
||||||
for (arg, carg) in args.iter().zip(cargs) {
|
|
||||||
let ty = self.ty(&carg.ty);
|
|
||||||
log::dbg!("arg: {}", self.ty_display(ty));
|
|
||||||
self.tys.args.push(ty);
|
|
||||||
let sym = parser::find_symbol(&ast.symbols, carg.id);
|
|
||||||
let loc = if sym.flags & idfl::COMPTIME == 0 {
|
|
||||||
// FIXME: could fuck us
|
|
||||||
Loc::default()
|
|
||||||
} else {
|
|
||||||
debug_assert_eq!(
|
|
||||||
ty,
|
|
||||||
ty::TYPE.into(),
|
|
||||||
"TODO: we dont support anything except type generics"
|
|
||||||
);
|
|
||||||
let arg = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
|
||||||
self.tys.args.push(arg.loc.to_ty().unwrap());
|
|
||||||
arg.loc
|
|
||||||
};
|
|
||||||
|
|
||||||
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = self.pack_args(expr.pos(), arg_base);
|
|
||||||
let ret = self.ty(ret);
|
|
||||||
self.ci.vars.truncate(scope);
|
|
||||||
|
|
||||||
let sym = SymKey {
|
|
||||||
file: !args.repr(),
|
|
||||||
ident: ty::Kind::Func(func).compress().repr(),
|
|
||||||
};
|
|
||||||
let ct = || {
|
|
||||||
let func_id = self.tys.funcs.len();
|
|
||||||
self.tys.funcs.push(Func {
|
|
||||||
file: fuc.file,
|
|
||||||
offset: task::id(func_id),
|
|
||||||
sig: Some(Sig { args, ret }),
|
|
||||||
expr: fuc.expr,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.tasks.push(Some(FTask {
|
|
||||||
// FIXME: this will fuck us
|
|
||||||
file: fuc.file,
|
|
||||||
id: func_id as _,
|
|
||||||
}));
|
|
||||||
|
|
||||||
ty::Kind::Func(func_id as _).compress()
|
|
||||||
};
|
|
||||||
func = self.tys.syms.entry(sym).or_insert_with(ct).expand().inner();
|
|
||||||
|
|
||||||
Sig { args, ret }
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut parama = self.tys.parama(sig.ret);
|
let mut parama = self.tys.parama(sig.ret);
|
||||||
let mut values = Vec::with_capacity(args.len());
|
let mut values = Vec::with_capacity(args.len());
|
||||||
let mut sig_args = sig.args.range();
|
let mut sig_args = sig.args.range();
|
||||||
|
@ -1888,7 +1924,7 @@ impl Codegen {
|
||||||
|
|
||||||
log::dbg!("call ctx: {ctx:?}");
|
log::dbg!("call ctx: {ctx:?}");
|
||||||
|
|
||||||
let loc = self.alloc_ret(sig.ret, ctx);
|
let loc = self.alloc_ret(sig.ret, ctx, false);
|
||||||
|
|
||||||
if should_momize {
|
if should_momize {
|
||||||
self.output.write_trap(trap::Trap::MomizedCall(trap::MomizedCall { func }));
|
self.output.write_trap(trap::Trap::MomizedCall(trap::MomizedCall { func }));
|
||||||
|
@ -1897,6 +1933,7 @@ impl Codegen {
|
||||||
let reloc = Reloc::new(self.local_offset(), 3, 4);
|
let reloc = Reloc::new(self.local_offset(), 3, 4);
|
||||||
self.output.funcs.push((func, reloc));
|
self.output.funcs.push((func, reloc));
|
||||||
self.output.emit(jal(RET_ADDR, ZERO, 0));
|
self.output.emit(jal(RET_ADDR, ZERO, 0));
|
||||||
|
self.make_func_reachable(func);
|
||||||
|
|
||||||
if should_momize {
|
if should_momize {
|
||||||
self.output.emit(tx());
|
self.output.emit(tx());
|
||||||
|
@ -2177,6 +2214,63 @@ impl Codegen {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
|
||||||
|
let fuc = self.tys.funcs[*func as usize];
|
||||||
|
let fast = self.files[fuc.file as usize].clone();
|
||||||
|
let Expr::BinOp { right: &Expr::Closure { args: cargs, ret, .. }, .. } =
|
||||||
|
fuc.expr.get(&fast).unwrap()
|
||||||
|
else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(if let Some(sig) = fuc.sig {
|
||||||
|
sig
|
||||||
|
} else {
|
||||||
|
let arg_base = self.tys.args.len();
|
||||||
|
|
||||||
|
for (arg, carg) in args.iter().zip(cargs) {
|
||||||
|
let ty = self.ty(&carg.ty);
|
||||||
|
log::dbg!("arg: {}", self.ty_display(ty));
|
||||||
|
self.tys.args.push(ty);
|
||||||
|
let sym = parser::find_symbol(&fast.symbols, carg.id);
|
||||||
|
let loc = if sym.flags & idfl::COMPTIME == 0 {
|
||||||
|
// FIXME: could fuck us
|
||||||
|
Loc::default()
|
||||||
|
} else {
|
||||||
|
debug_assert_eq!(
|
||||||
|
ty,
|
||||||
|
ty::TYPE.into(),
|
||||||
|
"TODO: we dont support anything except type generics"
|
||||||
|
);
|
||||||
|
let arg = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
||||||
|
self.tys.args.push(arg.loc.to_ty().unwrap());
|
||||||
|
arg.loc
|
||||||
|
};
|
||||||
|
|
||||||
|
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = self.pack_args(pos, arg_base);
|
||||||
|
let ret = self.ty(ret);
|
||||||
|
|
||||||
|
let sym = SymKey { file: !args.repr(), ident: ty::Kind::Func(*func).compress().repr() };
|
||||||
|
let ct = || {
|
||||||
|
let func_id = self.tys.funcs.len();
|
||||||
|
self.tys.funcs.push(Func {
|
||||||
|
file: fuc.file,
|
||||||
|
offset: u32::MAX,
|
||||||
|
sig: Some(Sig { args, ret }),
|
||||||
|
expr: fuc.expr,
|
||||||
|
});
|
||||||
|
|
||||||
|
ty::Kind::Func(func_id as _).compress()
|
||||||
|
};
|
||||||
|
*func = self.tys.syms.entry(sym).or_insert_with(ct).expand().inner();
|
||||||
|
|
||||||
|
Sig { args, ret }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn has_ct(&self, expr: &Expr) -> bool {
|
fn has_ct(&self, expr: &Expr) -> bool {
|
||||||
expr.has_ct(&self.cfile().symbols)
|
expr.has_ct(&self.cfile().symbols)
|
||||||
}
|
}
|
||||||
|
@ -2625,7 +2719,7 @@ impl Codegen {
|
||||||
Value { ty: ret.into(), loc: Loc::reg(1) }
|
Value { ty: ret.into(), loc: Loc::reg(1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_ret(&mut self, ret: ty::Id, ctx: Ctx) -> Loc {
|
fn alloc_ret(&mut self, ret: ty::Id, ctx: Ctx, custom_ret_reg: bool) -> Loc {
|
||||||
let size = self.tys.size_of(ret);
|
let size = self.tys.size_of(ret);
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
debug_assert!(ctx.loc.is_none(), "{}", self.ty_display(ret));
|
debug_assert!(ctx.loc.is_none(), "{}", self.ty_display(ret));
|
||||||
|
@ -2638,9 +2732,10 @@ impl Codegen {
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
0 => Loc::default(),
|
0 => Loc::default(),
|
||||||
|
1..=8 if custom_ret_reg => Loc::reg(self.ci.regs.allocate()),
|
||||||
1..=8 => Loc::reg(1),
|
1..=8 => Loc::reg(1),
|
||||||
9..=16 => Loc::stack(self.ci.stack.allocate(size)),
|
9..=16 => Loc::stack(self.ci.stack.allocate(size)),
|
||||||
_ => {
|
17.. => {
|
||||||
let loc = ctx.loc.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size)));
|
let loc = ctx.loc.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size)));
|
||||||
let Loc::Rt { reg, stack, offset, .. } = &loc else {
|
let Loc::Rt { reg, stack, offset, .. } = &loc else {
|
||||||
todo!("old man with the beard looks at the sky scared");
|
todo!("old man with the beard looks at the sky scared");
|
||||||
|
@ -2955,10 +3050,8 @@ impl Codegen {
|
||||||
op: TokenKind::Decl,
|
op: TokenKind::Decl,
|
||||||
right: &Expr::Closure { pos, args, ret, .. },
|
right: &Expr::Closure { pos, args, ret, .. },
|
||||||
} => {
|
} => {
|
||||||
let mut push_task = false;
|
|
||||||
let func = Func {
|
let func = Func {
|
||||||
file,
|
file,
|
||||||
offset: task::id(self.tasks.len()),
|
|
||||||
sig: 'b: {
|
sig: 'b: {
|
||||||
let arg_base = self.tys.args.len();
|
let arg_base = self.tys.args.len();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -2971,8 +3064,6 @@ impl Codegen {
|
||||||
self.tys.args.push(ty);
|
self.tys.args.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
push_task = true;
|
|
||||||
|
|
||||||
let args = self.pack_args(pos, arg_base);
|
let args = self.pack_args(pos, arg_base);
|
||||||
log::dbg!("eval ret");
|
log::dbg!("eval ret");
|
||||||
let ret = self.ty(ret);
|
let ret = self.ty(ret);
|
||||||
|
@ -2984,12 +3075,10 @@ impl Codegen {
|
||||||
debug_assert!(refr.get(&f).is_some());
|
debug_assert!(refr.get(&f).is_some());
|
||||||
refr
|
refr
|
||||||
},
|
},
|
||||||
|
offset: u32::MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = self.tys.funcs.len() as _;
|
let id = self.tys.funcs.len() as _;
|
||||||
if push_task {
|
|
||||||
self.tasks.push(Some(FTask { file, id }));
|
|
||||||
}
|
|
||||||
self.tys.funcs.push(func);
|
self.tys.funcs.push(func);
|
||||||
|
|
||||||
ty::Kind::Func(id)
|
ty::Kind::Func(id)
|
||||||
|
@ -3023,6 +3112,14 @@ impl Codegen {
|
||||||
sym
|
sym
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||||
|
let fuc = &mut self.tys.funcs[func as usize];
|
||||||
|
if fuc.offset == u32::MAX {
|
||||||
|
fuc.offset = task::id(self.tasks.len() as _);
|
||||||
|
self.tasks.push(Some(FTask { file: fuc.file, id: func }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_global(&mut self, expr: &Expr) -> Global {
|
fn generate_global(&mut self, expr: &Expr) -> Global {
|
||||||
self.output.emit_prelude();
|
self.output.emit_prelude();
|
||||||
|
|
||||||
|
@ -3364,5 +3461,6 @@ mod tests {
|
||||||
comptime_min_reg_leak => README;
|
comptime_min_reg_leak => README;
|
||||||
// structs_in_registers => README;
|
// structs_in_registers => README;
|
||||||
comptime_function_from_another_file => README;
|
comptime_function_from_another_file => README;
|
||||||
|
inline => README;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 193
|
code size: 188
|
||||||
ret: 1
|
ret: 1
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 418
|
code size: 408
|
||||||
ret: 7
|
ret: 7
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 313
|
code size: 303
|
||||||
ret: 16
|
ret: 16
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 153
|
code size: 143
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 255
|
code size: 245
|
||||||
ret: 50
|
ret: 50
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 231
|
code size: 221
|
||||||
ret: 50
|
ret: 50
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 536
|
code size: 531
|
||||||
ret: 512
|
ret: 512
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 525
|
code size: 505
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 281
|
code size: 266
|
||||||
ret: 33
|
ret: 33
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 296
|
code size: 281
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 1504
|
code size: 1469
|
||||||
ret: 69
|
ret: 69
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 277
|
code size: 267
|
||||||
ret: 50
|
ret: 50
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 210
|
code size: 205
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 262
|
code size: 252
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
3
hblang/tests/codegen_tests_inline.txt
Normal file
3
hblang/tests/codegen_tests_inline.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
code size: 124
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 268
|
code size: 258
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 330
|
code size: 315
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 357
|
code size: 87
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 786
|
code size: 781
|
||||||
ret: 10
|
ret: 10
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 533
|
code size: 518
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 330
|
code size: 320
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 460
|
code size: 445
|
||||||
ret: 3
|
ret: 3
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 116
|
code size: 111
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue