blob: 64cc3ee9b19ea8b1ff7313543a37ef101a116b09 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/**
* @author Alexander Astapchuk
*/
#if !defined(__IA32_CGUTILS_INCLUDED__)
#define __IA32_CGUTILS_INCLUDED__
#include "Ia32IRManager.h"
namespace Jitrino {
namespace Ia32 {
class IRManagerHolder {
public:
IRManagerHolder()
{
m_irManager = NULL;
}
void setIRManager(IRManager* irm)
{
m_irManager = irm;
}
IRManager* getIRManager(void)
{
return m_irManager;
}
protected:
IRManager* m_irManager;
};
/**
* A mix-in that provides various Opnd manipulations IRManager.
*/
class OpndUtils : virtual protected IRManagerHolder {
public:
OpndUtils()
{
m_opndIntZero = NULL;
m_opndDoubleZero = NULL;
m_opndFloatZero = NULL;
}
/**
* Tests whether the Opnd has only one def.
*/
static bool isSingleDef(const Opnd* opnd);
/**
* Tests whether the given operand is placed on (any) register and
* optionally test against the specified RegName (\c what).
*/
static bool isReg(const Opnd* op, RegName what = RegName_Null);
/**
* Tests whether the given operand is placed on XMM register and
* optionally test against the specified RegName (\c what).
*/
static bool isXmmReg(const Opnd* op, RegName what = RegName_Null);
/**
* Tests whether the given operand is placed on memory.
*/
static bool isMem(const Opnd* op);
/**
* Tests whether the operand is immediate.
*
* @note The method only returns \n true for immediate-s without
* RuntimeInfo. This is because the real value of immediate with
* RuntimeInfo is unknown until very last - they get resolved only
* in CodeEmitter.
*/
static bool isImm(const Opnd* op);
/**
* Tests whether the Opnd is immediate and has the provided value.
*
* @note See note at isImm(const Opnd* op).
*/
static bool isImm(const Opnd* op, int iVal);
/**
* Tests whether the Opnd is immediate of the zero value.
*
* No more than a named shortcut for isImm(op, 0).
*/
static bool isZeroImm(const Opnd* op);
/**
* Tests whether the Opnd is Type::Int8 immediate.
*
* @note See note at isImm(const Opnd* op).
*/
static bool isImm8(const Opnd* op);
/**
* Tests whether the Opnd is Type::Int32 immediate.
*
* @note See note at isImm(const Opnd* op).
*/
static bool isImm32(const Opnd* op);
/**
* Tests whether the Opnd is an immediate (note: of \b any type)
* and whether it is equal to the provided value.
*
* @note See note at isImm(const Opnd* op).
*/
static bool isFPConst(const Opnd* op, double d);
/**
* Tests whether the Opnd is an immediate (note: of \b any type)
* and whether it is equal to the provided value.
*
* @note See note at isImm(const Opnd* op).
*/
static bool isFPConst(const Opnd* op, float f);
/**
* Tests whether the Opnd is a constant area item.
*/
static bool isConstAreaItem(const Opnd* op);
/**
* Extracts address of constant area item.
*
* @return NULL if \c op is not a constant area item.
*/
static const void* extractAddrOfConst(const Opnd* op);
/**
* Extracts integer constant from constant area item.
*
* @note The \c op must be the constant item.
*/
static int extractIntConst(const Opnd* op);
/**
* Extracts double constant from constant area item.
*
* @note The \c op must be the constant item.
*/
static double extractDoubleConst(const Opnd* op);
/**
* Extracts float constant from constant area item.
*
* @note The \c op must be the constant item.
*/
static float extractFloatConst(const Opnd* op);
/**
* Tests whether the provided Opnd is immediate and its value may be
* placed in a single byte.
*/
static bool fitsImm8(const Opnd* op);
/**
* Tests 2 operands for equality.
*/
static bool equals(const Opnd* a, const Opnd* b);
/**
* Searches for a source of an immediate value (if any) of the specified operand.
* Returns the "defining" operand or \c NULL.
*/
static Opnd* findImmediateSource(Opnd* opnd);
//
// The following are not static and require IRManager
//
Opnd* convertImmToImm8(Opnd* imm);
Opnd* convertToXmmReg64(Opnd* xmmReg);
Opnd* getIntZeroConst(void);
Opnd* getDoubleZeroConst(void);
Opnd* getFloatZeroConst(void);
Opnd* getZeroConst(Type* type);
private:
Opnd* m_opndIntZero;
Opnd* m_opndDoubleZero;
Opnd* m_opndFloatZero;
};
class InstUtils : virtual protected IRManagerHolder {
public:
static void replaceInst(Inst* old, Inst* brandNewInst);
static void replaceOpnd(Inst* inst, unsigned index, Opnd* newOpnd);
static bool instMustHaveBCMapping(Inst* inst);
};
class SubCfgBuilderUtils : virtual protected IRManagerHolder {
public:
SubCfgBuilderUtils()
{
m_subCFG = NULL;
m_currNode = NULL;
}
/**
* Creates new sub CFG and makes it current.
*/
ControlFlowGraph* newSubGFG(bool withReturn=true, bool withUnwind=false);
/**
* Creates new basic block and makes it current.
*/
BasicBlock* newBB(void);
/**
* Sets current node to operate on.
*/
Node* setCurrentNode(Node* node);
/**
* Returns current node.
*/
Node* getCurrentNode(void) const;
/**
* Returns entry node of current subCFG.
*/
Node* getSubCfgEntryNode(void);
/**
* Returns return node of current subCFG.
*/
Node* getSubCfgReturnNode(void);
/**
* Sets current subCFG to operate on.
*/
ControlFlowGraph* setSubCFG(ControlFlowGraph* subCFG);
/**
* Returns current subCFG.
*/
ControlFlowGraph* getSubCFG(void);
/**
* Replaces the given Inst with the subCFG just built, and clears
* current subCFG.
*
* Also invokes minor cleanup on CFG when \c purgeEmptyNodes == \c true.
*/
void propagateSubCFG(Inst* inst, bool purgeEmptyNodes = true);
/**
* Creates an instruction with the given mnemonic and arguments and
* adds it to the end of current node.
*
* Special handling for Mnemonic_MOV: CopyPseudoInstruction
* is generated.
*/
Inst* newInst(Mnemonic mn, unsigned defsCount,
Opnd* op0 = NULL, Opnd* op1 = NULL, Opnd* op2 = NULL,
Opnd* op3 = NULL, Opnd* op4 = NULL, Opnd* op5 = NULL);
/**
* Creates an instruction with the given mnemonic and arguments and
* adds it to the end of current node.
*
* Special handling for Mnemonic_MOV: CopyPseudoInstruction
* is generated.
*/
Inst* newInst(Mnemonic mn,
Opnd* op0 = NULL, Opnd* op1 = NULL, Opnd*op2 = NULL);
/**
* Generates branch instruction with the given mnemonic and given target
* nodes, adds it to the end of current node, and also adds edges
* from current to provided nodes.
*/
Inst* newBranch(Mnemonic mn, Node* trueTarget, Node* falseTarget,
double trueProbability=0.5, double falseProbability=0.5);
/**
* Creates an edge from the current node to the specified node.
*/
void connectNodeTo(Node* to);
/**
* Creates an edge from \c from node, to the \c to node.
*/
void connectNodes(Node* from, Node* to);
private:
ControlFlowGraph * m_subCFG;
Node* m_currNode;
};
}}; // ~namespace Jitrino::Ia32
#endif // ~ifndef __IA32_CGUTILS_INCLUDED__