Skip to content

Commit

Permalink
Add flow control instructions and a bunch more
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan Phoenix committed May 14, 2009
1 parent 693a615 commit 6a660c1
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 2 deletions.
1 change: 0 additions & 1 deletion kernel/bootstrap/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def at(idx)
# and returns self. We re-evaluate @total each time
# through the loop in case the array has changed.
def each
return to_enum :each unless block_given? || Rubinius::TARGET_IS_186
i = 0
while i < @total
yield at(i)
Expand Down
8 changes: 8 additions & 0 deletions vm/instructions_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ namespace rubinius {
#undef HANDLE_INST1
#undef HANDLE_INST2

void at_ip(int ip) { }

void drive(opcode* stream, int size) {
int ip = 0;
while(ip < size) {
SPECIFIC->at_ip(ip);

switch(stream[ip]) {
#define HANDLE_INST0(code, name) \
case code: \
Expand All @@ -45,6 +49,10 @@ namespace rubinius {
}
}
}

void drive(VMMethod* vmm) {
drive(vmm->opcodes, vmm->total);
}
};
}

44 changes: 44 additions & 0 deletions vm/llvm/jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <llvm/Analysis/Verifier.h>
#include <llvm/Transforms/Scalar.h>

#include <sstream>

using namespace llvm;

#include "llvm/jit_visit.hpp"
Expand Down Expand Up @@ -257,6 +259,43 @@ namespace rubinius {

}

class BlockFinder : public VisitInstructions<BlockFinder> {
BlockMap& map_;
Function* function_;

public:

BlockFinder(BlockMap& map, Function* func)
: map_(map)
, function_(func)
{}

void visit_goto(opcode which) {
BlockMap::iterator i = map_.find(which);
if(i == map_.end()) {
std::ostringstream ss;
ss << "ip" << which;
map_[which] = BasicBlock::Create(ss.str().c_str(), function_);
}
}

void visit_goto_if_true(opcode which) {
visit_goto(which);
}

void visit_goto_if_false(opcode which) {
visit_goto(which);
}

void visit_goto_if_defined(opcode which) {
visit_goto(which);
}

void setup_unwind(opcode which, opcode type) {
visit_goto(which);
}
};

void LLVMCompiler::compile(STATE, VMMethod* vmm) {
llvm::Module* mod = LLVMState::get(state)->module();

Expand Down Expand Up @@ -323,6 +362,11 @@ namespace rubinius {

JITVisit visitor(state, vmm, mod, func, bb, stk, cf, vars, stack_top);

// Pass 1, detect BasicBlock boundaries
BlockFinder finder(visitor.block_map(), func);
finder.drive(vmm);

// Pass 2, compile!
try {
visitor.drive(vmm->opcodes, vmm->total);
} catch(JITVisit::Unsupported &e) {
Expand Down
14 changes: 14 additions & 0 deletions vm/llvm/jit_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,4 +499,18 @@ extern "C" {

return scope->get_local(index);
}

Object* rbx_check_interrupts(STATE, CallFrame* call_frame) {
if(unlikely(state->interrupts.timer)) {
{
state->interrupts.timer = false;
state->set_call_frame(call_frame);
// unlock..
GlobalLock::UnlockGuard lock(state->global_lock());
// and relock automatically!
}
}
if(!state->check_async(call_frame)) return NULL;
return Qtrue;
}
}
150 changes: 149 additions & 1 deletion vm/llvm/jit_visit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
#include <llvm/DerivedTypes.h>

namespace rubinius {
typedef std::map<int, llvm::BasicBlock*> BlockMap;

class JITVisit : public VisitInstructions<JITVisit> {
STATE;
VMMethod* vmm_;
BlockMap block_map_;

llvm::Value* stack_;
llvm::Value* call_frame_;
Expand Down Expand Up @@ -78,6 +81,10 @@ namespace rubinius {
vm_ = input++;
}

BlockMap& block_map() {
return block_map_;
}

Value* stack_ptr(BasicBlock* block = NULL) {
if(!block) block = block_;
return new LoadInst(stack_top_, "stack_ptr", block);
Expand Down Expand Up @@ -164,6 +171,15 @@ namespace rubinius {
ObjType, "cast_to_obj", block);
}

void at_ip(int ip) {
BlockMap::iterator i = block_map_.find(ip);
if(i != block_map_.end()) {
BasicBlock* next = i->second;
BranchInst::Create(next, block_);
block_ = next;
}
}

// visitors.

void visit(opcode op, opcode arg1, opcode arg2) {
Expand Down Expand Up @@ -762,7 +778,8 @@ namespace rubinius {
ConstantInt::get(Type::Int32Ty, cache)
};

CallInst::Create(func, call_args, call_args+4, "push_const_fast", block_);
stack_push(
CallInst::Create(func, call_args, call_args+4, "push_const_fast", block_));
}

void visit_push_variables() {
Expand Down Expand Up @@ -851,5 +868,136 @@ namespace rubinius {

stack_push(CallInst::Create(func, call_args, call_args+4, "pld", block_));
}

void visit_goto(opcode ip) {
BranchInst::Create(block_map_[ip], block_);
block_ = BasicBlock::Create("continue", function_);
}

void visit_goto_if_true(opcode ip) {
Value* cond = stack_pop();
Value* i = CastInst::Create(
Instruction::PtrToInt,
cond, IntPtrTy, "as_int", block_);

Value* anded = BinaryOperator::CreateAnd(i,
ConstantInt::get(Type::Int32Ty, FALSE_MASK), "and", block_);

Value* cmp = new ICmpInst(ICmpInst::ICMP_NE, anded,
ConstantInt::get(Type::Int32Ty, cFalse), "is_true", block_);

BasicBlock* cont = BasicBlock::Create("continue", function_);
BranchInst::Create(block_map_[ip], cont, cmp, block_);

block_ = cont;
}

void visit_goto_if_false(opcode ip) {
Value* cond = stack_pop();
Value* i = CastInst::Create(
Instruction::PtrToInt,
cond, IntPtrTy, "as_int", block_);

Value* anded = BinaryOperator::CreateAnd(i,
ConstantInt::get(Type::Int32Ty, FALSE_MASK), "and", block_);

Value* cmp = new ICmpInst(ICmpInst::ICMP_EQ, anded,
ConstantInt::get(Type::Int32Ty, cFalse), "is_true", block_);

BasicBlock* cont = BasicBlock::Create("continue", function_);
BranchInst::Create(block_map_[ip], cont, cmp, block_);

block_ = cont;
}

void visit_meta_send_op_lt() {
std::vector<const Type*> types;

types.push_back(VMTy);
types.push_back(CallFrameTy);
types.push_back(PointerType::getUnqual(ObjType));

FunctionType* ft = FunctionType::get(ObjType, types, false);
Function* func = cast<Function>(
module_->getOrInsertFunction("rbx_meta_send_op_lt", ft));

Value* call_args[] = {
vm_,
call_frame_,
stack_objects(2)
};

Value* val = CallInst::Create(func, call_args, call_args+3, "molt", block_);
stack_remove(2);
stack_push(val);
}

void visit_yield_stack(opcode count) {
std::vector<const Type*> types;

types.push_back(VMTy);
types.push_back(CallFrameTy);
types.push_back(Type::Int32Ty);
types.push_back(PointerType::getUnqual(ObjType));

FunctionType* ft = FunctionType::get(ObjType, types, false);
Function* func = cast<Function>(
module_->getOrInsertFunction("rbx_yield_stack", ft));

Value* call_args[] = {
vm_,
call_frame_,
ConstantInt::get(Type::Int32Ty, count),
stack_objects(count)
};

Value* val = CallInst::Create(func, call_args, call_args+4, "ys", block_);
stack_remove(count);
stack_push(val);
}

void visit_check_interrupts() {
std::vector<const Type*> types;

types.push_back(VMTy);
types.push_back(CallFrameTy);

FunctionType* ft = FunctionType::get(ObjType, types, false);
Function* func = cast<Function>(
module_->getOrInsertFunction("rbx_check_interrupts", ft));

Value* call_args[] = {
vm_,
call_frame_
};

CallInst::Create(func, call_args, call_args+2, "ci", block_);
}

void visit_push_my_offset(opcode offset) {
Value* idx[] = {
ConstantInt::get(Type::Int32Ty, 0),
ConstantInt::get(Type::Int32Ty, 6)
};

Value* pos = GetElementPtrInst::Create(vars_, idx, idx + 2, "self_pos", block_);

Value* self = new LoadInst(pos, "self", block_);

assert(offset % sizeof(Object*) == 0);

Value* cst = CastInst::Create(
Instruction::BitCast,
self,
PointerType::getUnqual(ObjType), "obj_array", block_);

Value* idx2[] = {
ConstantInt::get(Type::Int32Ty, offset / sizeof(Object*))
};

pos = GetElementPtrInst::Create(cst, idx2, idx2+1, "val_pos", block_);

stack_push(new LoadInst(pos, "val", block_));
}
};
}

0 comments on commit 6a660c1

Please sign in to comment.