void CodeGenVisitor::visit(FunctionCallExpression* e) { llvm::Function* cf = module_->getFunction(e->getId()); if (!cf) { throw "function to call not found"; return; } auto values = e->getValues()->getValues(); if (cf->arg_size() != values.size()) { throw "argument size mismatch"; return; } std::vector<llvm::Value*> args; auto iter = values.begin(); auto end = values.end(); for (; iter != end; ++iter) { Expression *expr = (*iter); expr->accept(this); if (!value_) { throw "error evaluating expression"; } args.push_back(value_); } if (cf->getFunctionType()->getReturnType() == typeToLLVMType(Type::VOID)) { builder_->CreateCall(cf, args); // just handle void functions as if they returned 0 value_ = llvm::ConstantInt::get(llvm::getGlobalContext(), llvm::APInt(0, 32, 10)); } else { value_ = builder_->CreateCall(cf, args, "calltmp"); } }
//===================================================================================================================== void visitMethodCall(MethodCall *p) { fprintf(m_outputfile, "#### METHC\n"); // Visit variable and method name p->m_methodid->accept(this); p->m_variableid->accept(this); // Grab variable's classname (for jump label) from offset table OffsetTable* table = currMethodOffset; bool inClass=false; const char* varname = dynamic_cast<VariableIDImpl*>(p->m_variableid)->m_symname->spelling(); if(!table->exist(varname)) {table = currClassOffset; inClass=true;} assert(table->exist(varname)); CompoundType type = table->get_type(varname); const char* name; name = type.classID; // Visit parameters in reverse order, so their results will end up on the stack in x86 convention order int numparams = 0; list<Expression_ptr> *l = p->m_expression_list; list<Expression_ptr>::iterator it; Expression* exp; Expression_ptr ptr; for(it=l->end(); it!=l->begin();) { --it; ptr = (Expression_ptr)*it; exp = dynamic_cast<Expression*> (ptr); exp->accept(this); numparams++; } // Push referenced object's pointer to stack as final parameter if(!inClass) { fprintf( m_outputfile, " pushl %i(%%ebp)\n", table->get_offset(varname)); } else { fprintf( m_outputfile, " movl 8(%%ebp), %%ebx\n"); fprintf( m_outputfile, " pushl %i(%%ebx)\n", table->get_offset(varname)); } numparams++; // Find class/superclass that contains the function const char* funcname = dynamic_cast<MethodIDImpl*>(p->m_methodid)->m_symname->spelling(); ClassNode* node = m_classtable->lookup(name); assert(node!=NULL); while(!(node->scope->exist(funcname))) { assert(node->superClass != NULL); node = m_classtable->lookup(node->superClass); } // Call the function fprintf(m_outputfile, " call %s_%s\n", node->name->spelling(), funcname); // Clean up parameters fprintf(m_outputfile, " addl $%i, %%esp\n", numparams*4); // Push return value fprintf(m_outputfile, " pushl %%ebx\n"); fprintf(m_outputfile, "####\n"); }
void Interpreter::print(Instruction* instruction) { OutputVisitor ov(std::cout); for (u32_t i = 0; i < instruction->getOperandAmount(); i++) { Expression* exp = this->resolveExpression(instruction->getOperand(i)); exp->accept(ov); } std::cout << '\n'; }
void SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node) { Expression *expr = node->expr(); expr->accept(this); if (!expr->hasSideEffects()) cc_.report(node->loc(), rmsg::expr_has_no_side_effects); }
void check(Loc loc, Declaration *d) { assert(d); VarDeclaration *v = d->isVarDeclaration(); if (v && v->toParent2() == sc->func) { if (v->isDataseg()) return; if ((v->storage_class & (STCref | STCout)) == 0) { error(loc, "escaping reference to local variable %s", v); return; } if (global.params.useDIP25 && (v->storage_class & (STCref | STCout)) && !(v->storage_class & (STCreturn | STCforeach))) { if (sc->func->flags & FUNCFLAGreturnInprocess) { //printf("inferring 'return' for variable '%s'\n", v->toChars()); v->storage_class |= STCreturn; if (v == sc->func->vthis) { TypeFunction *tf = (TypeFunction *)sc->func->type; if (tf->ty == Tfunction) { //printf("'this' too\n"); tf->isreturn = true; } } } else if (sc->module && sc->module->isRoot()) { //printf("escaping reference to local ref variable %s\n", v->toChars()); //printf("storage class = x%llx\n", v->storage_class); error(loc, "escaping reference to local ref variable %s", v); } return; } if (v->storage_class & STCref && v->storage_class & (STCforeach | STCtemp) && v->init) { // (ref v = ex; ex) if (ExpInitializer *ez = v->init->isExpInitializer()) { assert(ez->exp && ez->exp->op == TOKconstruct); Expression *ex = ((ConstructExp *)ez->exp)->e2; ex->accept(this); return; } } } }
void visit(StructLiteralExp *e) { if (e->elements) { for (size_t i = 0; i < e->elements->dim; i++) { Expression *ex = (*e->elements)[i]; if (ex) ex->accept(this); } } }
void visit(StructLiteralExp *e) { size_t dim = e->elements ? e->elements->dim : 0; buf->printf("S%u", dim); for (size_t i = 0; i < dim; i++) { Expression *ex = (*e->elements)[i]; if (ex) ex->accept(this); else buf->writeByte('v'); // 'v' for void } }
void visit(NewExp *e) { Type *tb = e->newtype->toBasetype(); if (tb->ty == Tstruct && !e->member && e->arguments) { for (size_t i = 0; i < e->arguments->dim; i++) { Expression *ex = (*e->arguments)[i]; if (ex) ex->accept(this); } } }
Expression * GetDerivativeVisitor::visit(Fcn::Cosh * expression) { ExpressionList * parameters = expression->getParameterList(); if (parameters->getLength() != 1) { throw InvalidFunctionParametersException(); } Expression * parameterExpr = parameters->getExpressionAt(0); std::unique_ptr<Expression> derivedParameterExprPtr((Expression *)parameterExpr->accept(this)); return new Op::Multiplication( new Fcn::Sinh(parameterExpr->copy()), derivedParameterExprPtr.release() ); }
void visit(ArrayLiteralExp *e) { Type *tb = e->type->toBasetype(); if (tb->ty == Tsarray || tb->ty == Tarray) { if (e->basis) e->basis->accept(this); for (size_t i = 0; i < e->elements->dim; i++) { Expression *el = (*e->elements)[i]; if (el) el->accept(this); } } }
void visit(CallExp *e) { /* If the function returns by ref, check each argument that is * passed as 'return ref'. */ Type *t1 = e->e1->type->toBasetype(); TypeFunction *tf; if (t1->ty == Tdelegate) tf = (TypeFunction *)((TypeDelegate *)t1)->next; else if (t1->ty == Tfunction) tf = (TypeFunction *)t1; else return; if (tf->isref) { if (e->arguments && e->arguments->dim) { /* j=1 if _arguments[] is first argument, * skip it because it is not passed by ref */ int j = (tf->linkage == LINKd && tf->varargs == 1); for (size_t i = j; i < e->arguments->dim; ++i) { Expression *arg = (*e->arguments)[i]; size_t nparams = Parameter::dim(tf->parameters); if (i - j < nparams && i >= j) { Parameter *p = Parameter::getNth(tf->parameters, i - j); if ((p->storageClass & (STCout | STCref)) && (p->storageClass & STCreturn)) arg->accept(this); } } } // If 'this' is returned by ref, check it too if (tf->isreturn && e->e1->op == TOKdotvar && t1->ty == Tfunction) { DotVarExp *dve = (DotVarExp *)e->e1; dve->e1->accept(this); } } else { error(e->loc, "escaping reference to stack allocated value returned by %s", e); return; } }
Expression * GetDerivativeVisitor::visit(Fcn::ArTanh * expression) { ExpressionList * parameters = expression->getParameterList(); if (parameters->getLength() != 1) { throw InvalidFunctionParametersException(); } Expression * parameterExpr = parameters->getExpressionAt(0); std::unique_ptr<Expression> derivedParameterExprPtr((Expression *)parameterExpr->accept(this)); return new Op::Division( derivedParameterExprPtr.release(), new Op::Subtraction( new Number(1.0), new Op::Power(parameterExpr->copy(), new Number(2.0)) ) ); }
void visitArrayLiteral(ArrayLiteral *node) override { prefix(); fprintf(fp_, "[ ArrayLiteral\n"); indent(); for (size_t i = 0; i < node->expressions()->length(); i++) { Expression *expr = node->expressions()->at(i); indent(); expr->accept(this); unindent(); } if (node->repeatLastElement()) { indent(); prefix(); fprintf(fp_, "...\n"); unindent(); } }
//===================================================================================================================== void visitSelfCall(SelfCall *p) { fprintf(m_outputfile, "#### SELFC\n"); // Visit method name p->m_methodid->accept(this); // Visit parameters in reverse order, so their results will end up on the stack in x86 convention order int numparams = 0; list<Expression_ptr> *l = p->m_expression_list; list<Expression_ptr>::iterator it; Expression* exp; Expression_ptr ptr; for(it=l->end(); it!=l->begin();) { --it; ptr = (Expression_ptr)*it; exp = dynamic_cast<Expression*> (ptr); exp->accept(this); numparams++; } // Push current object's pointer to stack as final parameter fprintf( m_outputfile, " pushl 8(%%ebp)\n"); numparams++; // Find class/superclass that contains the function const char* funcname = dynamic_cast<MethodIDImpl*>(p->m_methodid)->m_symname->spelling(); ClassNode* node = m_classtable->lookup(currClassName); assert(node!=NULL); while(!(node->scope->exist(funcname))) { assert(node->superClass != NULL); node = m_classtable->lookup(node->superClass); } // Call the function fprintf(m_outputfile, " call %s_%s\n", node->name->spelling(), funcname); // Clean up parameters fprintf(m_outputfile, " addl $%i, %%esp\n", numparams*4); // Push return value fprintf(m_outputfile, " pushl %%ebx\n"); fprintf(m_outputfile, "####\n"); }
void visit(VarExp *e) { VarDeclaration *v = e->var->isVarDeclaration(); if (v) { if (v->storage_class & STCref && v->storage_class & (STCforeach | STCtemp) && v->_init) { /* If compiler generated ref temporary * (ref v = ex; ex) * look at the initializer instead */ if (ExpInitializer *ez = v->_init->isExpInitializer()) { assert(ez->exp && ez->exp->op == TOKconstruct); Expression *ex = ((ConstructExp *)ez->exp)->e2; ex->accept(this); } } else er->byref.push(v); } }
Expression * GetDerivativeVisitor::visit(Variable * expression) { Expression * resultExpr = (Expression *)0; std::string varName = expression->getName(); if (varName == derivativeVariableName) { resultExpr = new Number(1.0); } else { Expression * varExpr = (Expression *)0; Scope * scope = getCurrentScope(); while (varExpr == 0 && scope != 0) { varExpr = scope->getExpressionByIdentifier(varName); scope = scope->getParentScope(); } if (varExpr == 0) { throw UnknownIdentifierException(varName); } resultExpr = varExpr->accept(this); } return resultExpr; }
void visit(CallExp *e) { //printf("CallExp(): %s\n", e->toChars()); /* Check each argument that is * passed as 'return scope'. */ Type *t1 = e->e1->type->toBasetype(); TypeFunction *tf = NULL; TypeDelegate *dg = NULL; if (t1->ty == Tdelegate) { dg = (TypeDelegate *)t1; tf = (TypeFunction *)dg->next; } else if (t1->ty == Tfunction) tf = (TypeFunction *)t1; else return; if (e->arguments && e->arguments->dim) { /* j=1 if _arguments[] is first argument, * skip it because it is not passed by ref */ size_t j = (tf->linkage == LINKd && tf->varargs == 1); for (size_t i = j; i < e->arguments->dim; ++i) { Expression *arg = (*e->arguments)[i]; size_t nparams = Parameter::dim(tf->parameters); if (i - j < nparams && i >= j) { Parameter *p = Parameter::getNth(tf->parameters, i - j); const StorageClass stc = tf->parameterStorageClass(p); if ((stc & (STCscope)) && (stc & STCreturn)) arg->accept(this); else if ((stc & (STCref)) && (stc & STCreturn)) escapeByRef(arg, er); } } } // If 'this' is returned, check it too if (e->e1->op == TOKdotvar && t1->ty == Tfunction) { DotVarExp *dve = (DotVarExp *)e->e1; FuncDeclaration *fd = dve->var->isFuncDeclaration(); AggregateDeclaration *ad = NULL; if (global.params.vsafe && tf->isreturn && fd && (ad = fd->isThis()) != NULL) { if (ad->isClassDeclaration() || tf->isscope) // this is 'return scope' dve->e1->accept(this); else if (ad->isStructDeclaration()) // this is 'return ref' escapeByRef(dve->e1, er); } else if (dve->var->storage_class & STCreturn || tf->isreturn) { if (dve->var->storage_class & STCscope) dve->e1->accept(this); else if (dve->var->storage_class & STCref) escapeByRef(dve->e1, er); } } /* If returning the result of a delegate call, the .ptr * field of the delegate must be checked. */ if (dg) { if (tf->isreturn) e->e1->accept(this); } }
void visit(CallExp *e) { /* If the function returns by ref, check each argument that is * passed as 'return ref'. */ Type *t1 = e->e1->type->toBasetype(); TypeFunction *tf; if (t1->ty == Tdelegate) tf = (TypeFunction *)((TypeDelegate *)t1)->next; else if (t1->ty == Tfunction) tf = (TypeFunction *)t1; else return; if (tf->isref) { if (e->arguments && e->arguments->dim) { /* j=1 if _arguments[] is first argument, * skip it because it is not passed by ref */ size_t j = (tf->linkage == LINKd && tf->varargs == 1); for (size_t i = j; i < e->arguments->dim; ++i) { Expression *arg = (*e->arguments)[i]; size_t nparams = Parameter::dim(tf->parameters); if (i - j < nparams && i >= j) { Parameter *p = Parameter::getNth(tf->parameters, i - j); const StorageClass stc = tf->parameterStorageClass(p); if ((stc & (STCout | STCref)) && (stc & STCreturn)) arg->accept(this); else if ((stc & STCscope) && (stc & STCreturn)) { if (arg->op == TOKdelegate) { DelegateExp *de = (DelegateExp *)arg; if (de->func->isNested()) er->byexp.push(de); } else escapeByValue(arg, er); } } } } // If 'this' is returned by ref, check it too if (e->e1->op == TOKdotvar && t1->ty == Tfunction) { DotVarExp *dve = (DotVarExp *)e->e1; if (dve->var->storage_class & STCreturn || tf->isreturn) { if ((dve->var->storage_class & STCscope) || tf->isscope) escapeByValue(dve->e1, er); else if ((dve->var->storage_class & STCref) || tf->isref) dve->e1->accept(this); } } // If it's a delegate, check it too if (e->e1->op == TOKvar && t1->ty == Tdelegate) { escapeByValue(e->e1, er); } } else er->byexp.push(e); }