gambas-source-code/gb.jit.llvm/src/jit_gambas_pass.cpp
gambas f39f7063ef Start working on the new jit system.
[COMPILER]
* NEW: Start working on the new jit system.

[GB.JIT]
* NEW: Rename the component as 'gb.jit.llvm'.
2018-05-17 01:13:56 +02:00

139 lines
3.9 KiB
C++

/***************************************************************************
jit_gambas_pass.cpp
gb.jit component
(c) 2012 Emil Lenngren <emil.lenngren [at] gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#include "llvm/Pass.h"
#if (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 3)
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Function.h"
#elif (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 2)
#include "llvm/IRBuilder.h"
#include "llvm/Function.h"
#else
#include "llvm/Support/IRBuilder.h"
#include "llvm/Function.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "main.h"
#ifdef __CYGWIN__
#define __finite finite
#define __isnan __isnand
#define __isinf __isinfd
#endif
#define FUNCTION_NAME(s) _FN(s)
#define _FN(s) #s
using namespace llvm;
namespace {
struct GambasPass : public FunctionPass {
static char ID;
GambasPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F);
};
}
char GambasPass::ID = 0;
static RegisterPass<GambasPass> X("gamabs-pass", "Gambas Pass", false, false);
FunctionPass* createGambasPass(){
return new GambasPass();
}
bool GambasPass::runOnFunction(Function &F){
IRBuilder<> Builder(F.getContext());
bool changed = false;
for(Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ){
ICmpInst* ICI = dyn_cast<ICmpInst>(I);
CallInst* CI = dyn_cast<CallInst>(I++);
if (ICI && ICI->hasMetadata() && ICI->getMetadata("unref_slt") && dyn_cast<LoadInst>(ICI->getOperand(0))){
ICI->replaceAllUsesWith(ConstantInt::get(ICI->getType(), false));
ICI->eraseFromParent();
changed = true;
continue;
}
if (!CI)
continue;
Function* callee = CI->getCalledFunction();
if (callee == NULL || !callee->isDeclaration())
continue;
StringRef name = callee->getName();
if (name == "JR_release_variant" || name == "JR_borrow_variant"){
ConstantInt* vtype_int = dyn_cast<ConstantInt>(CI->getArgOperand(0));
if (!vtype_int)
continue;
uint64_t vtype = vtype_int->getZExtValue();
if (TYPE_is_string(vtype) || TYPE_is_object(vtype))
continue;
CI->eraseFromParent();
changed = true;
} else if (name == FUNCTION_NAME(__finite)){
ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
if (!op)
continue;
int val = __finite(op->getValueAPF().convertToDouble());
Constant* res = ConstantInt::get(CI->getType(), val);
CI->replaceAllUsesWith(res);
CI->eraseFromParent();
changed = true;
} else if (name == FUNCTION_NAME(__isnan)){
ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
if (!op)
continue;
int val = __isnan(op->getValueAPF().convertToDouble());
Constant* res = ConstantInt::get(CI->getType(), val);
CI->replaceAllUsesWith(res);
CI->eraseFromParent();
changed = true;
} else if (name == FUNCTION_NAME(__isinf)){
ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
if (!op)
continue;
int val = __isinf(op->getValueAPF().convertToDouble());
Constant* res = ConstantInt::get(CI->getType(), val);
CI->replaceAllUsesWith(res);
CI->eraseFromParent();
changed = true;
}
}
}
return changed;
}