// Parsing nth argument (output = -1) pair<string,ProtoType*> ProtoInterpreter::parse_argument(SE_List_iter* i, int n, Signature* sig, bool anonymous_ok) { SExpr *a = i->get_next("argument"); SExpr *b = (i->on_token("|")) ? i->get_next("argument") : NULL; string name=""; ProtoType* type=NULL; if(b) { // specified as name|type if(sexp_is_type(a)) compile_error(a,"Parameter name cannot be a type"); if(a->isSymbol()) name = dynamic_cast<SE_Symbol &>(*a).name; else compile_error(a,"Parameter name not a symbol: "+ce2s(a)); type = sexp_to_type(b); } else { // determine name or type by parsing if(sexp_is_type(a)) { if(anonymous_ok) type = sexp_to_type(a); else compile_error(a,"Function parameters must be named: "+ce2s(a)); } else if(a->isSymbol()) name = dynamic_cast<SE_Symbol &>(*a).name; else compile_error(a,"Parameter name not a symbol: "+ce2s(a)); } // fall back to defaults where needed if(name=="") name = (n>=0) ? ("arg"+i2s(n)) : "value"; if(type==NULL) type = new ProtoType(); // record name in signature and return if(sig->names.count(name)) compile_error(a,"Cannot bind '"+name+"': already bound"); sig->names[name] = n; return make_pair(name,type); }
void SExpr::toStream(std::ostream& out, const SExpr& sexpr, OutputLanguage language, int indent) throw() { if( sexpr.isKeyword() && languageQuotesKeywords(language) ){ out << quoteSymbol(sexpr.getValue()); } else { toStreamRec(out, sexpr, language, indent); } }
SExpr* ProtoInterpreter::expand_macro(MacroOperator* m, SE_List* call) { Env m_env(this); // bind variables to SExprs if(!m->signature->legal_length(call->len()-1)) return sexp_err(call,"Wrong number of arguments for macro "+m->name); int i=1; // start after macro name for(int j=0;j<m->signature->required_inputs.size();j++) { ProtoSymbol* var = &dynamic_cast<ProtoSymbol &>(*m->signature->required_inputs[j]); m_env.bind(var->value,(*call)[i++]); } for(int j=0;j<m->signature->optional_inputs.size() && i<call->len();j++) { ProtoSymbol* var = &dynamic_cast<ProtoSymbol &>(*m->signature->optional_inputs[j]); m_env.bind(var->value,(*call)[i++]); } if(m->signature->rest_input) { // sweep all else into rest argument ProtoSymbol* var = &dynamic_cast<ProtoSymbol &>(*m->signature->rest_input); SE_List *rest = new SE_List(); rest->inherit_attributes(m); for(; i<call->len(); ) { rest->add((*call)[i++]); } m_env.bind(var->value,rest); } // then substitute the pattern V3 << "Expand macro call:\n"; V3 << call->to_str() << endl; SExpr* expanded = macro_substitute(m->pattern,&m_env); V3 << "Macro expanded into:\n"; V3 << expanded->to_str() << endl; return expanded; }
CVC4::SExpr SmtEngine::getOption(const std::string& key) const throw(OptionException) { NodeManagerScope nms(d_nodeManager); Trace("smt") << "SMT getOption(" << key << ")" << endl; if(key.length() >= 18 && key.compare(0, 18, "command-verbosity:") == 0) { map<string, Integer>::const_iterator i = d_commandVerbosity.find(key.c_str() + 18); if(i != d_commandVerbosity.end()) { return (*i).second; } i = d_commandVerbosity.find("*"); if(i != d_commandVerbosity.end()) { return (*i).second; } return Integer(2); } if(Dump.isOn("benchmark")) { Dump("benchmark") << GetOptionCommand(key); } if(key == "command-verbosity") { vector<SExpr> result; SExpr defaultVerbosity; for(map<string, Integer>::const_iterator i = d_commandVerbosity.begin(); i != d_commandVerbosity.end(); ++i) { vector<SExpr> v; v.push_back((*i).first); v.push_back((*i).second); if((*i).first == "*") { // put the default at the end of the SExpr defaultVerbosity = v; } else { result.push_back(v); } } // put the default at the end of the SExpr if(!defaultVerbosity.isAtom()) { result.push_back(defaultVerbosity); } else { // ensure the default is always listed vector<SExpr> v; v.push_back("*"); v.push_back(Integer(2)); result.push_back(v); } return result; } ${smt_getoption_handlers} #line 134 "${template}" throw UnrecognizedOptionException(key); }
bool Game::pollSource() { if(m_sexprSource == 0) { return false; } if(m_sexprSource->sexprReady()) { SExpr sexpr = m_sexprSource->getSExpr(); if(sexpr.type() == NodeType::Unknown) { return false; } if(sexpr[0] == "status") { GameState* state = new GameState; state->fromSExpr(sexpr); pushState(state); return true; } //Ident message //("ident" (("0" "MuesAI" "Stephen Mues" "human") ("1" "MuesAI" "Stephen Mues" "zombie")) "0") if(sexpr[0] == "ident") { SExpr ident = sexpr.next().list(); if(ident.list()[3] == "zombie") { m_zombieName = ident.list()[2]; m_humanName = ident.next().list()[2]; } else { m_humanName = ident.list()[2]; m_zombieName = ident.next().list()[2]; } } if(sexpr[0] == "notification") { if(sexpr[1] == Config::instance()->get("user") || atoi(Config::instance()->get("arenaMode").c_str()) > 0) { cout << "A game was joined by the same player that this visualizer is logged in as" << endl; if( atoi(Config::instance()->get("autoJoin").c_str()) > 0 || atoi(Config::instance()->get("arenaMode").c_str()) > 0) { cout << "Stopping reader thread" << endl; m_nextGame = sexpr[2]; Engine::instance()->stopPolling(); //throw "die"; } } } } return false; }
void Printer::toStream(std::ostream& out, const SExpr& sexpr) const throw() { if(sexpr.isInteger()) { out << sexpr.getIntegerValue(); } else if(sexpr.isRational()) { out << fixed << sexpr.getRationalValue().getDouble(); } else if(sexpr.isKeyword()) { out << sexpr.getValue(); } else if(sexpr.isString()) { string s = sexpr.getValue(); // escape backslash and quote for(size_t i = 0; i < s.length(); ++i) { if(s[i] == '"') { s.replace(i, 1, "\\\""); ++i; } else if(s[i] == '\\') { s.replace(i, 1, "\\\\"); ++i; } } out << "\"" << s << "\""; } else { out << '('; const vector<SExpr>& kids = sexpr.getChildren(); bool first = true; for(vector<SExpr>::const_iterator i = kids.begin(); i != kids.end(); ++i) { if(first) { first = false; } else { out << ' '; } out << *i; } out << ')'; } }/* Printer::toStream(SExpr) */
ProtoType* ProtoInterpreter::sexp_to_type(SExpr* s) { if(s->isSymbol()) { const string &name = dynamic_cast<SE_Symbol &>(*s).name; if(name=="any") { return new ProtoType(); } else if(name=="local") { return new ProtoLocal(); } else if(name=="tuple") { return new ProtoTuple(); } else if(name=="symbol") { return new ProtoSymbol(); } else if(name=="number") { return new ProtoNumber(); } else if(name=="scalar") { return new ProtoScalar(); } else if(name=="boolean") { return new ProtoBoolean(); } else if(name=="vector") { return new ProtoVector(); } else if(name=="lambda" || name=="fun") { return new ProtoLambda(); } else if(name=="field") { return new ProtoField(); } else { return type_err(s,"Unknown type "+s->to_str()); } } else if(s->isList()) { SE_List* sl = &dynamic_cast<SE_List &>(*s); if(!sl->op()->isSymbol()) return type_err(s,"Compound type must start with symbol: "+ce2s(s)); const string &name = dynamic_cast<SE_Symbol &>(*sl->op()).name; if(name=="tuple" || name=="vector") { ProtoTuple* t; if(name=="tuple") t=new ProtoTuple(true); else t=new ProtoVector(true); for(int i=1;i<sl->len();i++) { SExpr* subex = (*sl)[i]; if(subex->isSymbol() && dynamic_cast<SE_Symbol &>(*subex).name=="&rest") { t->bounded=false; continue; } ProtoType* sub = sexp_to_type(subex); if(name=="vector" && !sub->isA("ProtoScalar")) return type_err(sl,"Vectors must contain only scalars"); t->types.push_back(sub); } return t; } else if(name=="lambda" || name=="fun") { if(sl->len()!=3) return type_err(s,"Bad lambda type: "+s->to_str()); Signature* sig = sexp_to_sig((*sl)[1]); sig->output = sexp_to_type((*sl)[2]); return new ProtoLambda(new Operator(s,sig)); } else if(name=="field") { if(sl->len()!=2) return type_err(s,"Bad field type: "+s->to_str()); ProtoType* sub = sexp_to_type((*sl)[1]); if(sub->isA("ProtoField")) return type_err(s,"Field type must have a local subtype"); return new ProtoField(sub); } else { return type_err(s,"Unknown type "+s->to_str()); } } else { // scalars specify ProtoScalar literals return new ProtoScalar(dynamic_cast<SE_Scalar &>(*s).value); } }
// Parse the extra arguments of a primitive into attributes void parse_primitive_attributes(SE_List_iter* li,Primitive* p) { while(li->has_next()) { SExpr* v = li->get_next(); if(!v->isKeyword()) {compile_error(v,v->to_str()+" not a keyword"); return;} const string &name = dynamic_cast<SE_Symbol &>(*v).name; if(p->attributes.count(name)) compile_warn("Primitive "+p->name+" overriding duplicate '" +name+"' attribute"); if(li->has_next() && !li->peek_next()->isKeyword()) { p->attributes[name]=new SExprAttribute(li->get_next()); } else { p->attributes[name]=new MarkerAttribute(true); } } }
// walks through, copying (and inheriting attributes) SExpr* ProtoInterpreter::macro_substitute(SExpr* src, Env* e, SE_List* wrapper) { if(is_gensym(src)) { // substitute with a gensym for this instance SE_Symbol *groot = &dynamic_cast<SE_Symbol &>(*src); SExpr *gensym; CompilationElement *element = e->lookup(groot->name); if (element == 0) { gensym = make_gensym(groot->name); gensym->inherit_attributes(src); e->bind(groot->name, gensym); } else { gensym = &dynamic_cast<SExpr &>(*element); } return gensym; } else if(src->isList()) { // SE_List SE_List *srcl = &dynamic_cast<SE_List &>(*src); string opname = ((*srcl)[0]->isSymbol() ? dynamic_cast<SE_Symbol &>(*(*srcl)[0]).name : ""); if(opname=="comma") { if(srcl->len()!=2 || !(*srcl)[1]->isSymbol()) return sexp_err(src,"Bad comma form: "+src->to_str()); SE_Symbol* sn = &dynamic_cast<SE_Symbol &>(*(*srcl)[1]); // insert source text return dynamic_cast<SExpr &>(*e->lookup(sn,"SExpr")).copy(); } else if(opname=="comma-splice") { if(wrapper==NULL) return sexp_err(src,"Comma-splice "+(*srcl)[0]->to_str()+" w/o list"); if(srcl->len()!=2 || !(*srcl)[1]->isSymbol()) return sexp_err(src,"Bad comma form: "+src->to_str()); SE_Symbol* sn = &dynamic_cast<SE_Symbol &>(*(*srcl)[1]); SE_List* value = &dynamic_cast<SE_List &>(*e->lookup(sn,"SE_List")); for(int i=0;i<value->len();i++) wrapper->add((*value)[i]->copy()); return NULL; // comma-splices return null } else { // otherwise, just substitute each child SE_List *l = new SE_List(); SE_List *srcl = &dynamic_cast<SE_List &>(*src); for(int i=0;i<srcl->len();i++) { SExpr* sub = macro_substitute((*srcl)[i],e,l); if(sub!=NULL) l->add(sub); // comma-splices add selves and return null } return l; } } else { // symbol or scalar return src->copy(); } }
void SExpr::toStreamRec(std::ostream& out, const SExpr& sexpr, OutputLanguage language, int indent) { StreamFormatScope scope(out); if (sexpr.isInteger()) { out << sexpr.getIntegerValue(); } else if (sexpr.isRational()) { const double approximation = sexpr.getRationalValue().getDouble(); out << std::fixed << approximation; } else if (sexpr.isKeyword()) { out << sexpr.getValue(); } else if (sexpr.isString()) { std::string s = sexpr.getValue(); // escape backslash and quote for (size_t i = 0; i < s.length(); ++i) { if (s[i] == '"') { s.replace(i, 1, "\\\""); ++i; } else if (s[i] == '\\') { s.replace(i, 1, "\\\\"); ++i; } } out << "\"" << s << "\""; } else { const std::vector<SExpr>& kids = sexpr.getChildren(); out << (indent > 0 && kids.size() > 1 ? "( " : "("); bool first = true; for (std::vector<SExpr>::const_iterator i = kids.begin(); i != kids.end(); ++i) { if (first) { first = false; } else { if (indent > 0) { out << "\n" << std::string(indent, ' '); } else { out << ' '; } } toStreamRec(out, *i, language, indent <= 0 || indent > 2 ? 0 : indent + 2); } if (indent > 0 && kids.size() > 1) { out << '\n'; if (indent > 2) { out << std::string(indent - 2, ' '); } } out << ')'; } } /* toStreamRec() */
SExpr convertInvoke(const SExpr& invoke) { std::string resultString = "call " + currentModule_->exportedFunction(invoke[1].value())->name() + " "; for (std::size_t i = 2; i < invoke.children().size(); i++) { resultString += invoke[i].toString(); resultString += " "; } SExpr result = SExprParser::parseString(resultString); return result; }
SExpr* SPrimScope::inlineEQ() { if (PrintInlining) lprintf("%*s*inlining _Eq\n", (void*)(depth-1), ""); NodeGen* ng = theNodeGen; if (SICDebug) ng->comment("inlined _Eq"); SExpr* arg = args->top(); PReg* r = receiver->preg(); PReg* ar = arg->preg(); ng->append(new ArithRRNode(SubCCArithOp, r, ar, ng->noPR)); Node* test = ng->append(new BranchNode(EQBranchOp)); Node* falseNode; test->append(falseNode = new AssignNode(falsePR(), resultPR)); SExpr* e1 = new ConstantSExpr(Memory->falseObj, resultPR, falseNode); MergeNode* merge = new MergeNode("inlineEQ merge"); falseNode->append(merge); Node* trueNode = new AssignNode(truePR(), resultPR); ng->current = test->append1(trueNode); SExpr* e2 = new ConstantSExpr(Memory->trueObj, resultPR, trueNode); ng->branch(merge); SExpr* res = e1->copyMergeWith(e2, resultPR, ng->current); return res; }
bool SExpr::operator==(const SExpr& s) const { if (d_sexprType == s.d_sexprType && d_integerValue == s.d_integerValue && d_rationalValue == s.d_rationalValue && d_stringValue == s.d_stringValue) { if (d_children == NULL && s.d_children == NULL) { return true; } else if (d_children != NULL && s.d_children != NULL) { return getChildren() == s.getChildren(); } } return false; }
lookupTarget* sicScopeLookupTarget::get_target_for_slot(slotDesc* s, simpleLookup* L) { Unused(L); if (s->name == VMString[LEXICAL_PARENT]) { return new sicScopeLookupTarget(scope->parent()); } else if (s->name == VMString[SELF]) { SExpr* t = scope->receiverExpr(); if (t->isConstantSExpr()) { return (new objectLookupTarget(t->constant())) -> be_receiver(); } else if (t->hasMap()) { return ( new mapLookupTarget(t->map())) -> be_receiver(); } else { // don't know the receiver type return NULL; } } else if (! s->is_map_slot()) { return NULL; } else { return new objectLookupTarget(s->data); } }
SExpr* SPrimScope::inlineIntArithmetic() { ArithOpCode op = opcode_for_selector(_selector); bool intRcvr = receiver->hasMap() && receiver->map() == Memory->smi_map; SExpr* arg = args->nth(0); bool intArg = arg->hasMap() && arg->map() == Memory->smi_map; if ( intArg && arg->isConstantSExpr() && intRcvr && arg->constant() == as_smiOop(0) && can_fold_rcvr_op_zero_to_zero(op)) { if (PrintInlining) lprintf("%*s*constant-folding %s: 0\n", (void*)(depth-1), "", ArithOpName[op]); return receiver; } if (PrintInlining) lprintf("%*s*inlining %s:\n", (void*)(depth-1), "", ArithOpName[op]); if (!TArithRRNode::isOpInlinable(op)) return NULL; NodeGen* n = theNodeGen; Node* arith = n->append(new TArithRRNode(op, receiver->preg(), arg->preg(), resultPR, intRcvr, intArg)); // success case - no overflow, int tags MergeNode* ok = (MergeNode*)n->append(new MergeNode("inlineIntArithmetic ok")); SExpr* succExpr = new MapSExpr(Memory->smi_map->enclosing_mapOop(), resultPR, ok); // merge of success & failure branches MergeNode* done = (MergeNode*)ok->append(new MergeNode("inlineIntArithmetic done")); // failure case n->current = arith->append1(new NopNode); if (theSIC->useUncommonTraps && sender()->rscope->isUncommonAt(sender()->bci(), true)) { n->uncommonBranch(currentExprStack(0), true); n->current = done; if (PrintInlining) { lprintf("%*s*making arithmetic failure uncommon\n", (void*)(depth-1), ""); } return succExpr; } else { fint b = bci(); PReg* error = new SAPReg(_sender, b, b); if (intRcvr && intArg) { // must be overflow n->loadOop(VMString[OVERFLOWERROR], error); } else { arith->hasSideEffects_now = true; // may fail, so can't eliminate if (intRcvr || TARGET_ARCH == I386_ARCH) { // arg & TagMask already done by TArithRRNode // I386 does 'em all } else { PReg* t = new TempPReg(this, Temp1, false, true); n->append(new ArithRCNode(AndCCArithOp, t, Tag_Mask, t)); n->current->hasSideEffects_now = true; } // Note: this code assumes that condcode EQ means overflow Node* branch = n->append(new BranchNode(EQBranchOp)); // no overflow, must be type error n->loadOop(VMString[BADTYPEERROR], error); MergeNode* cont = (MergeNode*)n->append( new MergeNode("inlineIntArithmetic cont")); // overflow error PReg* err = new_ConstPReg(_sender, VMString[OVERFLOWERROR]); n->current = branch->append1(new AssignNode(err, error)); n->branch(cont); } Node* dummy; SExpr* failExpr = genPrimFailure(NULL, error, dummy, done, resultPR); assert(done, "merge should always exist"); return succExpr->mergeWith(failExpr, done); } }
const char* NodeGen::splitCondBranch( MergeNode* targetNode, bool isBackwards, PReg* targetPR, SExpr* testExpr, BranchBCTargetStack* targetStack, SExprStack* exprStack, PRegBList* exprStackPRs, SplitSig* s ) { // try to split a conditional branch bc to avoid materializing // the boolean // local splitting only for now assert(targetPR->isConstPReg(), "cond branch must be testing for constant"); oop targetOop = ((ConstPReg*)targetPR)->constant; if (!testExpr->isMergeSExpr()) return "testExpr not MergeSExpr"; if (!((MergeSExpr*)testExpr)->isSplittable()) return "textExpr not splittable"; SExprBList* exprs = ((MergeSExpr*)testExpr)->exprs; assert(testExpr->node(), "splittable implies node()"); Node* preceedingMerge = testExpr->node(); if (current != preceedingMerge) return "not local"; // local only for now if ( preceedingMerge->nPredecessors() != exprs->length() ) return "would have to iterate over predecessors"; fint i; for ( i = 0; i < exprs->length(); ++i) { SExpr* e = exprs->nth(i); Node* n = e->node(); if ( !preceedingMerge->isPredecessor(n) ) return "merge not immediately after expr node"; if ( !e->isConstantSExpr() ) return "merge contains non-constant expression"; } MergeNode* mergeForBranching = new MergeNode("for branching"); MergeNode* mergeForFallingThrough = new MergeNode("for falling through"); mergeForBranching ->setScope(currentScope()); mergeForFallingThrough->setScope(currentScope()); for ( i = 0; i < exprs->length(); ++i) { SExpr* e = exprs->nth(i); Node* n = e->node(); MergeNode* mn = e->constant() == targetOop ? mergeForBranching : mergeForFallingThrough; mn->setPrev(n); n->moveNext(preceedingMerge, mn); } while (preceedingMerge->nPredecessors()) preceedingMerge->removePrev(preceedingMerge->prev(0)); current = mergeForBranching; branchCode( targetNode, isBackwards, NULL, NULL, targetStack, exprStack, exprStackPRs, s); append(mergeForFallingThrough); return NULL; }
Field * ProtoInterpreter::letfed_to_graph(SE_List *s, AM *space, Env *env, bool init) { // Parse the input with the beautiful pattern matching language that // C++ affords us. if (! ((s->len() >= 3) & (*s)[1]->isList())) return field_err(s, space, "Malformed letfed expression: " + s->to_str()); vector<SExpr *>::const_iterator iterator = s->args(); SE_List *bindings = &dynamic_cast<SE_List &>(*(*iterator++)); size_t n = bindings->len(); vector<SExpr *> patterns; vector<SExpr *> initial_expressions; vector<SExpr *> update_expressions; for (size_t i = 0; i < n; i++) { SExpr *binding = (*bindings)[i]; if (!binding->isList()) compile_error(binding, "Malformed letfed binding: " + binding->to_str()); SE_List *binding_list = &dynamic_cast<SE_List &>(*binding); if (binding_list->len() != 3) compile_error(binding, "Malformed letfed binding: " + binding->to_str()); SExpr *pattern = (*binding_list)[0]; if (!letfed_pattern_p(pattern)) compile_error(pattern, "Malformed letfed pattern: " + pattern->to_str()); patterns.push_back(pattern); initial_expressions.push_back((*binding_list)[1]); update_expressions.push_back((*binding_list)[2]); } // Create the environments, conditional OIs, and subspaces. Env *body_env = new Env(env), *update_env = new Env(env); OI *true_if_change, *false_if_change; AM *initial_space, *update_space; if (init) { true_if_change = new OI(s, Env::core_op("dchange"), space); false_if_change = new OI(s, Env::core_op("not"), space); false_if_change->add_input(true_if_change->output); initial_space = new AM(s, space, true_if_change->output); update_space = new AM(s, space, false_if_change->output); } else { true_if_change = false_if_change = 0; initial_space = 0; update_space = space; } // Evaluate the initial expressions. vector<OI *> ois; for (size_t i = 0; i < n; i++) { SExpr *binding = (*bindings)[i]; SExpr *pattern = patterns[i]; SExpr *initial_expression = initial_expressions[i]; OI *delay = new OI(binding, Env::core_op("delay"), update_space); if (init) { OI *mux = new OI(binding, Env::core_op("mux"), space); mux->attributes["LETFED-MUX"] = new MarkerAttribute(true); mux->add_input(true_if_change->output); mux->add_input(sexp_to_graph(initial_expression, initial_space, env)); delay->add_input(mux->output); ois.push_back(mux); } else { delay->output->range = sexp_to_type(initial_expression); ois.push_back(delay); } // Bind the pattern variables to the delayed fields in the // environment for the update expression. bind_letfed_pattern(pattern, delay->output, update_space, update_env); } // Evaluate the update expressions. for (size_t i = 0; i < n; i++) { SExpr *binding = (*bindings)[i]; SExpr *pattern = patterns[i]; SExpr *update_expression = update_expressions[i]; Field *update = sexp_to_graph(update_expression, update_space, update_env); Field *field; if (init) field = ois[i]->output; else field = update; // Bind the pattern variables to the actual field in the body. bind_letfed_pattern(pattern, field, space, body_env); // Feed the update field back into the mux/delay OI. ois[i]->add_input(update); } // Evaluate the body. Field *field = 0; while (iterator != s->children.end()) field = sexp_to_graph(*iterator++, space, body_env); return field; }
// returns the output field Field* ProtoInterpreter::sexp_to_graph(SExpr* s, AM* space, Env *env) { V3 << "Interpret: " << ce2s(s) << " in " << ce2s(space) << endl; if(s->isSymbol()) { // All other symbols are looked up in the environment CompilationElement* elt = env->lookup(dynamic_cast<SE_Symbol &>(*s).name); if(elt==NULL) { V4 << "Symbolic literal?\n"; ProtoType* val = symbolic_literal(dynamic_cast<SE_Symbol &>(*s).name); if(val) { V4 << "- Yes\n"; return dfg->add_literal(val,space,s); } return field_err(s,space,"Couldn't find definition of "+s->to_str()); } else if(elt->isA("Field")) { V4 << "Found field: " << ce2s(elt) << endl; Field* f = &dynamic_cast<Field &>(*elt); if(f->domain==space) { return f; } if(f->domain->child_of(space)) { ierror(s,"Direct reference to child space in parent:"+ce2s(s)); } else { // implicit restriction OI *oi = new OperatorInstance(s,Env::core_op("restrict"),space); oi->add_input(f); if(space->selector) oi->add_input(space->selector); return oi->output; } } else if(elt->isA("Operator")) { V4 << "Lambda literal: " << ce2s(elt) << endl; return dfg->add_literal(new ProtoLambda(&dynamic_cast<Operator &>(*elt)), space, s); } else if(elt->isA("MacroSymbol")) { V4 << "Macro: " << ce2s(elt) << endl; return sexp_to_graph(dynamic_cast<MacroSymbol &>(*elt).pattern,space,env); } else return field_err(s,space,"Can't interpret "+elt->type_of()+" "+ s->to_str()+" as field"); } else if(s->isScalar()) { // Numbers are literals V4 << "Numeric literal.\n"; return dfg->add_literal(new ProtoScalar(dynamic_cast<SE_Scalar &>(*s).value), space,s); } else { // it must be a list // Lists are special forms or function applicatios SE_List* sl = &dynamic_cast<SE_List &>(*s); if(sl->len()==0) return field_err(sl,space,"Expression has no members"); if(sl->op()->isSymbol()) { // check if it's a special form string opname = dynamic_cast<SE_Symbol &>(*sl->op()).name; if(opname=="let") { return let_to_graph(sl,space,env,false); } else if(opname=="let*") { return let_to_graph(sl,space,env,true); } else if(opname=="all") { // evaluate children, returning last field Field* last=NULL; V4 << "Found 'all' construct\n"; for(int j=1;j<sl->len();j++) last = sexp_to_graph((*sl)[j],space,env); return last; } else if(opname=="restrict"){ return restrict_to_graph(sl,space,env); } else if(opname=="def" && sl->len()==3) { // variable definition SExpr *def=(*sl)[1], *exp=(*sl)[2]; if(!def->isSymbol()) return field_err(sl,space,"def name not a symbol: "+def->to_str()); Field* f = sexp_to_graph(exp,space,env); env->force_bind(dynamic_cast<SE_Symbol &>(*def).name,f); V4 << "Defined variable: " << ce2s(f) << endl; return f; } else if(opname=="def" || opname=="primitive" || opname=="lambda" || opname=="fun") { Operator* op = sexp_to_op(s,env); if(!(opname=="lambda" || opname=="fun")) return NULL; return dfg->add_literal(new ProtoLambda(op),space,s); } else if(opname=="annotate") { SE_List_iter li(sl); li.get_next(); // make iterator, discard op string name = li.get_token("operator name"); CE* p = env->lookup(name); if(p==NULL) { compile_error(sl,"Can't find primitve '"+name+"' to annotate"); } else if(!p->isA("Primitive")) { compile_error(sl,"Can't annotate '"+name+"': not a primitive"); } else { // add in attributes parse_primitive_attributes(&li, &dynamic_cast<Primitive &>(*p)); } return NULL; // annotations are like primitives: nothing returned } else if(opname=="letfed" || opname=="letfed+") { return letfed_to_graph(sl,space,env,opname=="letfed"); } else if(opname=="macro") { V4 << "Defining macro\n"; sexp_to_macro(sl,env); return NULL; } else if(opname=="include") { for(int j=1;j<sl->len();j++) { SExpr *ex = (*sl)[j]; V4 << "Including file: "<<ce2s(ex)<<endl; if(ex->isSymbol()) interpret_file(dynamic_cast<SE_Symbol &>(*ex).name); else compile_error(ex,"File name "+ex->to_str()+" is not a symbol"); } return NULL; } else if(opname=="quote") { if(sl->len()!=2) return field_err(sl,space,"Quote requires an argument: "+s->to_str()); V4 << "Creating quote literal\n"; return dfg->add_literal(quote_to_literal_type((*sl)[1]),space,s); } else if(opname=="quasiquote") { return field_err(sl,space,"Quasiquote only allowed in macros: "+sl->to_str()); } // check if it's a macro CompilationElement* ce = env->lookup(opname); if(ce && ce->isA("Macro")) { V4 << "Applying macro\n"; SExpr* new_expr; if(ce->isA("MacroOperator")) { new_expr = expand_macro(&dynamic_cast<MacroOperator &>(*ce),sl); if(new_expr->attributes.count("DUMMY")) // Mark of a failure return field_err(s,space,"Macro expansion failed on "+s->to_str()); } else { // it's a MacroSymbol new_expr = sl->copy(); dynamic_cast<SE_List &>(*new_expr).children[0] = dynamic_cast<Macro &>(*ce).pattern; } return sexp_to_graph(new_expr,space,env); } } // if we didn't return yet, it's an ordinary composite expression Operator *op = sexp_to_op(sl->op(),env); if(op->marked(":protected")) compile_warn(op,"operator '"+op->name+"' not intended for direct use."); OperatorInstance *oi = new OperatorInstance(s,op,space); for(vector<SExpr*>::iterator it=sl->args(); it!=sl->children.end(); it++) { Field* sub = sexp_to_graph(*it,space,env); // operator defs, primitives, and macros return null & are ignored if(sub) oi->add_input(sub); } if(!op->signature->legal_length(oi->inputs.size())) { compile_error(s,"Called "+ce2s(op)+" with "+i2s(oi->inputs.size())+ " arguments; it requires "+op->signature->num_arg_str()); } V4 << "Added operator "<<ce2s(oi)<<endl; return oi->output; } ierror("Fell through sexp_to_graph w/o returning for: "+s->to_str()); }
Log * makeSTATSlog() { //Log state. std::vector<SExpr> fields; fields.push_back(SExpr(CONTENT_TYPE_S, "STATS")); std::vector<SExpr> fvector = { SExpr("flags"), SExpr("serv_connected", control::serv_connected, control::flags[control::serv_connected]), SExpr("control_connected", control::control_connected, control::flags[control::control_connected]), SExpr("fileio", control::fileio, control::flags[control::fileio]), SExpr("SENSORS", control::SENSORS, control::flags[control::SENSORS]), SExpr("GUARDIAN", control::GUARDIAN, control::flags[control::GUARDIAN]), SExpr("COMM", control::COMM, control::flags[control::COMM]), SExpr("LOCATION", control::LOCATION, control::flags[control::LOCATION]), SExpr("ODOMETRY", control::ODOMETRY, control::flags[control::ODOMETRY]), SExpr("OBSERVATIONS", control::OBSERVATIONS, control::flags[control::OBSERVATIONS]), SExpr("LOCALIZATION", control::LOCALIZATION, control::flags[control::LOCALIZATION]), SExpr("BALLTRACK", control::BALLTRACK, control::flags[control::BALLTRACK]), SExpr("VISION", control::VISION, control::flags[control::VISION]), SExpr("tripoint", control::tripoint, control::flags[control::tripoint]), SExpr("thumbnail", control::thumbnail, control::flags[control::thumbnail]) }; fields.push_back(SExpr(fvector)); fields.push_back(SExpr("num_buffers", NUM_LOG_BUFFERS)); fields.push_back(SExpr("num_cores", (int) NUM_CORES)); SExpr ratios; ratios.append(SExpr("ratio")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { ratios.append(SExpr(LOG_RATIO[i])); } fields.push_back(ratios); SExpr sizes; sizes.append(SExpr("size")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { sizes.append(SExpr(LOG_BUFFER_SIZES[i])); } fields.push_back(sizes); time_t NOW = time(NULL); fields.push_back(SExpr("con_uptime", control::flags[control::serv_connected] ? difftime(NOW, cio_upstart) : 0)); fields.push_back(SExpr("cnc_uptime", control::flags[control::control_connected] ? difftime(NOW, cnc_upstart) : 0)); fields.push_back(SExpr("fio_uptime", control::flags[control::fileio] ? difftime(NOW, fio_upstart) : 0)); fields.push_back(SExpr("log_uptime", difftime(NOW, main_upstart))); SExpr manages; manages.append(SExpr("bufmanage")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { manages.append(makeBufManage(i)); } fields.push_back(manages); /* This system of grabbing io state is subject to multi-threading accuracy drift. It is therefore only for estimates. */ io_state_t zerostate; bzero(&zerostate, sizeof(io_state_t)); SExpr state_total; state_total.append(SExpr("total-state")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { state_total.append(makeBufState(&zerostate, total + i)); } fields.push_back(state_total); if (control::flags[control::fileio]) { SExpr state_file; state_file.append(SExpr("file-state")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { state_file.append(makeBufState(fio_start + i, total + i)); } fields.push_back(state_file); } if (control::flags[control::serv_connected]) { SExpr state_serv; state_serv.append(SExpr("serv-state")); for (int i = 0; i < NUM_LOG_BUFFERS; ++i) { state_serv.append(makeBufState(cio_start + i, total + i)); } fields.push_back(state_serv); } std::vector<SExpr> contents = {SExpr(fields)}; return new Log(LOG_FIRST_ATOM_S, "makeSTATSlog()", time(NULL), LOG_VERSION, contents, ""); };
SExpr* SCodeScope::typePredict(SendInfo* info) { // try static type prediction PReg* r = info->rcvr->preg(); stringOop sel = info->sel; if (sel == VMString[IF_TRUE_] || sel == VMString[IF_FALSE_] || sel == VMString[IF_TRUE_FALSE_] || sel == VMString[IF_FALSE_TRUE_] || sel == VMString[OR] || sel == VMString[AND] || sel == VMString[NOT]) { // boolean message if (PrintInlining) { lprintf("%*s*type-predicting %s\n", (void*)depth, "", sel->copy_null_terminated()); } info->predicted = true; bool allowUnlikely = theSIC->useUncommonTraps; if (SICDeferUncommonBranches && (sel == VMString[IF_TRUE_] || sel == VMString[IF_FALSE_] || sel == VMString[IF_TRUE_FALSE_] || sel == VMString[IF_FALSE_TRUE_])) { // these bets are really safe - make uncommon even when recompiling // due to uncommon trap (if the ifTrue itself caused the trap, // rscope->isUncommonAt will be false, so this is safe) allowUnlikely = true; } if (allowUnlikely) { if (rscope->isUncommonAt(_bci, false)) { // ok, no uncommon trap here } else if (rscope->hasSubScopes(_bci)) { // has real send for ifTrue et al. -- must be NIC-compiled // make uncommon unlikely if no non-true/false receiver present RScopeBList* subs = rscope->subScopes(_bci); for (fint i = subs->length() - 1; i >= 0; i--) { RScope* s = subs->nth(i); SExpr* rcvr = s->receiverExpr(); if (rcvr->hasMap()) { Map* m = rcvr->map(); if (m != Memory-> true_map() && m != Memory->false_map()) { allowUnlikely = false; break; } } } if (WizardMode && !allowUnlikely) warning("SIC: non-bool receiver for ifTrue: et al. detected"); } if (allowUnlikely) { // make unknown case unlikely despite info->rcvr = info->rcvr->makeUnknownUnlikely(this); } } SExpr* rcvr = info->rcvr; SExpr* t = new ConstantSExpr(Memory->trueObj , r, NULL); SExpr* f = new ConstantSExpr(Memory->falseObj, r, NULL); // make sure we don't destroy splitting info; only add types if not // already present if (rcvr->findMap(Memory-> true_mapOop()) == NULL) rcvr = rcvr->mergeWith(t, NULL); if (rcvr->findMap(Memory->false_mapOop()) == NULL) rcvr = rcvr->mergeWith(f, NULL); return rcvr; } if (// binary integer arithmetic messages sel == VMString[PLUS] || sel == VMString[MINUS] || sel == VMString[PERCENT] || sel == VMString[LESS_THAN] || sel == VMString[LESS_EQUAL] || sel == VMString[GREATER_EQUAL] || sel == VMString[GREATER_THAN] | // integer looping messages sel == VMString[TO_DO_] || sel == VMString[UP_TO_DO_] || sel == VMString[DOWN_TO_DO_] || sel == VMString[TO_BY_DO_] || sel == VMString[UP_TO_BY_DO_] || sel == VMString[DOWN_TO_BY_DO_] || // unary integer arithmetic selectors sel == VMString[SUCCESSOR] || sel == VMString[SUCC] || sel == VMString[PREDECESSOR] || sel == VMString[PRED]) { if (info->rcvr->findMap(Memory->smi_map->enclosing_mapOop())) return info->rcvr; if (PrintInlining) { lprintf("%*s*type-predicting %s\n", (void*)depth, "", sel->copy_null_terminated()); } info->predicted = true; SExpr* res = info->rcvr->mergeWith(new MapSExpr(Memory->smi_map->enclosing_mapOop(), r, NULL), NULL); if (theSIC->useUncommonTraps && rscope->isUncommonAt(_bci, false)) { info->rcvr = res = res->makeUnknownUnlikely(this); } return res; } return info->rcvr; }
SExpr* SCodeScope::picPredict(SendInfo* info) { // check PICs for information if (!UsePICRecompilation) return info->rcvr; bool canBeUnlikely = theSIC->useUncommonTraps; if (rscope->hasSubScopes(_bci)) { RScopeBList* l = rscope->subScopes(_bci); if (l->first()->isUntakenScope() && l->length() == 1) { return picPredictUnlikely(info, (RUntakenScope*)l->first()); } else if (info->rcvr->containsUnknown()) { if (PrintInlining) { lprintf("%*s*PIC-type-predicting %s (%ld maps)\n", (void*)depth, "", info->sel->copy_null_terminated(), (void*)l->length()); } for (fint i = 0; i < l->length(); i++) { RScope* r = l->nth(i); SExpr* expr = r->receiverExpr(); if (expr->isUnknownSExpr()) { // untaken real send (from PIC) } else if (expr->map()->is_block()) { // for now, doesn't make sense to predict block maps because of // map cloning if (PrintInlining) { lprintf("%*s*not predicting block map\n", (void*)depth, ""); } canBeUnlikely = false; } else { SExpr* alreadyThere = info->rcvr->findMap(expr->myMapOop()); if (alreadyThere) { // generalize to map if only have constant if (alreadyThere->isConstantSExpr()) info->rcvr = info->rcvr->mergeWith(expr, NULL); } else { // add map only if type isn't already present (for splitting) info->predicted = true; info->rcvr = info->rcvr->mergeWith(expr, NULL); if (expr->hasConstant() && l->length() == 1) { // check to see if single predicted receiver is true or false; // if so, add other boolean to prediction. Reduces the number // of uncommon branches; not doing so appears to be overly // aggressive (as observed experimentally) oop c = expr->constant(); if (c == Memory->trueObj && !info->rcvr->findMap(Memory->false_mapOop())) { SExpr* f = new ConstantSExpr(Memory->falseObj, NULL, NULL); info->rcvr = info->rcvr->mergeWith(f, NULL); } else if (c == Memory->falseObj && !info->rcvr->findMap(Memory->true_mapOop())) { SExpr* t = new ConstantSExpr(Memory->trueObj, NULL, NULL); info->rcvr = info->rcvr->mergeWith(t, NULL); } } } } } } else { // know receiver type precisely return info->rcvr; } // mark unknown branch as unlikely UnknownSExpr* u = info->rcvr->findUnknown(); if (u && canBeUnlikely && theSIC->useUncommonTraps && rscope->isUncommonAt(_bci, false)) { info->rcvr = info->rcvr->makeUnknownUnlikely(this); } } else if (theSIC->useUncommonTraps && info->primFailure && rscope->isUncommonAt(_bci, true)) { // this is the failure send of a primitive, and the failure was made // uncommon in the recompilee, and it was never taken, so keep it // uncommon if (PrintInlining) { lprintf("%*s*PIC-type-predicting %s as never executed (2)\n", (void*)depth, "", info->sel->copy_null_terminated()); } info->rcvr = new UnknownSExpr(info->rcvr->preg(), NULL, true); } assert(info->rcvr->preg(), "should have a preg"); return info->rcvr; }
SExpr* SCodeScope::inlineSend(SendInfo* info) { stringOop sel = info->sel; SExpr* res = NULL; info->resReg = new SAPReg(this); MergeNode* merge = NULL; fint argc = sel->arg_count(); if (!Inline && !InlineSTMessages) { // don't do any inlining info->needRealSend = true; } else { info->rcvr = picPredict(info); UnknownSExpr* u = info->rcvr->findUnknown(); if (u && !u->isUnlikely()) { info->rcvr = typePredict(info); } if (info->rcvr->really_hasMap(this)) { // single map - try to inline this send SSelfScope* s = tryLookup(info, info->rcvr); if (s) { SExpr* r = doInline(s, info->rcvr, theNodeGen->current, NULL); if (r->isNoResultSExpr()) { res = r; } else { theNodeGen->append(new NopNode()); // to get right scope for r res = r->shallowCopy(r->preg(), theNodeGen->current); } } else { if (PrintInlining) { lprintf("%*s*marking %s send ReceiverStatic\n", (void*)depth,"", selector_string(sel)); } // receiver type is constant (but e.g. method was too big to inline) info->l |= ReceiverStaticBit; info->needRealSend = true; } } else if (info->rcvr->isMergeSExpr()) { res = inlineMerge(info, merge); } else { // unknown receiver // NB: *must* use uncommon branch if marked unlikely because // future type tests won't test for unknown if (info->rcvr->findUnknown()->isUnlikely()) { // generate an uncommon branch for the unknown case, not a send theNodeGen->current = theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim); info->needRealSend = false; if (PrintInlining) { lprintf("%*s*making %s uncommon\n", (void*)depth,"",selector_string(sel)); } } else { info->needRealSend = true; } } } if (info->needRealSend) { SExpr* r = genRealSend(info); res = res ? res->mergeWith(r, merge) : r; } if (merge && res && !res->isNoResultSExpr()) theNodeGen->branch(merge); // now pop expr stack for (fint i = 0; i < argc; i++) exprStack->pop(); if (!info->isSelfImplicit) exprStack->pop(); if (!res) res = new NoResultSExpr; return res; }
SExpr* SPrimScope::inlineAtPut(bool objVector) { assert(_selector == VMString[objVector ? _AT_PUT_ : _BYTE_AT_PUT_], "bad selector"); bool okRcvr = receiver->hasMap(); Map* rm; if (okRcvr) { rm = receiver->map(); if (objVector) { okRcvr = rm->is_objVector(); } else { okRcvr = rm->is_byteVector(); } } if (!okRcvr) { // receiver type not known statically return NULL; } if (PrintInlining) lprintf("%*s*inlining _%sAtPut:\n", (void*)(depth-1), "", objVector ? "" :"Byte"); SExpr* arg = args->nth(1); NodeGen* ng = theNodeGen; if (SICDebug) ng->comment("inlined _At:Put:/_ByteAt:Put:"); fint b = bci(); bool intArg = arg->hasMap() && arg->map() == Memory->smi_map; bool willFail = arg->hasMap() && arg->map() != Memory->smi_map; bool useUncommonTrap = !willFail && theSIC->useUncommonTraps && sender()->rscope->isUncommonAt(sender()->bci(), true); PReg* errorPR = useUncommonTrap ? NULL : new SAPReg(_sender, b, b); Node* at; if (objVector) { PReg* elementArgPR = args->nth(0)->preg(); // materialize value arg theNodeGen->materializeBlock(elementArgPR, _sender->sig, new PRegBList(1)); fint size = ((slotsMap*)rm)->empty_vector_object_size(); at = new ArrayAtPutNode(receiver->preg(), arg->preg(), intArg, elementArgPR, resultPR, errorPR, size * oopSize - Mem_Tag); } else { SExpr* value = args->nth(0); bool intVal = value->hasMap() && value->map() == Memory->smi_map; willFail |= value->hasMap() && value->map() != Memory->smi_map; at = new ByteArrayAtPutNode(receiver->preg(), arg->preg(), intArg, value->preg(), intVal, resultPR, errorPR); } ng->append(at); // success case - int index, in bounds MergeNode* ok = (MergeNode*)ng->append(new NopNode); // merge of success & failure branches MergeNode* done = (MergeNode*)ok->append(new MergeNode("inlineAtPut done")); // failure case SExpr* res = receiver->shallowCopy(resultPR, ok); ng->current = at->append1(new MergeNode("inlineAtPut current")); if (useUncommonTrap) { if (PrintInlining) { lprintf("%*s*making atPut: failure uncommon\n", (void*)(depth-1), ""); } ng->uncommonBranch(currentExprStack(0), true); ng->current = done; } else { Node* dummy; SExpr* failExpr = genPrimFailure(NULL, errorPR, dummy, done, resultPR); assert(done, "node should always exist"); res = res->mergeWith(failExpr, done); } return res; }
void Animation::fromSExpr(SExpr in) { m_ids.clear(); //enum Type{None, Add, Remove, Move, Turn, Attack, Hurt, Eat, Grab, Throw, Give, Build}; //Sigh if(in[0] == "add") { m_type = Add; m_ids.push_back(atoi( in[1].c_str() )); } else if(in[0] == "move") { m_type = Move; m_ids.push_back(atoi( in[1].c_str() )); m_x = atoi( in[2].c_str() ); m_y = atoi( in[3].c_str() ); } else if(in[0] == "remove") { m_type = Remove; m_ids.push_back(atoi( in[1].c_str() )); } else if(in[0] == "attack") { m_type = Attack; m_ids.push_back(atoi( in[1].c_str() )); m_x = atoi( in[2].c_str() ); m_y = atoi( in[3].c_str() ); } else if(in[0] == "hurt") { m_type = Hurt; SExpr ids = in.next().list(); int count = ids.numElements(); for(int i=0; i < count; ++i) { m_ids.push_back( atoi( ids[0].c_str() )); ids = ids.next(); } } else if(in[0] == "turn") { m_type = Turn; m_ids.push_back(atoi( in[1].c_str() )); m_x = atoi( in[2].c_str() ); //Facing direction } //enum Type{None, Add, Remove, Move, Turn, Attack, Hurt, Eat, Grab, Throw, Give, Build}; else if(in[0] == "eat") { m_type = Eat; m_ids.push_back(atoi( in[1].c_str() )); m_ids.push_back(atoi( in[2].c_str() )); } else if(in[0] == "grab") { m_type = Grab; m_ids.push_back(atoi( in[1].c_str() )); m_ids.push_back(atoi( in[2].c_str() )); } else if(in[0] == "throw") { m_type = Throw; m_ids.push_back(atoi( in[1].c_str() )); m_ids.push_back(atoi( in[2].c_str() )); m_x = atoi( in[3].c_str() ); m_y = atoi( in[4].c_str() ); } else if(in[0] == "give") { m_type = Give; m_ids.push_back(atoi( in[1].c_str() )); m_ids.push_back(atoi( in[2].c_str() )); } else if(in[0] == "build") { m_type = Build; m_ids.push_back(atoi( in[1].c_str() )); m_x = atoi( in[2].c_str() ); m_y = atoi( in[3].c_str() ); } else { //We don't know what this was... m_type = None; } }
SExpr* SPrimScope::inlineIntComparison() { BranchOpCode cond; if (_selector == VMString[_INT_EQ_]) { cond = EQBranchOp; } else if (_selector == VMString[_INT_LT_]) { cond = LTBranchOp; } else if (_selector == VMString[_INT_LE_]) { cond = LEBranchOp; } else if (_selector == VMString[_INT_GT_]) { cond = GTBranchOp; } else if (_selector == VMString[_INT_GE_]) { cond = GEBranchOp; } else if (_selector == VMString[_INT_NE_]) { cond = NEBranchOp; } else { return NULL; } bool intRcvr = receiver->hasMap() && receiver->map() == Memory->smi_map; SExpr* arg = args->nth(0); bool intArg = arg->hasMap() && arg->map() == Memory->smi_map; if (PrintInlining) lprintf("%*s*inlining int comparison prim\n", (void*)(depth-1), ""); NodeGen* n = theNodeGen; Node* branch = n->append(new TBranchNode(cond, receiver->preg(), intRcvr, arg->preg(), intArg)); // false branch n->move(falsePR(), resultPR); SExpr* falseExpr= new ConstantSExpr(Memory->falseObj, resultPR, n->current); MergeNode* done = (MergeNode*)n->append( new MergeNode("inlineIntComparison done")); // true branch n->current = branch->append1(new AssignNode(truePR(), resultPR)); SExpr* trueExpr = new ConstantSExpr(Memory->trueObj, resultPR, n->current); n->branch(done); SExpr* res = trueExpr->copyMergeWith(falseExpr, resultPR, done); // failure branch if (!intRcvr || !intArg) { branch->hasSideEffects_now = true; if (theSIC->useUncommonTraps && sender()->rscope->isUncommonAt(sender()->bci(), true)) { n->current = branch->append(2, new NopNode); n->uncommonBranch(currentExprStack(0), true); n->current = done; if (PrintInlining) { lprintf("%*s*making int comparison failure uncommon\n", (void*)(depth-1), ""); } } else { fint b = bci(); PReg* error = new SAPReg(_sender, b, b); PReg* err = new_ConstPReg(_sender, VMString[BADTYPEERROR]); n->current = branch->append(2, new AssignNode(err, error)); Node* dummy; SExpr* failExpr = genPrimFailure(NULL, error, dummy, done, resultPR); assert(done, "merge should always exist"); res = (MergeSExpr*)res->mergeWith(failExpr, done); } } return res; }
SExpr* SCodeScope::inlineMerge(SendInfo* info, MergeNode*& merge) { // inline the send by type-casing; return uninlined cases in others list // If merge has no predecessors, return NULL for merge ref. SExpr* res = NULL; assert(info->rcvr->isMergeSExpr(), "must be a merge"); MergeSExpr* r = (MergeSExpr*)info->rcvr; stringOop sel = info->sel; merge = NULL; if (r->isSplittable() && shouldSplit(info)) { return splitMerge(info, merge); } fint ncases = r->exprs->length(); if (ncases > SICTypeCaseLimit) { info->needRealSend = true; if (PrintInlining) { lprintf("%*s*not type-casing %s (%ld > SICTypeCaseLimit)\n", (void*)depth, "", selector_string(sel), (void*)ncases); } return res; } assert( merge == NULL, "I assume merge is out param only"); merge = new MergeNode("inlineMerge merge"); if (SICDebug) { char* s = NEW_RESOURCE_ARRAY(char, 200); sprintf(s, "begin type-case of %s (ends at node N%ld)", sel->copy_null_terminated(), long(merge->id())); theNodeGen->comment(s); } if (PrintInlining) { lprintf("%*s*type-casing %s\n", (void*)depth, "", selector_string(sel)); } // build list of cases to inline // (add only immediate maps at first, collect others in ...2 lists SSelfScopeBList* slist = new SSelfScopeBList(ncases); SSelfScopeBList* slist2 = new SSelfScopeBList(ncases); SExprBList* elist = new SExprBList(ncases); SExprBList* elist2 = new SExprBList(ncases); SExprBList* others = new SExprBList(ncases); OopBList* mlist = new OopBList(ncases); OopBList* mlist2 = new OopBList(ncases); bool needMapLoad = false; fint i; for (i = 0; i < ncases; i++) { SExpr* nth = r->exprs->nth(i); assert(!nth->isConstantSExpr() || nth->next == NULL || nth->constant() == nth->next->constant(), "shouldn't happen: merged consts - convert to map"); SSelfScope* s; if (!nth->hasMap() || (s = tryLookup(info, nth)) == NULL) { // cannot inline others->append(nth); info->needRealSend = true; continue; } // can inline this case // Notice that for immediates, instead of putting the constants in the mlist, // we put the maps. No point in optimizing just for 17. -- dmu 6/05 Map* map = nth->map(); if (map == Memory->smi_map || map == Memory->float_map) { slist ->append(s); // immediate maps go first // Bug fix: instead of nth->shallowCopy, must generalize to any // with same map, not just the same constant, because other ints (for example) // will pass the type test, too. -- dmu 6/05 elist ->append(new MapSExpr(map->enclosing_mapOop(), r->preg(), NULL)); mlist ->append(map->enclosing_mapOop()); continue; } // can inline but not immediate map slist2->append(s); // append later elist2->append(nth->shallowCopy(r->preg(), NULL)); // use preg of merge if (nth->isConstantSExpr()) { mlist2->append(nth->constant()); } else { needMapLoad = true; // will need to load map of testee mlist2->append(map->enclosing_mapOop()); } } mlist->appendList(mlist2); elist->appendList(elist2); slist->appendList(slist2); // now do the type test and inline the individual cases if (slist->length() > 0) { memoizeBlocks(sel); Node* typeCase = theNodeGen->append(new TypeTestNode(r->preg(), mlist, needMapLoad, info->needRealSend)); Node* fallThrough = typeCase->append(new NopNode); for (i = 0; i < slist->length(); i++) { theNodeGen->current = typeCase->append(i + 1, new NopNode); SExpr* e = doInline(slist->nth(i), elist->nth(i), theNodeGen->current, merge); if (!e->isNoResultSExpr()) { theNodeGen->append(new NopNode); e = e->shallowCopy(info->resReg, theNodeGen->current); res = res ? res->mergeWith(e, merge) : e; } theNodeGen->branch(merge); } theNodeGen->current = fallThrough; } if (res && res->isMergeSExpr()) res->setNode(merge, info->resReg); assert( info->needRealSend && others->length() || !info->needRealSend && !others->length(), "inconsistent"); // NB: *must* use uncommon branch if marked unlikely because // future type tests won't test for unknown if (others->isEmpty()) { // typecase cannot fail theNodeGen->deadEnd(); } else if ( others->length() == 1 && others->first()->isUnknownSExpr() && ((UnknownSExpr*)others->first())->isUnlikely()) { // generate an uncommon branch for the unknown case, not a send theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim); info->needRealSend = false; if (PrintInlining) lprintf("%*s*making %s uncommon (2)\n", (void*)depth,"",selector_string(sel)); } return res; }
SExpr* SPrimScope::inlineAt(bool objVector) { assert(_selector == VMString[objVector ? _AT_ : _BYTE_AT_], "bad selector"); bool okRcvr = receiver->hasMap(); Map* rm; if (okRcvr) { rm = receiver->map(); if (objVector) { okRcvr = rm->is_objVector(); } else { okRcvr = rm->is_byteVector(); } } if (!okRcvr) { // receiver type not known statically return NULL; } if (PrintInlining) lprintf("%*s*inlining %s\n", (void*)(depth-1), "", objVector ? "_At:" : "_ByteAt:"); SExpr* arg = args->nth(0); NodeGen* ng = theNodeGen; if (SICDebug) ng->comment("inlined _At:/_ByteAt:"); fint b = bci(); bool intArg = arg->hasMap() && arg->map() == Memory->smi_map; bool willFail = arg->hasMap() && arg->map() != Memory->smi_map; bool useUncommonTrap = !willFail && theSIC->useUncommonTraps && sender()->rscope->isUncommonAt(sender()->bci(), true); // optimization: don't set error reg if using uncommon trap // (primitive will be reexecuted anyway) PReg* errorPR = useUncommonTrap ? NULL : new SAPReg(_sender, b, b); Node* at; if (objVector) { fint size = ((slotsMap*)rm)->empty_vector_object_size(); at = new ArrayAtNode(receiver->preg(), arg->preg(), intArg, resultPR, errorPR, size * oopSize - Mem_Tag); } else { at = new ByteArrayAtNode(receiver->preg(), arg->preg(), intArg, resultPR, errorPR); } ng->append(at); // success case - int index, in bounds NopNode* ok = (NopNode*)ng->append(new NopNode); // merge of success & failure branches MergeNode* done = (MergeNode*)ok->append(new MergeNode("inlineAt done")); // failure case ng->current = at->append1(new NopNode); if (useUncommonTrap) { if (PrintInlining) { lprintf("%*s*making at: failure uncommon\n", (void*)(depth-1), ""); } ng->uncommonBranch(currentExprStack(0), true); ng->current = done; } else { Node* dummy; SExpr* failExpr = genPrimFailure(NULL, errorPR, dummy, done, resultPR); assert(done, "merge should exist"); } return new UnknownSExpr(resultPR, ok); }
uint32_t cnc_setCameraParams(Log * arg) { size_t u = arg->data().size(); bool success = receivedParams.ParseFromString(arg->data()); if(!success) { std::cerr<<"Failed to Parse Params\n"; } else { SExpr s; SExpr h = SExpr("hflip",receivedParams.h_flip()); SExpr v = SExpr("vflip",receivedParams.v_flip()); SExpr ae = SExpr("autoexposure",receivedParams.auto_exposure()); SExpr b = SExpr("brightness",receivedParams.brightness()); SExpr c = SExpr("contrast",receivedParams.contrast()); SExpr sat = SExpr("saturation",receivedParams.saturation()); SExpr hue = SExpr("hue",receivedParams.hue()); SExpr sharp = SExpr("sharpness",receivedParams.sharpness()); SExpr gamma = SExpr("gamma",receivedParams.gamma()); SExpr awb = SExpr("auto_whitebalance",receivedParams.autowhitebalance()); SExpr expo = SExpr("exposure",receivedParams.exposure()); SExpr gain = SExpr("gain",receivedParams.gain()); SExpr wb = SExpr("white_balance",receivedParams.whitebalance()); SExpr ftb = SExpr("fade_to_black",receivedParams.fadetoblack()); s.append(h); s.append(v); s.append(ae); s.append(b); s.append(c); s.append(sat); s.append(hue); s.append(sharp); s.append(gamma); s.append(awb); s.append(expo); s.append(gain); s.append(wb); s.append(ftb); std::string stringToWrite = s.serialize(); #ifdef V5_ROBOT std::cout<<"Saving as V5"<<std::endl; if(receivedParams.whichcamera() == "TOP"){ std::cout<<"TOP Params Received"<<std::endl; std::ofstream file("/home/nao/nbites/Config/V5topCameraParams.txt"); std::cout<<stringToWrite<<std::endl; file << stringToWrite; file.close(); std::cout<<"Saving Done"<<std::endl; } else { std::cout<<"Bottom Params Received"<<std::endl; std::ofstream file("/home/nao/nbites/Config/V5bottomCameraParams.txt"); std::cout<<stringToWrite<<std::endl; file << stringToWrite; file.close(); std::cout<<"Saving Done"<<std::endl; } #else std::cout<<"Saving as V4"<<std::endl; if(receivedParams.whichcamera() == "TOP"){ std::cout<<"TOP Params Received"<<std::endl; std::ofstream file("/home/nao/nbites/Config/V4topCameraParams.txt"); file << stringToWrite; file.close(); std::cout<<"Saving Done"<<std::endl; } else { std::cout<<"Bottom Params Received"<<std::endl; std::ofstream file("/home/nao/nbites/Config/V4bottomCameraParams.txt"); file << stringToWrite; file.close(); std::cout<<"Saving Done"<<std::endl; } #endif } return 0; }
SExpr* SPrimScope::genPrimFailure(PrimNode* call, PReg* errorReg, Node*& test, MergeNode*& merge, PReg* resultReg, bool failure) { // generate primitive failure code // two modes: // if call == NULL, omit the test for failure because it's already // been generated (inlined prim.); in this case, errorReg // must be set // if call != NULL, generate test code (setting test & merge node args) // returns the result of the failure branch // pop prim args (they're not on the expr stack anymore in the fail branch) while (npop-- > 0) exprStack()->pop(); SCodeScope* s = sender(); NodeGen* ng = theNodeGen; if (call) { fint b = bci(); SAPReg* t = new SAPReg(s, b, b); // extract tag field and test for mark tag ng->append(new ArithRCNode(AndArithOp, call->dest(), Tag_Mask, t)); ng->append(new ArithRCNode(SubCCArithOp, t, Tag_Mask, ng->noPR)); test = ng->append(new BranchNode(NEBranchOp)); // failure branch; load error string if (!errorReg) errorReg = new SAPReg(s, b, b); ng->current = test->append(new ArithRCNode(SubArithOp, call->dest(), Mark_Tag-Mem_Tag, errorReg)); } SExpr* failReceiver = hasFailBlock ? failBlock : receiver; SendInfo* info = new SendInfo(failReceiver, NormalLookupType, false, false, (stringOop)failSelector, NULL); info->computeNSends(rscope, bci()); info->primFailure = failure; info->restartPrim = call == NULL; // restart inlined prims (unc. traps) s->exprStack->push(failReceiver); if (errorReg->isConstPReg()) { s->exprStack->push(new ConstantSExpr(((ConstPReg*)errorReg)->constant, errorReg, ng->current)); } else { s->exprStack->push(new MapSExpr(Memory->stringObj->map()->enclosing_mapOop(), errorReg, ng->current)); } ConstPReg* failSelReg = new_ConstPReg(s, selector()); s->exprStack->push(new ConstantSExpr(selector(), failSelReg, NULL)); SExpr* res = s->inlineSend(info); if (res->isNoResultSExpr()) { // never returns ng->current = merge; // set to NULL if no merge } else { if (needZap) { assert(failBlock->preg()->isBlockPReg(), "should be a block"); ng->zapBlock((BlockPReg*)failBlock->preg()); } ng->move(res->preg(), resultReg); res = res->shallowCopy(resultReg, ng->current); // moved creation down from before if res->isNoResult... // to avoid creating unreachable merge -- dmu if (merge == NULL) merge = new MergeNode("genPrimFailure merge"); ng->append(merge); } return res; }
WastConverter(const std::string& outDir, const boost::filesystem::path& path) : outDir_(outDir) { baseName_ = path.stem().string(); SExpr fileExpr = SExprParser::parseFile(path.string()); for (const SExpr& child : fileExpr.children()) { const std::string& firstValue = child[0].value(); if (firstValue == "module") { setCurrentModule(child); } else if (firstValue == "assert_invalid") { std::ofstream outStream(generateOutFile("invalid")); outStream << child[1].toString(); outStream.close(); } else if (firstValue == "assert_return_nan") { SExpr functionCall = convertInvoke(child[1]); SExpr newTest = SExprParser::parseString("if (i32.eq (i32.and () " + functionCall.toString() + ") (nop) (unreachable)"); mainFunction_.addChild(newTest); } else if (firstValue == "assert_return") { if (child.children().size() == 2) { SExpr functionCall = convertInvoke(child[1]); mainFunction_.addChild(functionCall); } else { std::string compareType = child[2][0].value().substr(0, 3); SExpr functionCall = convertInvoke(child[1]); SExpr newTest = SExprParser::parseString("if (" + compareType + ".eq " + functionCall.toString() + " " + child[2].toString() +") (nop) (unreachable)"); mainFunction_.addChild(newTest); } } else if (firstValue == "assert_trap") { SExpr functionCall = convertInvoke(child[1]); SExpr mainFunctionWithTrap = mainFunction_; mainFunctionWithTrap.addChild(functionCall); SExpr result = currentModuleExpr_; result.addChild(mainFunctionWithTrap); std::ofstream outStream(generateOutFile("trap")); outStream << result.toString(); outStream.close(); } else if (firstValue == "invoke") { SExpr functionCall = convertInvoke(child[1]); mainFunction_.addChild(functionCall); } else { std::cerr << "Can't handle assert " << child.toString() << std::endl; } } SExpr positiveModule = currentModuleExpr_; positiveModule.addChild(mainFunction_); std::ofstream outStream(generatePositiveOutFile("positive")); outStream << positiveModule.toString(); outStream.close(); }