/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file contains target independent register alloction support.
*/
#include "compiler/CompilerUtility.h"
#include "compiler/CompilerIR.h"
#include "compiler/Dataflow.h"
#include "compiler/codegen/arm/ArmLIR.h"
/*
* Return most flexible allowed register class based on size.
* Bug: 2813841
* Must use a core register for data types narrower than word (due
* to possible unaligned load/store.
*/
static inline RegisterClass dvmCompilerRegClassBySize(OpSize size)
{
return (size == kUnsignedHalf ||
size == kSignedHalf ||
size == kUnsignedByte ||
size == kSignedByte ) ? kCoreReg : kAnyReg;
}
static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
{
assert(sReg != INVALID_SREG);
return DECODE_REG(dvmConvertSSARegToDalvik(cUnit, sReg));
}
/* Reset the tracker to unknown state */
static inline void dvmCompilerResetNullCheck(CompilationUnit *cUnit)
{
dvmClearAllBits(cUnit->regPool->nullCheckedRegs);
}
/*
* Get the "real" sreg number associated with an sReg slot. In general,
* sReg values passed through codegen are the SSA names created by
* dataflow analysis and refer to slot numbers in the cUnit->regLocation
* array. However, renaming is accomplished by simply replacing RegLocation
* entries in the cUnit->reglocation[] array. Therefore, when location
* records for operands are first created, we need to ask the locRecord
* identified by the dataflow pass what it's new name is.
*/
static inline int dvmCompilerSRegHi(int lowSreg) {
return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1;
}
static inline bool dvmCompilerLiveOut(CompilationUnit *cUnit, int sReg)
{
//TODO: fully implement
return true;
}
static inline int dvmCompilerSSASrc(MIR *mir, int num)
{
assert(mir->ssaRep->numUses > num);
return mir->ssaRep->uses[num];
}
extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
int regClass, bool update);
/* Mark a temp register as dead. Does not affect allocation state. */
extern void dvmCompilerClobber(CompilationUnit *cUnit, int reg);
extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit,
RegLocation loc);
/* see comments for updateLoc */
extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
RegLocation loc);
/* Clobber all of the temps that might be used by a handler. */
extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit);
extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg);
extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg);
extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg,
int highReg);
extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg);
extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg);
extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl);
/* Set up temp & preserved register pools specialized by target */
extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num);
/*
* Mark the beginning and end LIR of a def sequence. Note that
* on entry start points to the LIR prior to the beginning of the
* sequence.
*/
extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
LIR *start, LIR *finish);
/*
* Mark the beginning and end LIR of a def sequence. Note that
* on entry start points to the LIR prior to the beginning of the
* sequence.
*/
extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
LIR *start, LIR *finish);
extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
int low, int high);
extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
int low, int high);
// Get the LocRecord associated with an SSA name use.
extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num);
// Get the LocRecord associated with an SSA name def.
extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
int num);
extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit);
/* Clobber all regs that might be used by an external C call */
extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit);
extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg);
extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg);
extern int dvmCompilerAllocTemp(CompilationUnit *cUnit);
extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit);
//REDO: too many assumptions.
extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit);
extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg);
extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl);
extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit);
/* Kill the corresponding bit in the null-checked register list */
extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
RegLocation loc);
//FIXME - this needs to also check the preserved pool.
extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg);
/* To be used when explicitly managing register use */
extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit);
extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit);
extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit);
extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit);
extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit);
/* Clobber any temp associated with an sReg. Could be in either class */
extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg);
/* Return a temp if one is available, -1 otherwise */
extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit);
/*
* Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
* register. No check is made to see if the register was previously
* allocated. Use with caution.
*/
extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg);
extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
RegLocation rl);
/*
* Free all allocated temps in the temp pools. Note that this does
* not affect the "liveness" of a temp register, which will stay
* live until it is either explicitly killed or reallocated.
*/
extern void dvmCompilerResetRegPool(CompilationUnit *cUnit);
extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit);
extern void dvmCompilerFlushRegWide(CompilationUnit *cUnit, int reg1, int reg2);
extern void dvmCompilerFlushReg(CompilationUnit *cUnit, int reg);
/*
* Architecture-dependent register allocation routines implemented in
* ${TARGET_ARCH}/${TARGET_ARCH_VARIANT}/Ralloc.c
*/
extern int dvmCompilerAllocTypedTempPair(CompilationUnit *cUnit,
bool fpHint, int regClass);
extern int dvmCompilerAllocTypedTemp(CompilationUnit *cUnit, bool fpHint,
int regClass);
extern ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
extern void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo,
int destHi, int srcLo, int srcHi);
extern void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
int displacement, int rSrc, OpSize size);
extern void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
int displacement, int rSrcLo,
int rSrcHi);