From ef048b8899ebc35667c7e2de19702ca835ee0b04 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 2 Oct 2017 15:56:38 -0700 Subject: [PATCH] Allow for call args in incoming stack slots. A value passed as an argument to a function call may live in an incoming stack slot initially. Fix the call legalizer so it copies such an argument into the expected outgoing stack slot for the call. --- cranelift/filetests/isa/intel/abi64.cton | 12 ++++++++++++ lib/cretonne/src/legalizer/boundary.rs | 25 +++++++++--------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cranelift/filetests/isa/intel/abi64.cton b/cranelift/filetests/isa/intel/abi64.cton index 59f3107560..ec943203ee 100644 --- a/cranelift/filetests/isa/intel/abi64.cton +++ b/cranelift/filetests/isa/intel/abi64.cton @@ -18,3 +18,15 @@ function %f() { ebb0: return } + +function %pass_stack_int64(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm { + sig0 = (i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 vmctx) spiderwasm + fn0 = sig0 #00000000 + +ebb0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v8: i64, v9: i64, v10: i64, v11: i64, v12: i64, v13: i64, v14: i64, v15: i64, v16: i64, v17: i64, v18: i64, v19: i64, v20: i64): + call fn0(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) + jump ebb1 + +ebb1: + return +} diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 5522db921f..d1d48b053b 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -21,7 +21,7 @@ use abi::{legalize_abi_value, ValueConversion}; use cursor::{Cursor, FuncCursor}; use flowgraph::ControlFlowGraph; use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef, - ArgumentType, ArgumentPurpose, ArgumentLoc, ValueLoc, StackSlotKind}; + ArgumentType, ArgumentPurpose, ArgumentLoc, ValueLoc}; use ir::instructions::CallInfo; use isa::TargetIsa; use legalizer::split::{isplit, vsplit}; @@ -651,21 +651,14 @@ fn spill_call_arguments(pos: &mut FuncCursor) -> bool { .filter_map(|(idx, (&arg, abi))| { match abi.location { ArgumentLoc::Stack(offset) => { - // Is `arg` already in the right kind of stack slot? - match locations.get(arg) { - Some(&ValueLoc::Stack(ss)) => { - // We won't reassign `arg` to a different stack slot. Assert out of - // the stack slot is wrong. - assert_eq!(stack_slots[ss].kind, StackSlotKind::OutgoingArg); - assert_eq!(stack_slots[ss].offset, offset); - assert_eq!(stack_slots[ss].size, abi.value_type.bytes()); - None - } - _ => { - // Assign `arg` to a new stack slot. - let ss = stack_slots.get_outgoing_arg(abi.value_type, offset); - Some((idx, arg, ss)) - } + // Assign `arg` to a new stack slot, unless it's already in the correct + // slot. The legalization needs to be idempotent, so we should see a + // correct outgoing slot on the second pass. + let ss = stack_slots.get_outgoing_arg(abi.value_type, offset); + if locations[arg] != ValueLoc::Stack(ss) { + Some((idx, arg, ss)) + } else { + None } } _ => None,