예제 #1
0
파일: Tracer.cpp 프로젝트: BruceZu/gwt
/*
 * Throw a HostedModeException and log a failure message.
 * 
 * Creates a new HostedModeException with the failure message,
 * and also logs the failure message 
 * 
 * env - JNI environment to throw the exception in
 * msg - failure message 
 */
void Tracer::throwHostedModeException(JNIEnv* env, const char* msg) {
#ifdef ENABLE_TRACING
  setFail(msg);
#endif // ENABLE_TRACING
  jclass exceptionClass
      = env->FindClass("com/google/gwt/dev/shell/HostedModeException");
  env->ThrowNew(exceptionClass, msg);
}
llvm::Value* minipascal::NLoop::codeGen(CodeGenContext* context)
{
        char buf[32];
        int count = sprintf(buf, "LOOP_CHECK_%d", index);
        llvm::BasicBlock* check_bb = llvm::BasicBlock::Create(llvm::getGlobalContext(), buf, context->getCurBlock()->getBlock()->getParent(), 0);
        count = sprintf(buf, "LOOP_%d", index);
        llvm::BasicBlock* body_bb = llvm::BasicBlock::Create(llvm::getGlobalContext(), buf, context->getCurBlock()->getBlock()->getParent(), 0);
        count = sprintf(buf, "LOOP_CONT_%d", index);
        llvm::BasicBlock* loop_cont = llvm::BasicBlock::Create(llvm::getGlobalContext(), buf, context->getCurBlock()->getBlock()->getParent(), 0);
        
        // create jump instruction which is used to jump to loop check
        context->builder->CreateBr(check_bb);
        context->builder->SetInsertPoint(check_bb);
        
        llvm::Value* condvalue = getCond()->codeGen(context);
        if(condvalue == NULL) return NULL;
        
        // condition type check
        BooleanType temp;
        if(!(getCond()->getType()->compare(&temp)))
        {
                IntType inttest;
                if(!(getCond()->getType()->compare(&inttest)))
                {
                        showError("Condition are not boolean or integer type");
                        setFail(true);
                        context->fail = true;
                        return NULL;
                }
                condvalue = context->builder->CreateICmpNE(condvalue, llvm::ConstantInt::get(inttest.getLLVMType(), 0, true), "");
        }
        
        context->builder->CreateCondBr(condvalue, body_bb, loop_cont);
        
        context->builder->SetInsertPoint(body_bb);
        llvm::Value* bodyvalue = getStmt()->codeGen(context);
        context->builder->CreateBr(check_bb);
        
        context->builder->SetInsertPoint(loop_cont);
        
        ++index;
        return condvalue;
}
minipascal::NStatement::NStatement()
{
        setFail(false);
}
llvm::Value* minipascal::NBinaryOperator::codeGen(CodeGenContext* context)
{
        std::cout << "Generating code for " << getOutput() << std::endl;
        llvm::Value* L = getLeft()->codeGen(context);
        llvm::Value* R = getRight()->codeGen(context);
        
        if(L == NULL || R == NULL) return NULL;
        
        switch(getOP()) {
                case minipascal::NBinaryOperator::ADD:
                case minipascal::NBinaryOperator::SUB:
                case minipascal::NBinaryOperator::MUL:
                case minipascal::NBinaryOperator::DIV:
                        setType(getLeft()->getType());
                        break;
                case minipascal::NBinaryOperator::GT:
                case minipascal::NBinaryOperator::GE:
                case minipascal::NBinaryOperator::LT:
                case minipascal::NBinaryOperator::LE:
                case minipascal::NBinaryOperator::EQ:
                case minipascal::NBinaryOperator::NE:
                        setType(new minipascal::BooleanType());
                        break;
        }
        
        // type check
        if(!(getLeft()->getFail()))
        {
                if(!(getLeft()->getType()->compare(getRight()->getType())))
                {
                        showError("Cannot do binary operation");
                        setFail(true);
                        context->fail = true;
                        return NULL;
                }
        }
        
        std::string name = getStoreReg();
        minipascal::IntType temp;
        // for integer binary operation
        if(getLeft()->getType()->compare(&temp))
        {
                switch(getOP()){
                case minipascal::NBinaryOperator::ADD:
                        return context->builder->CreateAdd(L, R, name.c_str());
                case minipascal::NBinaryOperator::SUB:
                        return context->builder->CreateSub(L, R, name.c_str());
                case minipascal::NBinaryOperator::MUL:
                        return context->builder->CreateMul(L, R, name.c_str());
                case minipascal::NBinaryOperator::DIV:
                        return context->builder->CreateSDiv(L, R, name.c_str());
                case minipascal::NBinaryOperator::LE:
                        return context->builder->CreateICmpSLE(L, R, name.c_str());
                case minipascal::NBinaryOperator::LT:
                        return context->builder->CreateICmpSLT(L, R, name.c_str());
                case minipascal::NBinaryOperator::EQ:
                        return context->builder->CreateICmpEQ(L, R, name.c_str());
                case minipascal::NBinaryOperator::NE:
                        return context->builder->CreateICmpNE(L, R, name.c_str());
                case minipascal::NBinaryOperator::GE:
                        return context->builder->CreateICmpSGE(L, R, name.c_str());
                case minipascal::NBinaryOperator::GT:
                        return context->builder->CreateICmpSGT(L, R, name.c_str());
                }
        }
        else // for real binary operation
        {
                switch(getOP()){
                case minipascal::NBinaryOperator::ADD:
                        return context->builder->CreateFAdd(L, R, name.c_str());
                case minipascal::NBinaryOperator::SUB:
                        return context->builder->CreateFSub(L, R, name.c_str());
                case minipascal::NBinaryOperator::MUL:
                        return context->builder->CreateFMul(L, R, name.c_str());
                case minipascal::NBinaryOperator::DIV:
                        return context->builder->CreateFDiv(L, R, name.c_str());
                case minipascal::NBinaryOperator::LE:
                        return context->builder->CreateFCmpOLE(L, R, name.c_str());
                case minipascal::NBinaryOperator::LT:
                        return context->builder->CreateFCmpOLT(L, R, name.c_str());
                case minipascal::NBinaryOperator::EQ:
                        return context->builder->CreateFCmpOEQ(L, R, name.c_str());
                case minipascal::NBinaryOperator::NE:
                        return context->builder->CreateFCmpONE(L, R, name.c_str());
                case minipascal::NBinaryOperator::GE:
                        return context->builder->CreateFCmpOGE(L, R, name.c_str());
                case minipascal::NBinaryOperator::GT:
                        return context->builder->CreateFCmpOGT(L, R, name.c_str());
                }
        }
}
minipascal::NBinaryOperator::NBinaryOperator(minipascal::NExpression* left, minipascal::NExpression* right)
{
        setLeft(left);
        setRight(right);
        setFail(false);
}
minipascal::NDeclaration::NDeclaration(const std::string* name, minipascal::NType* type)
{
        setName(name);
        setType(type);
        setFail(false);
}
minipascal::NDeclaration::NDeclaration()
{
        setFail(false);
}
llvm::Value* minipascal::NMethodCall::codeGen(CodeGenContext* context)
{
        std::cout << "Generating code for " << getOutput() << std::endl;
        llvm::Value* retvalue = specialMethodCall(context);
        if(retvalue == NULL)
        {
                CodeGenContext::BlockStack* stack = &(context->blockstack);
                CodeGenContext::BlockStack::reverse_iterator rit;
                SymbolTable::iterator it;
                for(rit = stack->rbegin(); rit != stack->rend(); ++rit)
                {
                        it = (*rit)->getLocals()->find(getName());
                        if(it != context->getCurBlock()->getLocals()->end())
                        {
                                setType(it->second->declaration->getType());
                                
                                llvm::Function* function = context->getModule()->getFunction(getName().c_str());
                                std::vector<llvm::Value*> args;
                                const minipascal::Exps_list* exps = getExps();
                                minipascal::Exps_list::const_iterator eit;
                                for(eit = exps->begin(); eit != exps->end(); ++eit)
                                {
                                        llvm::Value* arg = (*eit)->codeGen(context);
                                        if(arg == NULL) return NULL;
                                        args.push_back(arg);
                                }
                                
                                // args check
                                try{
                                        NMethodDeclaration* method = boost::polymorphic_cast<NMethodDeclaration*>(it->second->declaration);
                                        Decls_list* decls = method->getArgs();
                                        Decls_list::iterator dit;
                                        for(dit = decls->begin(), eit = exps->begin(); dit != decls->end() && eit != exps->end(); ++eit, ++dit)
                                        {
                                                if(!((*dit)->getType()->compare((*eit)->getType())))
                                                {
                                                        showError("Function " + getName() + " args doesn't match");
                                                        setFail(true);
                                                        context->fail = true;
                                                        return NULL;
                                                }
                                        }
                                        if(dit != decls->end())
                                        {
                                                showError("Function " + getName() + " args isn't enough");
                                                setFail(true);
                                                context->fail = true;
                                                return NULL;
                                        }
                                        if(eit != exps->end())
                                        {
                                                showError("Function " + getName() + " args is too many");
                                                setFail(true);
                                                context->fail = true;
                                                return NULL;
                                        }
                                        
                                }catch(std::bad_cast& e){
                                        showError("No such function : " + getName());
                                        setFail(true);
                                        context->fail = true;
                                        return NULL;
                                }
                                
                                return context->builder->CreateCall<>(function, args.begin(), args.end(), "");
                        }
                }
        }
        else
        {
                std::vector<llvm::Value*> args;
                const minipascal::Exps_list* exps = getExps();
                minipascal::Exps_list::const_iterator eit;
                for(eit = exps->begin(); eit != exps->end(); ++eit)
                {
                        llvm::Value* arg = (*eit)->codeGen(context);
                        if(arg == NULL) return NULL;
                        args.push_back(arg);
                }
                return context->builder->CreateCall<>(retvalue, args.begin(), args.end(), "");
        }
        
        showError("No such function : " + getName());
        setFail(true);
        context->fail = true;
        return NULL;
}
minipascal::NMethodCall::NMethodCall(std::string* name, minipascal::Exps_list* exps)
{
        setName(name);
        setExps(exps);
        setFail(false);
}
minipascal::NProgram::NProgram()
{
        setFail(false);
}
minipascal::NLoop::NLoop(minipascal::NExpression* cond, minipascal::NStatement* stmt)
{ 
        setCond(cond);
        setStmt(stmt);
        setFail(false);
}
minipascal::NString::NString(std::string* value)
{
        setValue(value);
        setType(new StringType());
        setFail(false);
}
minipascal::NValue::NValue()
{
        setFail(false);
}