adding some simple provenance checks on return values
This commit is contained in:
parent
7d48d3beb1
commit
a299bad75b
File diff suppressed because one or more lines are too long
|
@ -994,6 +994,14 @@ impl Nodes {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self[class.1].outputs.iter().any(|&n| {
|
||||||
|
self[n].kind != Kind::Stre
|
||||||
|
&& self[n].outputs.iter().any(|&n| self[n].kind != Kind::Stre)
|
||||||
|
}) {
|
||||||
|
new_inps.push(n);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
cursor = self[cursor].inputs[3];
|
cursor = self[cursor].inputs[3];
|
||||||
while cursor != MEM {
|
while cursor != MEM {
|
||||||
debug_assert_eq!(self[cursor].kind, Kind::Stre);
|
debug_assert_eq!(self[cursor].kind, Kind::Stre);
|
||||||
|
@ -1799,6 +1807,7 @@ pub struct Node {
|
||||||
loop_depth: Cell<LoopDepth>,
|
loop_depth: Cell<LoopDepth>,
|
||||||
aclass: AClassId,
|
aclass: AClassId,
|
||||||
antidep: Nid,
|
antidep: Nid,
|
||||||
|
pos: Pos,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -2318,9 +2327,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.ct.run(ret_loc, entry)
|
self.ct.run(ret_loc, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_stack(&mut self, ty: ty::Id) -> Nid {
|
fn new_stack(&mut self, pos: Pos, ty: ty::Id) -> Nid {
|
||||||
let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]);
|
let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]);
|
||||||
self.ci.nodes[stck].aclass = self.ci.scope.aclasses.len() as _;
|
self.ci.nodes[stck].aclass = self.ci.scope.aclasses.len() as _;
|
||||||
|
self.ci.nodes[stck].pos = pos;
|
||||||
self.ci.scope.aclasses.push(AClass::new(&mut self.ci.nodes));
|
self.ci.scope.aclasses.push(AClass::new(&mut self.ci.nodes));
|
||||||
stck
|
stck
|
||||||
}
|
}
|
||||||
|
@ -2452,7 +2462,7 @@ impl<'a> Codegen<'a> {
|
||||||
Loc::Reg => Some(self.ci.nodes.new_const_lit(oty, 0)),
|
Loc::Reg => Some(self.ci.nodes.new_const_lit(oty, 0)),
|
||||||
Loc::Stack => {
|
Loc::Stack => {
|
||||||
let OptLayout { flag_ty, flag_offset, .. } = self.tys.opt_layout(ty);
|
let OptLayout { flag_ty, flag_offset, .. } = self.tys.opt_layout(ty);
|
||||||
let stack = self.new_stack(oty);
|
let stack = self.new_stack(pos, oty);
|
||||||
let offset = self.offset(stack, flag_offset);
|
let offset = self.offset(stack, flag_offset);
|
||||||
let value = self.ci.nodes.new_const(flag_ty, 0);
|
let value = self.ci.nodes.new_const(flag_ty, 0);
|
||||||
self.store_mem(offset, flag_ty, value);
|
self.store_mem(offset, flag_ty, value);
|
||||||
|
@ -2464,7 +2474,7 @@ impl<'a> Codegen<'a> {
|
||||||
inference!(ty, ctx, self, pos, "value", "@as(<ty>, idk)");
|
inference!(ty, ctx, self, pos, "value", "@as(<ty>, idk)");
|
||||||
|
|
||||||
if ty.loc(self.tys) == Loc::Stack {
|
if ty.loc(self.tys) == Loc::Stack {
|
||||||
Some(Value::ptr(self.new_stack(ty)).ty(ty))
|
Some(Value::ptr(self.new_stack(pos, ty)).ty(ty))
|
||||||
} else {
|
} else {
|
||||||
Some(self.ci.nodes.new_const_lit(ty, 0))
|
Some(self.ci.nodes.new_const_lit(ty, 0))
|
||||||
}
|
}
|
||||||
|
@ -2562,6 +2572,8 @@ impl<'a> Codegen<'a> {
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.ci.nodes[self.ci.ctrl.get()].pos = pos;
|
||||||
|
|
||||||
self.ci.nodes[NEVER].inputs.push(self.ci.ctrl.get());
|
self.ci.nodes[NEVER].inputs.push(self.ci.ctrl.get());
|
||||||
self.ci.nodes[self.ci.ctrl.get()].outputs.push(NEVER);
|
self.ci.nodes[self.ci.ctrl.get()].outputs.push(NEVER);
|
||||||
} else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret {
|
} else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret {
|
||||||
|
@ -2661,7 +2673,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
||||||
}
|
}
|
||||||
Expr::UnOp { op: TokenKind::Band, val, .. } => {
|
Expr::UnOp { op: TokenKind::Band, val, pos } => {
|
||||||
let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) };
|
let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) };
|
||||||
|
|
||||||
let mut val = self.raw_expr_ctx(val, ctx)?;
|
let mut val = self.raw_expr_ctx(val, ctx)?;
|
||||||
|
@ -2673,7 +2685,7 @@ impl<'a> Codegen<'a> {
|
||||||
return Some(val);
|
return Some(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
let stack = self.new_stack(val.ty);
|
let stack = self.new_stack(pos, val.ty);
|
||||||
self.store_mem(stack, val.ty, val.id);
|
self.store_mem(stack, val.ty, val.id);
|
||||||
|
|
||||||
Some(Value::new(stack).ty(self.tys.make_ptr(val.ty)))
|
Some(Value::new(stack).ty(self.tys.make_ptr(val.ty)))
|
||||||
|
@ -2710,11 +2722,11 @@ impl<'a> Codegen<'a> {
|
||||||
Value::NEVER
|
Value::NEVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::BinOp { left, op: TokenKind::Decl, right, .. } => {
|
Expr::BinOp { left, op: TokenKind::Decl, right, pos } => {
|
||||||
let mut right = self.expr(right)?;
|
let mut right = self.expr(right)?;
|
||||||
|
|
||||||
if right.ty.loc(self.tys) == Loc::Stack {
|
if right.ty.loc(self.tys) == Loc::Stack {
|
||||||
let stck = self.new_stack(right.ty);
|
let stck = self.new_stack(pos, right.ty);
|
||||||
self.store_mem(stck, right.ty, right.id);
|
self.store_mem(stck, right.ty, right.id);
|
||||||
right.id = stck;
|
right.id = stck;
|
||||||
right.ptr = true;
|
right.ptr = true;
|
||||||
|
@ -2807,7 +2819,7 @@ impl<'a> Codegen<'a> {
|
||||||
let mut rhs = rhs?;
|
let mut rhs = rhs?;
|
||||||
self.strip_var(&mut rhs);
|
self.strip_var(&mut rhs);
|
||||||
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
|
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
|
||||||
let dst = self.new_stack(lhs.ty);
|
let dst = self.new_stack(pos, lhs.ty);
|
||||||
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
|
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
|
||||||
Some(Value::ptr(dst).ty(lhs.ty))
|
Some(Value::ptr(dst).ty(lhs.ty))
|
||||||
}
|
}
|
||||||
|
@ -2906,7 +2918,7 @@ impl<'a> Codegen<'a> {
|
||||||
match ty.loc(self.tys) {
|
match ty.loc(self.tys) {
|
||||||
Loc::Reg if mem::take(&mut val.ptr) => val.id = self.load_mem(val.id, ty),
|
Loc::Reg if mem::take(&mut val.ptr) => val.id = self.load_mem(val.id, ty),
|
||||||
Loc::Stack if !val.ptr => {
|
Loc::Stack if !val.ptr => {
|
||||||
let stack = self.new_stack(ty);
|
let stack = self.new_stack(pos, ty);
|
||||||
self.store_mem(stack, val.ty, val.id);
|
self.store_mem(stack, val.ty, val.id);
|
||||||
val.id = stack;
|
val.id = stack;
|
||||||
val.ptr = true;
|
val.ptr = true;
|
||||||
|
@ -3074,7 +3086,7 @@ impl<'a> Codegen<'a> {
|
||||||
let alt_value = match ty.loc(self.tys) {
|
let alt_value = match ty.loc(self.tys) {
|
||||||
Loc::Reg => None,
|
Loc::Reg => None,
|
||||||
Loc::Stack => {
|
Loc::Stack => {
|
||||||
let stck = self.new_stack(ty);
|
let stck = self.new_stack(pos, ty);
|
||||||
inps.push(stck);
|
inps.push(stck);
|
||||||
Some(Value::ptr(stck).ty(ty))
|
Some(Value::ptr(stck).ty(ty))
|
||||||
}
|
}
|
||||||
|
@ -3151,7 +3163,7 @@ impl<'a> Codegen<'a> {
|
||||||
let alt_value = match sig.ret.loc(self.tys) {
|
let alt_value = match sig.ret.loc(self.tys) {
|
||||||
Loc::Reg => None,
|
Loc::Reg => None,
|
||||||
Loc::Stack => {
|
Loc::Stack => {
|
||||||
let stck = self.new_stack(sig.ret);
|
let stck = self.new_stack(func.pos(), sig.ret);
|
||||||
inps.push(stck);
|
inps.push(stck);
|
||||||
Some(Value::ptr(stck).ty(sig.ret))
|
Some(Value::ptr(stck).ty(sig.ret))
|
||||||
}
|
}
|
||||||
|
@ -3298,7 +3310,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
match sty.expand() {
|
match sty.expand() {
|
||||||
ty::Kind::Struct(s) => {
|
ty::Kind::Struct(s) => {
|
||||||
let mem = self.new_stack(sty);
|
let mem = self.new_stack(pos, sty);
|
||||||
let mut offs = OffsetIter::new(s, self.tys);
|
let mut offs = OffsetIter::new(s, self.tys);
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let Some((ty, offset)) = offs.next_ty(self.tys) else {
|
let Some((ty, offset)) = offs.next_ty(self.tys) else {
|
||||||
|
@ -3352,7 +3364,7 @@ impl<'a> Codegen<'a> {
|
||||||
return Value::NEVER;
|
return Value::NEVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mem = self.new_stack(aty);
|
let mem = self.new_stack(pos, aty);
|
||||||
|
|
||||||
for (field, offset) in
|
for (field, offset) in
|
||||||
fields.iter().zip((0u32..).step_by(elem_size as usize))
|
fields.iter().zip((0u32..).step_by(elem_size as usize))
|
||||||
|
@ -3407,7 +3419,7 @@ impl<'a> Codegen<'a> {
|
||||||
.into_iter(self.tys)
|
.into_iter(self.tys)
|
||||||
.map(|(f, o)| (f.ty, o))
|
.map(|(f, o)| (f.ty, o))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let mem = self.new_stack(sty);
|
let mem = self.new_stack(pos, sty);
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let Some(index) = self.tys.find_struct_field(s, field.name) else {
|
let Some(index) = self.tys.find_struct_field(s, field.name) else {
|
||||||
self.report(
|
self.report(
|
||||||
|
@ -4199,6 +4211,23 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
self.ci.unlock();
|
self.ci.unlock();
|
||||||
|
|
||||||
|
for &node in self.ci.nodes[NEVER].inputs.iter() {
|
||||||
|
if self.ci.nodes[node].kind == Kind::Return
|
||||||
|
&& self.ci.nodes[self.ci.nodes.aclass_index(self.ci.nodes[node].inputs[1]).1].kind
|
||||||
|
== Kind::Stck
|
||||||
|
{
|
||||||
|
self.report(
|
||||||
|
self.ci.nodes[node].pos,
|
||||||
|
"returning value with local provenance \
|
||||||
|
(pointer will be invalid after function returns)",
|
||||||
|
);
|
||||||
|
self.report(
|
||||||
|
self.ci.nodes[self.ci.nodes.aclass_index(self.ci.nodes[node].inputs[1]).1].pos,
|
||||||
|
"...the pointer points to stack allocation created here",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.errors.borrow().len() == prev_err_len {
|
if self.errors.borrow().len() == prev_err_len {
|
||||||
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
||||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||||
|
@ -4265,7 +4294,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_in_opt(&mut self, val: &mut Value) {
|
fn wrap_in_opt(&mut self, pos: Pos, val: &mut Value) {
|
||||||
debug_assert!(!val.var);
|
debug_assert!(!val.var);
|
||||||
|
|
||||||
let was_ptr = val.ptr;
|
let was_ptr = val.ptr;
|
||||||
|
@ -4294,7 +4323,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
Loc::Stack => {
|
Loc::Stack => {
|
||||||
self.strip_ptr(val);
|
self.strip_ptr(val);
|
||||||
let stack = self.new_stack(oty);
|
let stack = self.new_stack(pos, oty);
|
||||||
let fill = self.ci.nodes.new_const(flag_ty, 1);
|
let fill = self.ci.nodes.new_const(flag_ty, 1);
|
||||||
self.store_mem(stack, flag_ty, fill);
|
self.store_mem(stack, flag_ty, fill);
|
||||||
let off = self.offset(stack, payload_offset);
|
let off = self.offset(stack, payload_offset);
|
||||||
|
@ -4394,7 +4423,7 @@ impl<'a> Codegen<'a> {
|
||||||
if inner != src.ty {
|
if inner != src.ty {
|
||||||
self.assert_ty(pos, src, inner, hint);
|
self.assert_ty(pos, src, inner, hint);
|
||||||
}
|
}
|
||||||
self.wrap_in_opt(src);
|
self.wrap_in_opt(pos, src);
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
src.ty.is_integer() || src.ty == ty::Id::NEVER,
|
src.ty.is_integer() || src.ty == ty::Id::NEVER,
|
||||||
|
@ -4609,6 +4638,7 @@ mod tests {
|
||||||
fb_driver;
|
fb_driver;
|
||||||
|
|
||||||
// Purely Testing Examples;
|
// Purely Testing Examples;
|
||||||
|
stack_provenance;
|
||||||
advanced_floating_point_arithmetic;
|
advanced_floating_point_arithmetic;
|
||||||
nullable_structure;
|
nullable_structure;
|
||||||
needless_unwrap;
|
needless_unwrap;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
get_ptr:
|
get_ptr:
|
||||||
ADDI64 r254, r254, -8d
|
LI64 r1, 0d
|
||||||
ADDI64 r1, r254, 0d
|
|
||||||
ADDI64 r254, r254, 8d
|
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -40d
|
ADDI64 r254, r254, -40d
|
||||||
|
@ -21,6 +19,6 @@ main:
|
||||||
1: LD r31, r254, 0a, 40h
|
1: LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 208
|
code size: 185
|
||||||
ret: 10
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -2,8 +2,8 @@ decide:
|
||||||
LI8 r1, 1b
|
LI8 r1, 1b
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -224d
|
ADDI64 r254, r254, -232d
|
||||||
ST r31, r254, 80a, 144h
|
ST r31, r254, 80a, 152h
|
||||||
JAL r31, r0, :decide
|
JAL r31, r0, :decide
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
ADDI64 r2, r254, 72d
|
ADDI64 r2, r254, 72d
|
||||||
|
@ -13,52 +13,54 @@ main:
|
||||||
CP r34, r32
|
CP r34, r32
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r34, r33
|
0: CP r34, r33
|
||||||
1: JNE r34, r32, :2
|
1: LI64 r35, 1d
|
||||||
|
ST r35, r254, 72a, 8h
|
||||||
|
JNE r34, r32, :2
|
||||||
LI64 r1, 9001d
|
LI64 r1, 9001d
|
||||||
JMP :3
|
JMP :3
|
||||||
2: JAL r31, r0, :decide
|
2: JAL r31, r0, :decide
|
||||||
LI8 r35, 0b
|
LI8 r36, 0b
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :4
|
JNE r1, r0, :4
|
||||||
LI8 r36, 1b
|
LI8 r37, 1b
|
||||||
ST r36, r254, 56a, 1h
|
ST r37, r254, 56a, 1h
|
||||||
LD r36, r34, 0a, 8h
|
LD r37, r34, 0a, 8h
|
||||||
ST r36, r254, 64a, 8h
|
ST r37, r254, 64a, 8h
|
||||||
JMP :5
|
JMP :5
|
||||||
4: ST r35, r254, 56a, 1h
|
4: ST r36, r254, 56a, 1h
|
||||||
5: LD r37, r254, 56a, 1h
|
5: LD r38, r254, 56a, 1h
|
||||||
ANDI r37, r37, 255d
|
ANDI r38, r38, 255d
|
||||||
ANDI r35, r35, 255d
|
ANDI r36, r36, 255d
|
||||||
JEQ r37, r35, :6
|
JEQ r38, r36, :6
|
||||||
LI64 r1, 42d
|
LI64 r1, 42d
|
||||||
JMP :3
|
JMP :3
|
||||||
6: JAL r31, r0, :decide
|
6: JAL r31, r0, :decide
|
||||||
LI32 r38, 0w
|
LI32 r39, 0w
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :7
|
JNE r1, r0, :7
|
||||||
CP r39, r38
|
CP r40, r39
|
||||||
JMP :8
|
JMP :8
|
||||||
7: LI32 r39, 2147483649w
|
7: LI32 r40, 2147483649w
|
||||||
8: ANDI r39, r39, 4294967295d
|
8: ANDI r40, r40, 4294967295d
|
||||||
ANDI r38, r38, 4294967295d
|
ANDI r39, r39, 4294967295d
|
||||||
JNE r39, r38, :9
|
JNE r40, r39, :9
|
||||||
LI64 r1, 69d
|
LI64 r1, 69d
|
||||||
JMP :3
|
JMP :3
|
||||||
9: ADDI64 r3, r254, 40d
|
9: ADDI64 r3, r254, 40d
|
||||||
CP r40, r3
|
CP r41, r3
|
||||||
JAL r31, r0, :new_foo
|
JAL r31, r0, :new_foo
|
||||||
ST r1, r254, 40a, 16h
|
ST r1, r254, 40a, 16h
|
||||||
LI64 r32, 0d
|
LI64 r42, 0d
|
||||||
LD r41, r254, 40a, 8h
|
LD r43, r254, 40a, 8h
|
||||||
JNE r41, r32, :10
|
JNE r43, r42, :10
|
||||||
LI64 r1, 999d
|
LI64 r1, 999d
|
||||||
JMP :3
|
JMP :3
|
||||||
10: LRA r4, r0, :"foo\0"
|
10: LRA r4, r0, :"foo\0"
|
||||||
CP r3, r40
|
CP r3, r41
|
||||||
CP r2, r3
|
CP r2, r3
|
||||||
LD r2, r2, 0a, 16h
|
LD r2, r2, 0a, 16h
|
||||||
JAL r31, r0, :use_foo
|
JAL r31, r0, :use_foo
|
||||||
ADDI64 r42, r254, 0d
|
ADDI64 r44, r254, 0d
|
||||||
JAL r31, r0, :no_foo
|
JAL r31, r0, :no_foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
JAL r31, r0, :decide
|
JAL r31, r0, :decide
|
||||||
|
@ -68,11 +70,9 @@ main:
|
||||||
JMP :12
|
JMP :12
|
||||||
11: CP r2, r33
|
11: CP r2, r33
|
||||||
ST r2, r254, 0a, 8h
|
ST r2, r254, 0a, 8h
|
||||||
LI64 r43, 1d
|
ST r35, r254, 8a, 8h
|
||||||
ST r43, r254, 8a, 8h
|
12: LD r45, r254, 0a, 8h
|
||||||
ST r43, r254, 72a, 8h
|
JNE r45, r42, :13
|
||||||
12: LD r44, r254, 0a, 8h
|
|
||||||
JNE r44, r32, :13
|
|
||||||
LI64 r1, 34d
|
LI64 r1, 34d
|
||||||
JMP :3
|
JMP :3
|
||||||
13: ADDI64 r1, r254, 16d
|
13: ADDI64 r1, r254, 16d
|
||||||
|
@ -81,19 +81,19 @@ main:
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :14
|
JNE r1, r0, :14
|
||||||
JMP :15
|
JMP :15
|
||||||
14: ST r35, r254, 16a, 1h
|
14: ST r36, r254, 16a, 1h
|
||||||
15: LD r45, r254, 16a, 1h
|
15: LD r46, r254, 16a, 1h
|
||||||
ANDI r45, r45, 255d
|
ANDI r46, r46, 255d
|
||||||
ANDI r35, r35, 255d
|
ANDI r36, r36, 255d
|
||||||
JEQ r45, r35, :16
|
JEQ r46, r36, :16
|
||||||
LI64 r1, 420d
|
LI64 r1, 420d
|
||||||
JMP :3
|
JMP :3
|
||||||
16: LD r46, r254, 0a, 8h
|
16: LD r47, r254, 0a, 8h
|
||||||
LD r47, r46, 0a, 8h
|
LD r48, r47, 0a, 8h
|
||||||
ANDI r48, r39, 65535d
|
ANDI r49, r40, 65535d
|
||||||
SUB64 r1, r48, r47
|
SUB64 r1, r49, r48
|
||||||
3: LD r31, r254, 80a, 144h
|
3: LD r31, r254, 80a, 152h
|
||||||
ADDI64 r254, r254, 224d
|
ADDI64 r254, r254, 232d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
new_bar:
|
new_bar:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -24d
|
||||||
|
|
6
lang/tests/son_tests_stack_provenance.txt
Normal file
6
lang/tests/son_tests_stack_provenance.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
test.hb:5:23: returning value with local provenance (pointer will be invalid after function returns)
|
||||||
|
dangle := fn(): ^uint return &0
|
||||||
|
^
|
||||||
|
test.hb:5:30: ...the pointer points to stack allocation created here
|
||||||
|
dangle := fn(): ^uint return &0
|
||||||
|
^
|
Loading…
Reference in a new issue