blob: ebecf588dcbfe9b49b5cb9dd119547235c23bf50 [file] [log] [blame]
//===-- BasicBlockBuilder.h - Java bytecode BasicBlock builder --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a BasicBlock builder that creates a LLVM
// BasicBlocks from Java bytecode. It also keeps track of the java
// bytecode indices that bound each basic block.
//
//===----------------------------------------------------------------------===//
#include <llvm/Java/BytecodeParser.h>
#include <llvm/Java/ClassFile.h>
#include <llvm/ADT/STLExtras.h>
#include <llvm/ADT/StringExtras.h>
#include <llvm/Instructions.h>
#include <map>
namespace llvm { namespace Java {
class BasicBlockBuilder : public BytecodeParser<BasicBlockBuilder> {
Function* function_;
typedef std::map<unsigned, BasicBlock*> BC2BBMap;
BC2BBMap bc2bbMap_;
typedef std::map<BasicBlock*, std::pair<unsigned,unsigned> > BB2BCMap;
BB2BCMap bb2bcMap_;
BasicBlock* getOrCreateBasicBlockAt(unsigned bcI) {
BC2BBMap::iterator it = bc2bbMap_.lower_bound(bcI);
if (it == bc2bbMap_.end() || it->first != bcI) {
bool inserted;
BasicBlock* newBB = new BasicBlock("bc" + utostr(bcI), function_);
tie(it, inserted) = bc2bbMap_.insert(std::make_pair(bcI, newBB));
assert(inserted && "LLVM basic block multiply defined!");
}
return it->second;
}
public:
BasicBlockBuilder(Function* f, CodeAttribute* c)
: function_(f) {
// Create the entry block.
BasicBlock* entry = new BasicBlock("entry", function_);
// Create the block for bytecode 0 (bb0).
BasicBlock* bb = getOrCreateBasicBlockAt(0);
// Create basic blocks for exception handlers.
const CodeAttribute::Exceptions& exceptions = c->getExceptions();
for (unsigned i = 0, e = exceptions.size(); i != e; ++i)
getOrCreateBasicBlockAt(exceptions[i]->getHandlerPc());
// Parse the bytecode and create basic blocks for all targets of
// control flow instructions.
parse(c->getCode(), 0, c->getCodeSize());
// Build the bytecode->basic block map.
for (BC2BBMap::const_iterator i = bc2bbMap_.begin(), e = bc2bbMap_.end();
i != e; ++i) {
unsigned end = next(i) != e ? next(i)->first : c->getCodeSize();
bb2bcMap_.insert(
std::make_pair(i->second, std::make_pair(i->first, end)));
}
assert(function_->getEntryBlock().getName() == "entry");
assert(bb2bcMap_.find(&function_->getEntryBlock()) == bb2bcMap_.end());
}
BasicBlock* getBasicBlock(unsigned bcI) const {
BC2BBMap::const_iterator i = bc2bbMap_.find(bcI);
assert(i != bc2bbMap_.end() &&
"No block is mapped to this bytecode index!");
return i->second;
}
std::pair<unsigned,unsigned> getBytecodeIndices(BasicBlock* bb) const {
BB2BCMap::const_iterator i = bb2bcMap_.find(bb);
assert(i != bb2bcMap_.end() &&
"BasicBlock was not created by this builder!");
return i->second;
}
void do_ifeq(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_ifne(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_iflt(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_ifge(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_ifgt(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_ifle(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmpeq(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmpne(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmplt(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmpgt(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmpge(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_icmple(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_acmpeq(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_if_acmpne(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_jsr(unsigned t, unsigned r) {
getOrCreateBasicBlockAt(r);
getOrCreateBasicBlockAt(t);
}
void do_switch_common(unsigned defTarget, const SwitchCases& sw) {
for (unsigned i = 0, e = sw.size(); i != e; ++i) {
unsigned target = sw[i].second;
getOrCreateBasicBlockAt(target);
}
getOrCreateBasicBlockAt(defTarget);
}
void do_tableswitch(unsigned defTarget, const SwitchCases& sw) {
do_switch_common(defTarget, sw);
}
void do_lookupswitch(unsigned defTarget, const SwitchCases& sw) {
do_switch_common(defTarget, sw);
}
void do_goto(unsigned target) {
getOrCreateBasicBlockAt(target);
}
void do_ifnull(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
void do_ifnonnull(unsigned t, unsigned f) {
getOrCreateBasicBlockAt(f);
getOrCreateBasicBlockAt(t);
}
};
} } // namespace llvm::Java