const moveSpills … const logSpills … const regDebug … const stackDebug … const likelyDistance … const normalDistance … const unlikelyDistance … // regalloc performs register allocation on f. It sets f.RegAlloc // to the resulting allocation. func regalloc(f *Func) { … } type register … const noRegister … var noRegisters … type regMask … func (m regMask) String() string { … } func (s *regAllocState) RegMaskString(m regMask) string { … } // countRegs returns the number of set bits in the register mask. func countRegs(r regMask) int { … } // pickReg picks an arbitrary register from the register mask. func pickReg(r regMask) register { … } type use … type valState … type regState … type regAllocState … type endReg … type startReg … // freeReg frees up register r. Any current user of r is kicked out. func (s *regAllocState) freeReg(r register) { … } // freeRegs frees up all registers listed in m. func (s *regAllocState) freeRegs(m regMask) { … } // clobberRegs inserts instructions that clobber registers listed in m. func (s *regAllocState) clobberRegs(m regMask) { … } // setOrig records that c's original value is the same as // v's original value. func (s *regAllocState) setOrig(c *Value, v *Value) { … } // assignReg assigns register r to hold c, a copy of v. // r must be unused. func (s *regAllocState) assignReg(r register, v *Value, c *Value) { … } // allocReg chooses a register from the set of registers in mask. // If there is no unused register, a Value will be kicked out of // a register to make room. func (s *regAllocState) allocReg(mask regMask, v *Value) register { … } // makeSpill returns a Value which represents the spilled value of v. // b is the block in which the spill is used. func (s *regAllocState) makeSpill(v *Value, b *Block) *Value { … } // allocValToReg allocates v to a register selected from regMask and // returns the register copy of v. Any previous user is kicked out and spilled // (if necessary). Load code is added at the current pc. If nospill is set the // allocated register is marked nospill so the assignment cannot be // undone until the caller allows it by clearing nospill. Returns a // *Value which is either v or a copy of v allocated to the chosen register. func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value { … } // isLeaf reports whether f performs any calls. func isLeaf(f *Func) bool { … } // needRegister reports whether v needs a register. func (v *Value) needRegister() bool { … } func (s *regAllocState) init(f *Func) { … } func (s *regAllocState) close() { … } // Adds a use record for id at distance dist from the start of the block. // All calls to addUse must happen with nonincreasing dist. func (s *regAllocState) addUse(id ID, dist int32, pos src.XPos) { … } // advanceUses advances the uses of v's args from the state before v to the state after v. // Any values which have no more uses are deallocated from registers. func (s *regAllocState) advanceUses(v *Value) { … } // Drop v from registers if it isn't used again, or its only uses are after // a call instruction. func (s *regAllocState) dropIfUnused(v *Value) { … } // liveAfterCurrentInstruction reports whether v is live after // the current instruction is completed. v must be used by the // current instruction. func (s *regAllocState) liveAfterCurrentInstruction(v *Value) bool { … } // Sets the state of the registers to that encoded in regs. func (s *regAllocState) setState(regs []endReg) { … } // compatRegs returns the set of registers which can store a type t. func (s *regAllocState) compatRegs(t *types.Type) regMask { … } // regspec returns the regInfo for operation op. func (s *regAllocState) regspec(v *Value) regInfo { … } func (s *regAllocState) isGReg(r register) bool { … } var tmpVal … func (s *regAllocState) regalloc(f *Func) { … } func (s *regAllocState) placeSpills() { … } // shuffle fixes up all the merge edges (those going into blocks of indegree > 1). func (s *regAllocState) shuffle(stacklive [][]ID) { … } type edgeState … type contentRecord … type dstRecord … // setup initializes the edge state for shuffling. func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive []ID) { … } // process generates code to move all the values to the right destination locations. func (e *edgeState) process() { … } // processDest generates code to put value vid into location loc. Returns true // if progress was made. func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool { … } // set changes the contents of location loc to hold the given value and its cached representative. func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.XPos) { … } // erase removes any user of loc. func (e *edgeState) erase(loc Location) { … } // findRegFor finds a register we can use to make a temp copy of type typ. func (e *edgeState) findRegFor(typ *types.Type) Location { … } // rematerializeable reports whether the register allocator should recompute // a value instead of spilling/restoring it. func (v *Value) rematerializeable() bool { … } type liveInfo … // computeLive computes a map from block ID to a list of value IDs live at the end // of that block. Together with the value ID is a count of how many instructions // to the next use of that value. The resulting map is stored in s.live. // computeLive also computes the desired register information at the end of each block. // This desired register information is stored in s.desired. // TODO: this could be quadratic if lots of variables are live across lots of // basic blocks. Figure out a way to make this function (or, more precisely, the user // of this function) require only linear size & time. func (s *regAllocState) computeLive() { … } type desiredState … type desiredStateEntry … func (d *desiredState) clear() { … } // get returns a list of desired registers for value vid. func (d *desiredState) get(vid ID) [4]register { … } // add records that we'd like value vid to be in register r. func (d *desiredState) add(vid ID, r register) { … } func (d *desiredState) addList(vid ID, regs [4]register) { … } // clobber erases any desired registers in the set m. func (d *desiredState) clobber(m regMask) { … } // copy copies a desired state from another desiredState x. func (d *desiredState) copy(x *desiredState) { … } // remove removes the desired registers for vid and returns them. func (d *desiredState) remove(vid ID) [4]register { … } // merge merges another desired state x into d. func (d *desiredState) merge(x *desiredState) { … }