blob: 5763d4e53c32d247d001a9d4c21703f355889b08 [file] [log] [blame]
//===-- OperandStack.cpp - Java operand stack -----------------------------===//
//
// 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 the abstraction of a Java operand stack. We
// model the java operand stack as a stack of LLVM allocas.
//
//===----------------------------------------------------------------------===//
#include "OperandStack.h"
#include <llvm/BasicBlock.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Instructions.h>
#include <llvm/ADT/StringExtras.h>
#include <llvm/Java/Compiler.h>
using namespace llvm;
using namespace llvm::Java;
void OperandStack::copySlots(const SlotMap& src,
SlotMap& dst,
BasicBlock* insertAtEnd)
{
SlotMap::const_iterator it = src.begin();
SlotMap::const_iterator end = src.end();
for (; it != end; ++it) {
AllocaInst* srcSlot = it->second;
AllocaInst* dstSlot = getOrCreateSlot(dst, it->first, insertAtEnd);
Value* value = new LoadInst(srcSlot, "tmp", insertAtEnd);
new StoreInst(value, dstSlot, insertAtEnd);
}
}
llvm::AllocaInst* OperandStack::getOrCreateSlot(SlotMap& slotMap,
const Type* type,
BasicBlock* bb)
{
SlotMap::iterator it = slotMap.find(type);
if (it == slotMap.end()) {
// Insert the alloca at the beginning of the entry block.
BasicBlock* entry = &bb->getParent()->getEntryBlock();
AllocaInst* alloca = new AllocaInst(type, NULL, "opStack", entry);
it = slotMap.insert(it, std::make_pair(type, alloca));
}
return it->second;
}
void OperandStack::push(Value* value, BasicBlock* insertAtEnd)
{
assert(currentDepth_ < stack_.size() && "Pushing to a full stack!");
const Type* valueTy = value->getType();
// std::cerr << "PUSH(" << insertAtEnd << "/"
// << insertAtEnd->getParent()->getName() << " " << stack_.size()
// << ") Depth: " << currentDepth_ << " type: " << *valueTy << '\n';
const Type* storageTy = resolver_->getStorageType(valueTy);
if (valueTy != storageTy)
value = new CastInst(value, storageTy, "to-storage-type", insertAtEnd);
SlotMap& slotMap = stack_[currentDepth_];
AllocaInst* slot = getOrCreateSlot(slotMap, storageTy, insertAtEnd);
new StoreInst(value, slot, insertAtEnd);
currentDepth_ += 1 + resolver_->isTwoSlotType(storageTy);
assert(currentDepth_ < stack_.size() && "Pushed more than max stack depth!");
}
llvm::Value* OperandStack::pop(const Type* valueTy, BasicBlock* insertAtEnd)
{
const Type* storageTy = resolver_->getStorageType(valueTy);
assert(currentDepth_ != 0 && "Popping from an empty stack!");
currentDepth_ -= 1 + resolver_->isTwoSlotType(storageTy);
// std::cerr << "POP(" << insertAtEnd->getName() << "/"
// << insertAtEnd->getParent()->getName() << " " << stack_.size()
// << ") Depth: " << currentDepth_ << " type: " << *valueTy << '\n';
SlotMap& slotMap = stack_[currentDepth_];
SlotMap::iterator it = slotMap.find(storageTy);
assert(it != slotMap.end() && "Type mismatch on operand stack!");
Value* value = new LoadInst(it->second, "pop", insertAtEnd);
if (valueTy != storageTy)
value = new CastInst(value, valueTy, "from-storage-type", insertAtEnd);
return value;
}
/// ..., value -> ...
void OperandStack::do_pop(BasicBlock* insertAtEnd)
{
assert(currentDepth_ != 0 && "Popping from an empty stack!");
--currentDepth_;
}
/// ..., value2, value1 -> ...
/// ..., value -> ...
void OperandStack::do_pop2(BasicBlock* insertAtEnd)
{
do_pop(insertAtEnd);
do_pop(insertAtEnd);
}
/// ..., value -> ..., value, value
void OperandStack::do_dup(BasicBlock* insertAtEnd)
{
assert(currentDepth_ != 0 && "Popping from an empty stack!");
copySlots(stack_[currentDepth_-1], stack_[currentDepth_], insertAtEnd);
++currentDepth_;
}
/// ..., value2, value1 -> ..., value1, value2, value1
void OperandStack::do_dup_x1(BasicBlock* insertAtEnd)
{
copySlots(stack_[currentDepth_-1], stack_[currentDepth_], insertAtEnd);
copySlots(stack_[currentDepth_-2], stack_[currentDepth_-1], insertAtEnd);
copySlots(stack_[currentDepth_], stack_[currentDepth_-2], insertAtEnd);
++currentDepth_;
}
/// ..., value3, value2, value1 -> ..., value1, value3, value2, value1
/// ..., value2, value1 -> ..., value1, value2, value1
void OperandStack::do_dup_x2(BasicBlock* insertAtEnd)
{
copySlots(stack_[currentDepth_-1], stack_[currentDepth_], insertAtEnd);
copySlots(stack_[currentDepth_-2], stack_[currentDepth_-1], insertAtEnd);
copySlots(stack_[currentDepth_-3], stack_[currentDepth_-2], insertAtEnd);
copySlots(stack_[currentDepth_], stack_[currentDepth_-3], insertAtEnd);
++currentDepth_;
}
/// ..., value2, value1 -> ..., value2, value1, value2, value1
void OperandStack::do_dup2(BasicBlock* insertAtEnd)
{
copySlots(stack_[currentDepth_-2], stack_[currentDepth_], insertAtEnd);
copySlots(stack_[currentDepth_-1], stack_[currentDepth_+1], insertAtEnd);
currentDepth_ += 2;
}
/// ..., value3, value2, value1 -> ..., value2, value1, value3, value2, value1
/// ..., value2, value1 -> ..., value1, value2, value1
void OperandStack::do_dup2_x1(BasicBlock* insertAtEnd)
{
copySlots(stack_[currentDepth_-1], stack_[currentDepth_+1], insertAtEnd);
copySlots(stack_[currentDepth_-2], stack_[currentDepth_], insertAtEnd);
copySlots(stack_[currentDepth_-3], stack_[currentDepth_-1], insertAtEnd);
copySlots(stack_[currentDepth_+1], stack_[currentDepth_-2], insertAtEnd);
copySlots(stack_[currentDepth_], stack_[currentDepth_-3], insertAtEnd);
currentDepth_ += 2;
}
/// ..., value4, value3, value2, value1 -> ..., value2, value1, value4, value3, value2, value1
/// ..., value3, value2, value1 -> ..., value1, value3, value2, value1
/// ..., value3, value2, value1 -> ..., value2, value1, value3, value2, value1
/// ..., value2, value1 -> ..., value1, value2, value1
void OperandStack::do_dup2_x2(BasicBlock* insertAtEnd)
{
copySlots(stack_[currentDepth_-1], stack_[currentDepth_+1], insertAtEnd);
copySlots(stack_[currentDepth_-2], stack_[currentDepth_], insertAtEnd);
copySlots(stack_[currentDepth_-3], stack_[currentDepth_-1], insertAtEnd);
copySlots(stack_[currentDepth_-4], stack_[currentDepth_-2], insertAtEnd);
copySlots(stack_[currentDepth_+1], stack_[currentDepth_-3], insertAtEnd);
copySlots(stack_[currentDepth_], stack_[currentDepth_-4], insertAtEnd);
currentDepth_ += 2;
}
void OperandStack::do_swap(BasicBlock* insertAtEnd)
{
SlotMap tmp;
copySlots(stack_[currentDepth_-1], tmp, insertAtEnd);
copySlots(stack_[currentDepth_-2], stack_[currentDepth_-1], insertAtEnd);
copySlots(tmp, stack_[currentDepth_-2], insertAtEnd);
}