/* * 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); }