blob: 8237dc269d13ec1ac7ff89ef272c90d8931aa1f2 [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, Konstantin M. Anisimov, Igor V. Chebykin
*
*/
#include "IpfInstrumentator.h"
#include "IpfIrPrinter.h"
#include "VMInterface.h"
#include <fstream>
namespace Jitrino {
namespace IPF {
//========================================================================================//
// IrPrinter
//========================================================================================//
Instrumentator::Instrumentator(Cfg &cfg) :
mm(cfg.getMM()),
opndManager(cfg.getOpndManager()),
cfg(cfg) {
}
//----------------------------------------------------------------------------------------//
void Instrumentator::instrument() {
instrumentStart();
instrumentEnd();
opndManager->setContainCall(true);
}
//----------------------------------------------------------------------------------------//
void Instrumentator::instrumentStart() {
InstVector instCode(mm);
uint64 funcDescPtr = (uint64) Instrumentator::methodStart; // get function descriptor address
genNativeCall(funcDescPtr, instCode);
BbNode *enterNode = cfg.getEnterNode();
InstVector &insts = enterNode->getInsts();
insts.insert(insts.end(), instCode.begin(), instCode.end());
IPF_LOG << endl << " Method start:" << endl << IrPrinter::toString(instCode);
}
//----------------------------------------------------------------------------------------//
void Instrumentator::instrumentEnd() {
InstVector instCode(mm);
uint64 funcDescPtr = (uint64) Instrumentator::methodEnd; // get function descriptor address
genNativeCall(funcDescPtr, instCode); // gen call of "methodEnd"
NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get nodes
for(uint16 i=0; i<nodes.size(); i++) { // iterate through CFG nodes
if (nodes[i]->getNodeKind() != NODE_BB) continue; // ignore non BB node
BbNode *node = (BbNode *)nodes[i];
InstVector &insts = node->getInsts(); // get node's insts
if (insts.size() == 0) continue; //
CompVector &comps = insts.back()->getComps(); // get last inst completers
if (comps.size()<1 || comps[0]!=CMPLT_BTYPE_RET) continue; // if the inst is not "ret" - ignore
// MethodDesc *methodDesc = cfg.getMethodDesc();
// Type *type = methodDesc->getMethodSig()->getReturnType();
//
// if (type->isVoid()) {
insts.insert(insts.end()-1, instCode.begin(), instCode.end());
// } else {
// insts.insert(insts.end()-2, instCode.begin(), instCode.end());
// }
}
IPF_LOG << endl << " Method end:" << endl << IrPrinter::toString(instCode);
}
//----------------------------------------------------------------------------------------//
void Instrumentator::genNativeCall(uint64 funcDescPtr, InstVector &insts) {
/*
DrlVMMethodDesc *methodDesc = (DrlVMMethodDesc *) cfg.getMethodDesc();
Method_Handle methodHandle = methodDesc->getDrlVMMethod();
Opnd *methodDescAddr = opndManager->newImm((uint64) methodHandle);
Opnd *p0 = opndManager->getP0();
Opnd *r0 = opndManager->getR0();
Opnd *b0 = opndManager->getB0();
Opnd *r1 = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, 1);
Opnd *funDescAddr = opndManager->newImm(funcDescPtr);
Opnd *globalPtrAddr = opndManager->newImm(funcDescPtr + 8);
Opnd *entryPointer = opndManager->newRegOpnd(OPND_G_REG, DATA_U64);
Opnd *globalPtrBak = opndManager->newRegOpnd(OPND_G_REG, DATA_U64);
Opnd *globalPtr = opndManager->newRegOpnd(OPND_G_REG, DATA_U64);
Opnd *callTgt = opndManager->newRegOpnd(OPND_B_REG, DATA_U64);
Opnd *callArg = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, opndManager->newOutReg(0));
// load entry pointer
insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, entryPointer, funDescAddr));
insts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, entryPointer, entryPointer));
// save global pointer
insts.push_back(new(mm) Inst(mm, INST_MOV, p0, globalPtrBak, r1));
// load new global pointer
insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, globalPtr, globalPtrAddr));
insts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, r1, globalPtr));
// make call
insts.push_back(new(mm) Inst(mm, INST_MOVL, p0, callArg, methodDescAddr));
insts.push_back(new(mm) Inst(mm, INST_MOV, p0, callTgt, entryPointer));
insts.push_back(new(mm) Inst(mm, INST_BR13, CMPLT_BTYPE_CALL, p0, r0, b0, callTgt, callArg, r1));
// restore global pointer
insts.push_back(new(mm) Inst(mm, INST_MOV, p0, r1, globalPtrBak));
insts.push_back(new(mm) Inst(mm, INST_USE, p0, r1));
*/
}
//----------------------------------------------------------------------------------------//
void Instrumentator::methodStart(Method_Handle methodHandle) {
ofstream rtLog;
rtLog.open("rt.log", ios::out | ios::app);
rtLog << "Start " << methodHandle << endl;
rtLog.close();
}
//----------------------------------------------------------------------------------------//
void Instrumentator::methodEnd(Method_Handle methodHandle) {
ofstream rtLog;
rtLog.open("rt.log", ios::out | ios::app);
rtLog << "End " << methodHandle << endl;
}
} // IPF
} // Jitrino