blob: 1bdd9cadb10ba394dccd3014330cdc25a8cf80fb [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 Intel, Pavel A. Ozhdikhin
*
*/
#ifndef _OPND_H_
#define _OPND_H_
#include <iostream>
#include "open/types.h"
#include "Type.h"
#include "MemoryManager.h"
namespace Jitrino {
class Inst;
class OpndManager;
class OpndRenameTable;
class IRBuilder;
//
// forward declarations
//
class SsaOpnd;
class SsaTmpOpnd;
class SsaVarOpnd;
class VarOpnd;
class PiOpnd;
class OpndBase { // rename to Opnd
public:
virtual ~OpndBase() {}
U_32 getId() const {return id;}
Type* getType() const {return type;}
void setType(Type *t) {type = t;}
void setProperties(U_32 v) {properties = v;}
U_32 getProperties() const {return properties;}
//
// methods for dynamic type checking and casting
//
bool isNull() const {return (type == NULL);}
virtual bool isVarOpnd() const {return false;}
virtual bool isSsaOpnd() const {return false;}
virtual bool isSsaVarOpnd() const {return false;}
virtual bool isSsaTmpOpnd() const {return false;}
virtual bool isPiOpnd() const {return false;}
SsaTmpOpnd* asSsaTmpOpnd() const {
return isSsaTmpOpnd()?(SsaTmpOpnd*)this:NULL;
}
SsaVarOpnd* asSsaVarOpnd() const {
return isSsaVarOpnd()?(SsaVarOpnd*)this:NULL;
}
VarOpnd* asVarOpnd() const {
return isVarOpnd()?(VarOpnd*)this:NULL;
}
SsaOpnd* asSsaOpnd() const {
return isSsaOpnd()?(SsaOpnd*)this:NULL;
}
PiOpnd* asPiOpnd() {
return isPiOpnd()?(PiOpnd*)this:NULL;
}
//
// for debug only
//
virtual void print(::std::ostream&) const {}
virtual void printWithType(::std::ostream& os) const;
protected:
//
// Constructor
//
OpndBase(Type* t,U_32 i) : properties(0), type(t), id(i) {}
//
// default constructor creates a null opnd
//
OpndBase() : properties(0), type(NULL), id(0) {}
private:
friend class OpndManager;
U_32 properties;
Type* type;
//
// used by code generator to map to back end operand
//
U_32 id;
};
class Opnd : public OpndBase {
public:
virtual ~Opnd() {}
void setIsGlobal(bool val) {isGlobalFlag = val;}
bool isGlobal() const {return isGlobalFlag;}
//
// eventually move these down 1 level to SsaOpnd
//
Inst* getInst() const {assert(!isVarOpnd()); return inst;}
void setInst(Inst* i) {assert(!isVarOpnd()); inst = i;}
public:
virtual void print(::std::ostream&) const;
protected:
friend class OpndManager;
Opnd(Type* t,U_32 i) : OpndBase(t,i), isGlobalFlag(false), inst(NULL) {}
Opnd() : OpndBase(), isGlobalFlag(false), inst(NULL) {}
bool isGlobalFlag;
//
// move down to SsaOpnd
//
Inst* inst; // only for single-assignment opnds (tmp & ssa)
};
class SsaOpnd : public Opnd {
public:
virtual ~SsaOpnd() {}
virtual bool isSsaOpnd() const {return true;}
protected:
friend class OpndManager;
SsaOpnd(Type* t,U_32 i) : Opnd(t,i)
{}
};
class SsaTmpOpnd : public SsaOpnd {
public:
virtual ~SsaTmpOpnd() {}
virtual bool isSsaTmpOpnd() const {return true;}
private:
friend class OpndManager;
SsaTmpOpnd(Type* t,U_32 i) : SsaOpnd(t,i) {}
};
class PiOpnd : public SsaOpnd {
public:
virtual ~PiOpnd() {}
virtual bool isSsaTmpOpnd() const {return false;};
virtual bool isPiOpnd() const {return true;};
const Opnd *getOrg() const { return orgOpnd; };
Opnd *getOrg() { return orgOpnd; };
virtual void print(::std::ostream&) const;
private:
friend class OpndManager;
PiOpnd(Opnd *orgOpnd0, U_32 i) :
SsaOpnd(orgOpnd0->getType(),i),
orgOpnd(orgOpnd0)
{};
Opnd *orgOpnd;
};
class VarAccessInst;
class VarOpnd : public Opnd {
public:
virtual ~VarOpnd() {}
virtual bool isVarOpnd() const {return true;}
bool isAddrTaken() const {return isAddrTakenFlag;}
void setAddrTaken() {isAddrTakenFlag = true;}
bool isPinned() const {return isPinnedFlag;}
U_32 getNumLoads() const {return numLoads;}
U_32 getNumStores() const {return numStores;}
VarOpnd* getNextVarOpnd() {return nextVarInMethod;}
VarOpnd* getPrevVarOpnd() {return prevVarInMethod;}
void addVarAccessInst(VarAccessInst*);
VarAccessInst* getVarAccessInsts() {return varAccessInsts;}
bool isDead() const {return isDeadFlag;}
void setDeadFlag(bool flag) { isDeadFlag = flag; }
//
// debug only
//
void print(::std::ostream& os) const;
virtual void printWithType(::std::ostream& os) const;
private:
friend class OpndManager;
VarOpnd(Type* t,U_32 i,VarOpnd* next,bool isPinned)
: Opnd(t,i), nextVarInMethod(0), prevVarInMethod(0),varAccessInsts(NULL)
{
isPinnedFlag = isPinned;
isDeadFlag = isAddrTakenFlag = false;
numLoads = numStores = 0;
if (next) {
assert(next->prevVarInMethod->nextVarInMethod == next);
nextVarInMethod = next;
prevVarInMethod = next->prevVarInMethod;
next->prevVarInMethod = this;
prevVarInMethod->nextVarInMethod= this;
} else {
nextVarInMethod = this;
prevVarInMethod = this;
}
}
//
// private fields
//
bool isDeadFlag;
bool isPinnedFlag;
bool isAddrTakenFlag;
U_32 numLoads;
U_32 numStores;
VarOpnd* nextVarInMethod;
VarOpnd* prevVarInMethod;
VarAccessInst* varAccessInsts; // ldvar, stvars that access this var
};
//
//
//
class SsaVarOpnd : public SsaOpnd {
public:
virtual ~SsaVarOpnd() {}
virtual bool isSsaVarOpnd() const {return true;}
VarOpnd* getVar() {return var;}
//
// debug only
//
virtual void print(::std::ostream& os) const;
virtual void printWithType(::std::ostream& os) const;
void setVar(VarOpnd *newvar) {
assert(newvar->getType() == var->getType());
var = newvar;
};
private:
friend class OpndManager;
SsaVarOpnd(U_32 i, VarOpnd* v) : SsaOpnd(v->getType(),i), var(v) {}
VarOpnd* var;
};
class NullOpnd : public Opnd {
};
class OpndManager {
public:
OpndManager(TypeManager& tm,MemoryManager& mm)
: typeManager(tm), memManager(mm) {
nextPiOpndId=nextSsaOpndId=nextVarId=1;
varOpnds = NULL;
numArgs = 0;
}
SsaTmpOpnd* createSsaTmpOpnd(Type* type) {
return new (memManager)
SsaTmpOpnd(getOpndTypeFromLdType(type),nextSsaOpndId++);
}
SsaTmpOpnd* createArgOpnd(Type* type) {
numArgs++;
return createSsaTmpOpnd(type);
}
VarOpnd* createVarOpnd(Type* type,bool isPinned) {
varOpnds = new (memManager)
VarOpnd(getOpndTypeFromLdType(type),nextVarId++,varOpnds,isPinned);
return varOpnds;
}
SsaVarOpnd* createSsaVarOpnd(VarOpnd* var) {
return new (memManager) SsaVarOpnd(nextSsaOpndId++,var);
}
PiOpnd* createPiOpnd(Opnd* orgOpnd) {
return new (memManager) PiOpnd(orgOpnd, nextPiOpndId++);
}
//
// Instruction Opnds can have only a subset of types. This method converts
// from the general set of types to the legal set of types for opnds.
//
Type* getOpndTypeFromLdType(Type* ldType);
//
// Change DefUse so that it does not depend on the Opnd::id
// Use a hashtable instead.
//
int getUniqueId(Opnd *op) {
int id = op->getId();
if (op->isVarOpnd()) id += (nextSsaOpndId-1);
return id;
}
static Opnd* getNullOpnd() {return &_nullOpnd;}
VarOpnd* getVarOpnds() {return varOpnds;}
U_32 getNumVarOpnds() {return nextVarId;}
U_32 getNumSsaOpnds() {return nextSsaOpndId;}
U_32 getNumArgs() {return numArgs;}
U_32 getNumPiOpnds() {return nextPiOpndId;}
void deleteVar(VarOpnd *var);
private:
//
// private fields
//
static NullOpnd _nullOpnd;
U_32 nextSsaOpndId;
U_32 nextPiOpndId;
U_32 nextVarId;
U_32 numArgs;
VarOpnd* varOpnds;
TypeManager& typeManager;
MemoryManager& memManager;
};
class OpndRenameTable : public HashTable<Opnd,Opnd> {
public:
OpndRenameTable(MemoryManager& mm, U_32 size = 16, bool renameSSA = true):
HashTable<Opnd,Opnd>(mm,size) {renameSsaOpnd = renameSSA;}
virtual ~OpndRenameTable() {}
Opnd *getMapping(Opnd *from) {return lookup(from); }
void setMapping(Opnd *from, Opnd *to) {
insert(from,to);
}
Opnd* rename(Opnd* opndToRename) {
// if the argument is in the rename table, take it
// otherwise use the original operand
Opnd *lkp = getMapping(opndToRename);
if (lkp != NULL)
return lkp;
return opndToRename;
}
Opnd* duplicate(OpndManager& opndManager, Opnd* opndToRename);
protected:
virtual bool keyEquals(Opnd* key1,Opnd* key2) const {
return key1 == key2;
}
virtual U_32 getKeyHashCode(Opnd* key) const {
// return hash of address bits
return (key ? key->getId() : 0);
}
private:
bool renameSsaOpnd;
};
} //namespace Jitrino
#endif // _OPND_H_