blob: 06752892ef71f1232332904132a8397902d4a848 [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 Vyacheslav P. Shakin
*/
#ifndef _IA32_CONSTRAINT_H_
#define _IA32_CONSTRAINT_H_
#include "open/types.h"
#include "Ia32IRConstants.h"
namespace Jitrino
{
namespace Ia32{
/**
class Constraint represents operand constraints and is used to
describe Ia32 irregularities
The constraint framework is similar to a lattice Null < other constraints < Any
with partial order set by the contains method
The constraint contains 4 fields:
OpndKind kind, OpndSize size, and register mask
Each constraint instance is exactly 4-bytes long making it possible to pass
it directly by value.
*/
class Constraint
{
public:
//----------------------------------------------------------------------
/** enum CompareResult represent results of Constraint::compare
The values are self-documenting
*/
enum CompareResult
{
CompareResult_Equal=0,
CompareResult_LeftContainsRight=1,
CompareResult_RightContainsLeft=-1,
CompareResult_NotEqual=2
};
//----------------------------------------------------------------------
/** Creates a Null constraint */
Constraint()
{ fullValue = 0;}
/** Creates a constraint of the specified OpndKind
This allows for passing of OpndKind values wherever Constraint is expected
The size of the constraint is set to OpndSize_Any
For OpndKind_Reg and sub-kinds initializes the mask field to 0xffff
*/
Constraint(OpndKind k)
:mask(OpndKind_Reg&k?0xffff:0), size(OpndSize_Any), kind(k)
{ assert(k!=OpndKind_Null); }
/** Creates a constraint of the specified OpndKind k and OpndSize s
Both k and s cannot be _Null.
If k contains OpndKind_Reg the constructor initializes the mask field to 0xffff
*/
Constraint(OpndKind k, OpndSize s)
:mask(OpndKind_Reg&k?0xffff:0), size(s), kind(k)
{ assert(k!=OpndKind_Null && size!=OpndSize_Null); }
/** Creates a constraint of the specified OpndKind, OpndSize, and register mask m
Both k and s cannot be _Null, and k must contain be OpndKind_Reg if mask is not null
For OpndKind_Reg and sub-kinds initializes the mask field to 0xffff
*/
Constraint(OpndKind k, OpndSize s, U_32 m)
:mask(m), size(s), kind(k)
{ assert(k!=OpndKind_Null && size!=OpndSize_Null); assert(mask==0||(OpndKind_Reg&k)!=0); }
/** Creates a constraint corresponding to the specified physical register RegName
This allows for passing of RegName values wherever Constraint is expected
The size of the constraint is initialized to the size for the specified RegName
returned by getRegSize(OpndKind)
The mask field of the constraint is initialized to the mask corresponding to the specified register
*/
Constraint(RegName reg)
:mask(getRegMask(reg)), size(getRegSize(reg)), kind(getRegKind(reg)) {}
Constraint(const char * str){ fullValue = 0; str=parse(str); assert(str!=NULL); }
const char * parse(const char * str);
//----------------------------------------------------------------------
/** returns the kind field of the constraint */
U_32 getKind()const{ return kind; }
/** returns the size field of the constraint */
OpndSize getSize()const{ return (OpndSize)size; }
/** returns the mask field of the constraint */
U_32 getMask()const{ return mask; }
/** sets the mask field of the constraint */
void setMask(U_32 m){ mask=m; }
/** resets the constraint to the Null value */
void makeNull(){ fullValue = 0; }
/** resets the constraint to the Any value */
void makeAny()
{ fullValue = OpndKind_Any|OpndSize_Any|0xffff; }
/** Convenience operator |
Creates a copy of 'this' constraint, unions it with c, and returns the result
*/
Constraint operator|(Constraint c)const
{ Constraint l=*this; l.unionWith(c); return l; }
/** Convenience operator &
Creates a copy of 'this' constraint, intersects it with c, and returns the result
*/
Constraint operator&(Constraint c)const
{ Constraint l=*this; l.intersectWith(c); return l; }
/** Returns true if the constraint is Null (its kind is Null) */
bool isNull()const{ return kind==OpndKind_Null; }
/** Returns the default size for the OpndKind combination k */
static OpndSize getDefaultSize(U_32 k);
/** Returns true if 'this' can be merged (via unionWith) with c
Sizes must be equal, and kinds cannot designate different reg kinds (like GPReg vs XMMReg)
Note: Null constraints are mergeable with any constraints
*/
bool canBeMergedWith(Constraint c)
{
U_32 filter = (U_32)OpndKind_Reg << 24;
U_32 thisTmp = fullValue & filter, cTmp = c.fullValue & filter, rTmp = thisTmp & cTmp;
if (rTmp!=thisTmp && rTmp!=cTmp)
return false;
filter = (U_32)OpndSize_Any << 16;
thisTmp = fullValue & filter, cTmp = c.fullValue & filter, rTmp = thisTmp & cTmp;
return rTmp==thisTmp || rTmp==cTmp;
}
/** Unions 'this' with c (|-like)
this must be mergeable with c (canBeMergedWith(c) must return true)
*/
Constraint& unionWith(Constraint c)
{ assert(canBeMergedWith(c)); fullValue |= c.fullValue; return *this; }
/** Intersects 'this' constraint with c (&-like) */
Constraint& intersectWith(Constraint c)
{
fullValue &= c.fullValue;
if (size==0 || kind==0) fullValue=0; else if (mask==0) kind&=~OpndKind_Reg;
return *this;
}
/** returns true if 'this' constrains contains c */
bool contains(Constraint c)const{ return (*this&c)==c; }
/** returns true if 'this' constraint exactly equals to c */
bool operator==(Constraint c)const
{ return fullValue == c.fullValue; }
bool operator!=(Constraint c)const
{ return fullValue != c.fullValue; }
/** Determines the relationship of between 'this' constraint and c
The semantics of the operation and possible result values are defined by the CompareResult enumeration
*/
CompareResult compare(Constraint c)const
{ return *this==c?CompareResult_Equal:contains(c)?CompareResult_LeftContainsRight:c.contains(*this)?CompareResult_RightContainsLeft:CompareResult_NotEqual; }
/** Returns the constraint for an outer aliased operand
s must be greater than or equal to the constraint's size
*/
Constraint getAliasConstraint(OpndSize s, U_32 offset=0)const;
/** Returns the regname for an aliased regname
In some sense this operations is reverse to getAliasConstraint.
e.g. for eax it can return eax, ax, ah, al, depending on the constraint
The constraint's size must be less than or equal to regName's size
*/
static RegName getAliasRegName(RegName regName, OpndSize s, U_32 offset=0);
RegName getAliasRegName(RegName regName, U_32 offset=0)const;
//----------------------------------------------------------------------
private:
union{
struct {
U_32 mask:16;
U_32 size:8;
U_32 kind:8;
};
U_32 fullValue;
};
friend struct DefaultConstraintInitializer;
const static Constraint nullConstraint;
};
}; // namespace Ia32
}
#endif