diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index fefff2f..062917c 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -368,19 +368,15 @@ impl<'a, F: Function> Env<'a, F> { self.liveins[block.index()] = live; } - // Check that there are no liveins to the entry block. (The - // client should create a virtual intsruction that defines any - // PReg liveins if necessary.) - if self.liveins[self.func.entry_block().index()] - .iter() - .next() - .is_some() - { - trace!( - "non-empty liveins to entry block: {:?}", - self.liveins[self.func.entry_block().index()] - ); - return Err(RegAllocError::EntryLivein); + // Check that there are no liveins to the entry block, except + // for pinned vregs. (The client should create a virtual + // instruction that defines any other liveins if necessary.) + for livein in self.liveins[self.func.entry_block().index()].iter() { + let livein = self.vreg_regs[livein]; + if self.func.is_pinned_vreg(livein).is_none() { + trace!("non-pinned-vreg livein to entry block: {}", livein); + return Err(RegAllocError::EntryLivein); + } } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 73a6c1c..29521ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -977,6 +977,11 @@ pub trait Function { /// liverange computation will check that this is the case (that /// there are enough remaining allocatable pregs of every class to /// hold all Reg-constrained operands). + /// + /// Pinned vregs are implicitly live-in to the function: that is, + /// one can use a pinned vreg without having first defined it, and + /// this will take the value that that physical register (to which + /// the vreg is pinned) had at function entry. fn is_pinned_vreg(&self, _: VReg) -> Option { None }