int examine_inside_scaling_none(void) { int i; double inside; inside_failure = 0.0; for (i = 0; i < num_roots; i++) { inside = expl_graph[roots[i]->id]->inside; if (i == failure_root_index) { inside_failure = inside; if (!(1.0 - inside_failure > 0.0)) { emit_error("Probability of failure being unity"); RET_ERR(err_invalid_numeric_value); } } else { if (!(inside > 0.0)) { emit_error("Probability of an observed goal being zero"); RET_ERR(err_invalid_numeric_value); } } } return BP_TRUE; }
int examine_inside_scaling_log_exp(void) { int i; double inside; /* [23 Aug 2007, by yuizumi] * By the code below, inside_failure can take only a non-zero value * when `failure' is observed. We can therefore safely use zero as * an indicator of failure being not observed. Zero is chosen just * for convenience in implementation of the parallel version. */ inside_failure = 0.0; for (i = 0; i < num_roots; i++) { inside = expl_graph[roots[i]->id]->inside; if (i == failure_root_index) { inside_failure = inside; /* log-scale */ if (!(inside_failure < 0.0)) { emit_error("Probability of failure being unity"); RET_ERR(err_invalid_numeric_value); } } else { if (!isfinite(inside)) { emit_error("Probability of an observed goal being zero"); RET_ERR(err_invalid_numeric_value); } } } return BP_TRUE; }
/* We check if all smoothing constants are positive (MAP), * or all smoothing constants are zero. If some are positive, * but the others are zero, die immediately. We also check * if there exist parameters fixed at zero in MAP estimation. */ int check_smooth(int *smooth) { /* q = +4 : found non-zero smoothing constants +2 : found zero-valued smoothing constants +1 : found parameters fixed to zero */ int i, q = 0; SW_INS_PTR sw_ins_ptr; for (i = 0; i < occ_switch_tab_size; i++) { sw_ins_ptr = occ_switches[i]; while (sw_ins_ptr != NULL) { if (sw_ins_ptr->smooth_prolog < 0) { emit_error("negative delta values in MAP estimation"); RET_ERR(err_invalid_numeric_value); } q |= (sw_ins_ptr->smooth_prolog < TINY_PROB) ? 2 : 4; q |= (sw_ins_ptr->fixed && sw_ins_ptr->inside < TINY_PROB) ? 1 : 0; sw_ins_ptr = sw_ins_ptr->next; } } switch (q) { case 0: /* p.counts = (none), w/o 0-valued params */ case 1: /* p.counts = (none), with 0-valued params */ emit_internal_error("unexpected case in check_smooth()"); RET_ERR(ierr_unmatched_branches); break; case 2: /* p.counts = 0 only, w/o 0-valued params */ case 3: /* p.counts = 0 only, with 0-valued params */ *smooth = 0; break; case 4: /* p.counts = + only, w/o 0-valued params */ *smooth = 1; break; case 5: /* p.counts = + only, with 0-valued params */ emit_error("parameters fixed to zero in MAP estimation"); RET_ERR(err_invalid_numeric_value); break; case 6: /* p.counts = (both), w/o 0-valued params */ case 7: /* p.counts = (both), with 0-valued params */ emit_error("mixture of zero and non-zero pseudo counts"); RET_ERR(err_invalid_numeric_value); } transfer_hyperparams_prolog(); return BP_TRUE; }
int update_params(void) { int i; SW_INS_PTR ptr; double sum; for (i = 0; i < occ_switch_tab_size; i++) { ptr = occ_switches[i]; sum = 0.0; while (ptr != NULL) { sum += ptr->total_expect; ptr = ptr->next; } if (sum != 0.0) { ptr = occ_switches[i]; if (ptr->fixed > 0) continue; while (ptr != NULL) { if (ptr->fixed == 0) ptr->inside = ptr->total_expect / sum; if (log_scale && ptr->inside < TINY_PROB) { emit_error("Parameter being zero (-inf in log scale) -- %s", prism_sw_ins_string(ptr->id)); RET_ERR(err_underflow); } ptr = ptr->next; } } } return BP_TRUE; }
/// Performs the call to Python bool PythonScript::executeString() { emit started(MSG_STARTED); bool success(false); GlobalInterpreterLock gil; PyObject * compiledCode = compileToByteCode(false); PyObject *result(NULL); if(compiledCode) { result = executeCompiledCode(compiledCode); } // If an error has occurred we need to construct the error message // before any other python code is run QString msg; if(!result) { emit_error(); } else { emit finished(MSG_FINISHED); success = true; } if(isInteractive()) { generateAutoCompleteList(); } Py_XDECREF(compiledCode); Py_XDECREF(result); return success; }
/// Performs the call to Python bool PythonScript::executeString() { emit started(MSG_STARTED); bool success(false); ScopedPythonGIL lock; PyObject *compiledCode = compileToByteCode(false); PyObject *result(nullptr); if (compiledCode) { result = executeCompiledCode(compiledCode); } // If an error has occurred we need to construct the error message // before any other python code is run if (!result) { emit_error(); // If a script was aborted we both raise a KeyboardInterrupt and // call Algorithm::cancel to make sure we capture it. The doubling // can leave an interrupt in the pipeline so we clear it was we've // got the error info out m_interp->raiseAsyncException(m_threadID, nullptr); } else { emit finished(MSG_FINISHED); success = true; if (isInteractive()) { generateAutoCompleteList(); } } Py_XDECREF(compiledCode); Py_XDECREF(result); return success; }
bool PythonScript::compile(bool for_eval) { if(Context->isA("Table")) { PyDict_SetItemString(localDict,"__builtins__",PyDict_GetItemString(env()->globalDict(),"__builtins__")); PyObject *ret = PyRun_String("def col(c,*arg):\n\ttry: return self.cell(c,arg[0])\n\texcept(IndexError): return self.cell(c,i)\n",Py_file_input,localDict,localDict); if (ret) Py_DECREF(ret); else PyErr_Print(); } else if(Context->isA("Matrix")) { PyDict_SetItemString(localDict,"__builtins__",PyDict_GetItemString(env()->globalDict(),"__builtins__")); PyObject *ret = PyRun_String("def cell(*arg):\n\ttry: return self.cell(arg[0],arg[1])\n\texcept(IndexError): return self.cell(i,j)\n",Py_file_input,localDict,localDict); if (ret) Py_DECREF(ret); else PyErr_Print(); } bool success=false; Py_XDECREF(PyCode); PyCode = Py_CompileString(Code.ascii(),Name,Py_eval_input); if (PyCode) { // code is a single expression success = true; } else if (for_eval) { // code contains statements PyErr_Clear(); PyObject *key, *value; int i=0; QString signature = ""; while(PyDict_Next(localDict, &i, &key, &value)) signature.append(PyString_AsString(key)).append(","); signature.truncate(signature.length()-1); QString fdef = "def __doit__("+signature+"):\n"; fdef.append(Code); fdef.replace('\n',"\n\t"); PyCode = Py_CompileString(fdef,Name,Py_file_input); if (PyCode) { PyObject *tmp = PyDict_New(); Py_XDECREF(PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), tmp)); Py_DECREF(PyCode); PyCode = PyDict_GetItemString(tmp,"__doit__"); Py_XINCREF(PyCode); Py_DECREF(tmp); } success = PyCode != NULL; } else { PyErr_Clear(); PyCode = Py_CompileString(Code.ascii(),Name,Py_file_input); success = PyCode != NULL; } if (!success) { compiled = compileErr; emit_error(env()->errorMsg(), 0); } else compiled = isCompiled; return success; }
static void error_unless(Value *cond, const std::string &msg, jl_codectx_t *ctx) { BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); builder.CreateCondBr(cond, passBB, failBB); builder.SetInsertPoint(failBB); emit_error(msg, ctx); builder.CreateBr(passBB); ctx->f->getBasicBlockList().push_back(passBB); builder.SetInsertPoint(passBB); }
static Value *emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { JL_NARGS(cglobal, 1, 2); jl_value_t *rt=NULL; Value *res; JL_GC_PUSH1(&rt); if (nargs == 2) { rt = jl_interpret_toplevel_expr_in(ctx->module, args[2], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); JL_TYPECHK(cglobal, type, rt); rt = (jl_value_t*)jl_apply_type((jl_value_t*)jl_pointer_type, jl_tuple1(rt)); } else { rt = (jl_value_t*)jl_voidpointer_type; } Type *lrt = julia_type_to_llvm(rt); if (lrt == NULL) lrt = T_pint8; native_sym_arg_t sym = interpret_symbol_arg(args[1], ctx, "cglobal"); if (sym.jl_ptr != NULL) { res = builder.CreateIntToPtr(sym.jl_ptr, lrt); } else if (sym.fptr != NULL) { res = literal_pointer_val(sym.fptr, lrt); } else { void *symaddr; if (sym.f_lib != NULL) symaddr = add_library_sym(sym.f_name, sym.f_lib); else symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(sym.f_name); if (symaddr == NULL) { std::stringstream msg; msg << "cglobal: could not find symbol "; msg << sym.f_name; if (sym.f_lib != NULL) { msg << " in library "; msg << sym.f_lib; } emit_error(msg.str(), ctx); res = literal_pointer_val(NULL, lrt); } else { res = jl_Module->getOrInsertGlobal(sym.f_name, lrt->getContainedType(0)); } } JL_GC_POP(); return mark_julia_type(res, rt); }
QVariant MuParserScript::eval() { if (compiled != Script::isCompiled && !compile()) return QVariant(); try { // see documentation of s_currentInstance for explanation s_currentInstance = this; return m_parser.Eval(); } catch (EmptySourceError *e) { // formula tried to access a table cell marked as invalid return ""; } catch (mu::ParserError &e) { emit_error(QString::fromLocal8Bit(e.GetMsg().c_str()), 0); return QVariant(); } }
/** * \brief Pre-process #Code and hand it to #m_parser. * * This implements some functionality not directly supported by muParser, like overloaded functions * and multi-line expressions. See class documentation of MuParserScript for details. */ bool MuParserScript::compile(bool asFunction) { Q_UNUSED(asFunction); // only needed for Python QString intermediate = Code.trimmed(); // pre-processed version of #Code // remove comments bool inString = false; int commentStart = -1; for (int i=0; i<intermediate.size(); i++) switch (intermediate.at(i).toAscii()) { case '"': if (commentStart < 0) inString = !inString; break; case '#': if (!inString) commentStart = i; break; case '\n': if (commentStart >= 0) { intermediate.remove(commentStart, i-commentStart); i = commentStart; commentStart = -1; } break; } if (commentStart >= 0) intermediate.remove(commentStart, intermediate.size()-commentStart); // simplify statement separators intermediate.replace(QRegExp("([;\\n]\\s*)+"),"; "); // recursively translate legacy functions col(), tablecol() and cell() if (Context && Context->inherits("Table")) if (!translateLegacyFunctions(intermediate)) return false; try { m_parser.SetExpr(qPrintable(intermediate)); } catch (mu::ParserError &e) { emit_error(QString::fromLocal8Bit(e.GetMsg().c_str()), 0); return false; } compiled = isCompiled; return true; }
/** * \brief Set a (local, double-valued) variable. * * Other kinds of variables are not supported (integers are converted to * doubles). * * \sa m_variables */ bool MuParserScript::setDouble(double value, const char *name) { QByteArray baName(name); QMap<QByteArray, double>::iterator entry = m_variables.find(baName); if (entry == m_variables.end()) { // variable is not known yet entry = m_variables.insert(baName, value); try { m_parser.DefineVar(name, entry.operator->()); } catch (mu::ParserError &e) { m_variables.erase(entry); emit_error(QString::fromLocal8Bit(e.GetMsg().c_str()), 0); return false; } } else // variable is known and only needs to be updated *entry = value; return true; }
/* compute node->inside (CRF inside) */ int compute_feature_scaling_none(void) { int i,k; double sum, this_path_inside, this_sws_inside; EG_NODE_PTR eg_ptr; EG_PATH_PTR path_ptr; for (i = 0; i < sorted_egraph_size; i++) { eg_ptr = sorted_expl_graph[i]; sum = 0.0; path_ptr = eg_ptr->path_ptr; if (path_ptr == NULL) { sum = 1.0; /* path_ptr should not be NULL; but it happens */ } else { while (path_ptr != NULL) { this_path_inside = 1.0; for (k = 0; k < path_ptr->children_len; k++) { this_path_inside *= path_ptr->children[k]->inside; } this_sws_inside = 0.0; for (k = 0; k < path_ptr->sws_len; k++) { this_sws_inside += (path_ptr->sws[k]->inside * path_ptr->sws[k]->inside_h); } this_path_inside *= exp(this_sws_inside); path_ptr->inside = this_path_inside; //path_ptr->inside = exp(?) sum += this_path_inside; path_ptr = path_ptr->next; } } if (!isfinite(sum)) { emit_error("overflow CRF-inside"); RET_ERR(err_overflow); } eg_ptr->inside = sum; //eg_ptr->inside = exp(?) } return BP_TRUE; }
static int compute_gradient_scaling_log_exp(void) { int i,k; EG_PATH_PTR path_ptr; EG_NODE_PTR eg_ptr,node_ptr; SW_INS_PTR sw_ptr; double q,r; for (i = 0; i < sw_ins_tab_size; i++) { switch_instances[i]->total_expect = 0.0; switch_instances[i]->has_first_expectation = 0; switch_instances[i]->first_expectation = 0.0; } for (i = 0; i < sorted_egraph_size; i++) { sorted_expl_graph[i]->outside = 0.0; sorted_expl_graph[i]->has_first_outside = 0; sorted_expl_graph[i]->first_outside = 0.0; } for (i = 0; i < num_roots; i++) { if (roots[i]->pid == -1) { eg_ptr = expl_graph[roots[i]->id]; if (i == failure_root_index) { eg_ptr->first_outside = log(num_goals / (1.0 - exp(inside_failure))); } else { eg_ptr->first_outside = log((double)(roots[i]->sgd_count)) - eg_ptr->inside; } eg_ptr->has_first_outside = 1; eg_ptr->outside = 1.0; } } /* sorted_expl_graph[to] must be a root node */ for (i = sorted_egraph_size - 1; i >= 0; i--) { eg_ptr = sorted_expl_graph[i]; if (eg_ptr->visited == 0) continue; /* First accumulate log-scale outside probabilities: */ if (!eg_ptr->has_first_outside) { emit_internal_error("unexpected has_first_outside[%s]", prism_goal_string(eg_ptr->id)); RET_INTERNAL_ERR; } else if (!(eg_ptr->outside > 0.0)) { emit_internal_error("unexpected outside[%s]", prism_goal_string(eg_ptr->id)); RET_INTERNAL_ERR; } else { eg_ptr->outside = eg_ptr->first_outside + log(eg_ptr->outside); } path_ptr = sorted_expl_graph[i]->path_ptr; while (path_ptr != NULL) { q = sorted_expl_graph[i]->outside + path_ptr->inside; for (k = 0; k < path_ptr->children_len; k++) { node_ptr = path_ptr->children[k]; r = q - node_ptr->inside; if (!node_ptr->has_first_outside) { node_ptr->first_outside = r; node_ptr->outside += 1.0; node_ptr->has_first_outside = 1; } else if (r - node_ptr->first_outside >= log(HUGE_PROB)) { node_ptr->outside *= exp(node_ptr->first_outside - r); node_ptr->first_outside = r; node_ptr->outside += 1.0; } else { node_ptr->outside += exp(r - node_ptr->first_outside); } } for (k = 0; k < path_ptr->sws_len; k++) { sw_ptr = path_ptr->sws[k]; if (!sw_ptr->has_first_expectation) { sw_ptr->first_expectation = q; sw_ptr->total_expect += 1.0; sw_ptr->has_first_expectation = 1; } else if (q - sw_ptr->first_expectation >= log(HUGE_PROB)) { sw_ptr->total_expect *= exp(sw_ptr->first_expectation - q); sw_ptr->first_expectation = q; sw_ptr->total_expect += 1.0; } else { sw_ptr->total_expect += exp(q - sw_ptr->first_expectation); } } path_ptr = path_ptr->next; } } /* unscale total_expect */ for (i = 0; i < sw_ins_tab_size; i++) { sw_ptr = switch_instances[i]; if (!sw_ptr->has_first_expectation) continue; if (!(sw_ptr->total_expect > 0.0)) { emit_error("unexpected expectation for %s",prism_sw_ins_string(i)); RET_ERR(err_invalid_numeric_value); } sw_ptr->total_expect = exp(sw_ptr->first_expectation + log(sw_ptr->total_expect)); } for (i=0; i<occ_switch_tab_size; i++) { sw_ptr = occ_switches[i]; while (sw_ptr!=NULL) { sw_ptr->gradient = (sw_ptr->count - sw_ptr->total_expect) * sw_ptr->inside_h; if (crf_penalty != 0.0) { sw_ptr->gradient -= sw_ptr->inside * crf_penalty; } sw_ptr = sw_ptr->next; } } return BP_TRUE; }
Socks5::Socks5(Settings s, Logger *lp, Poller *poller) : Emitter(lp), settings(s), conn(settings["family"].c_str(), settings["socks5_address"].c_str(), settings["socks5_port"].c_str(), lp, poller), proxy_address(settings["socks5_address"]), proxy_port(settings["socks5_port"]) { logger->debug("socks5: connecting to Tor at %s:%s", settings["socks5_address"].c_str(), settings["socks5_port"].c_str()); // Step #0: Steal "error", "connect", and "flush" handlers conn.on_error([this](Error err) { emit_error(err); }); conn.on_connect([this]() { conn.on_flush([]() { // Nothing }); // Step #1: send out preferred authentication methods logger->debug("socks5: connected to Tor!"); Buffer out; out.write_uint8(5); // Version out.write_uint8(1); // Number of methods out.write_uint8(0); // "NO_AUTH" meth. conn.send(out); logger->debug("socks5: >> version=5"); logger->debug("socks5: >> number of methods=1"); logger->debug("socks5: >> NO_AUTH (0)"); // Step #2: receive the allowed authentication methods conn.on_data([this](Buffer d) { buffer << d; auto readbuf = buffer.readn(2); if (readbuf == "") { return; // Try again after next recv() } logger->debug("socks5: << version=%d", readbuf[0]); logger->debug("socks5: << auth=%d", readbuf[1]); if (readbuf[0] != 5 || // Reply version readbuf[1] != 0) { // Preferred auth method emit_error(BadSocksVersionError()); return; } // Step #3: ask Tor to connect to remote host Buffer out; out.write_uint8(5); // Version out.write_uint8(1); // CMD_CONNECT out.write_uint8(0); // Reserved out.write_uint8(3); // ATYPE_DOMAINNAME logger->debug("socks5: >> version=5"); logger->debug("socks5: >> CMD_CONNECT (0)"); logger->debug("socks5: >> Reserved (0)"); logger->debug("socks5: >> ATYPE_DOMAINNAME (3)"); auto address = settings["address"]; if (address.length() > 255) { emit_error(SocksAddressTooLongError()); return; } out.write_uint8(address.length()); // Len out.write(address.c_str(), address.length()); // String logger->debug("socks5: >> domain len=%d", (uint8_t)address.length()); logger->debug("socks5: >> domain str=%s", address.c_str()); auto portnum = std::stoi(settings["port"]); if (portnum < 0 || portnum > 65535) { emit_error(SocksInvalidPortError()); return; } out.write_uint16(portnum); // Port logger->debug("socks5: >> port=%d", portnum); conn.send(out); // Step #4: receive Tor's response conn.on_data([this](Buffer d) { buffer << d; if (buffer.length() < 5) { return; // Try again after next recv() } auto peekbuf = buffer.peek(5); logger->debug("socks5: << version=%d", peekbuf[0]); logger->debug("socks5: << reply=%d", peekbuf[1]); logger->debug("socks5: << reserved=%d", peekbuf[2]); logger->debug("socks5: << atype=%d", peekbuf[3]); // TODO: Here we should process peekbuf[1] more // carefully to map to the error that occurred // and report it correctly to the caller if (peekbuf[0] != 5 || // Version peekbuf[1] != 0 || // Reply peekbuf[2] != 0) { // Reserved emit_error(SocksGenericError()); return; } auto atype = peekbuf[3]; // Atype size_t total = 4; // Version .. Atype size if (atype == 1) { total += 4; // IPv4 addr size } else if (atype == 3) { total += 1 // Len size + peekbuf[4]; // String size } else if (atype == 4) { total += 16; // IPv6 addr size } else { emit_error(SocksGenericError()); return; } total += 2; // Port size if (buffer.length() < total) { return; // Try again after next recv() } buffer.discard(total); // // Step #5: we are now connected // Restore the original hooks // Tell upstream we are connected // If more data, pass it up // conn.on_data([this](Buffer d) { emit_data(d); }); conn.on_flush([this]() { emit_flush(); }); emit_connect(); // Note that emit_connect() may have called close() if (!isclosed && buffer.length() > 0) { emit_data(buffer); } }); }); }); }
// ccall(pointer, rettype, (argtypes...), args...) static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { JL_NARGSV(ccall, 3); jl_value_t *ptr=NULL, *rt=NULL, *at=NULL; JL_GC_PUSH(&ptr, &rt, &at); ptr = jl_interpret_toplevel_expr_in(ctx->module, args[1], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); rt = jl_interpret_toplevel_expr_in(ctx->module, args[2], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); if (jl_is_tuple(rt)) { std::string msg = "in " + ctx->funcName + ": ccall: missing return type"; jl_error(msg.c_str()); } at = jl_interpret_toplevel_expr_in(ctx->module, args[3], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); void *fptr=NULL; char *f_name=NULL, *f_lib=NULL; if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) { ptr = jl_tupleref(ptr,0); } if (jl_is_symbol(ptr)) f_name = ((jl_sym_t*)ptr)->name; else if (jl_is_byte_string(ptr)) f_name = jl_string_data(ptr); if (f_name != NULL) { // just symbol, default to JuliaDLHandle #ifdef __WIN32__ fptr = jl_dlsym_e(jl_dl_handle, f_name); if (!fptr) { fptr = jl_dlsym_e(jl_kernel32_handle, f_name); if (!fptr) { fptr = jl_dlsym_e(jl_ntdll_handle, f_name); if (!fptr) { fptr = jl_dlsym_e(jl_crtdll_handle, f_name); if (!fptr) { fptr = jl_dlsym(jl_winsock_handle, f_name); } } } } else { // available in process symbol table fptr = NULL; } #else // will look in process symbol table #endif } else if (jl_is_cpointer_type(jl_typeof(ptr))) { fptr = *(void**)jl_bits_data(ptr); } else if (jl_is_tuple(ptr) && jl_tuple_len(ptr)>1) { jl_value_t *t0 = jl_tupleref(ptr,0); jl_value_t *t1 = jl_tupleref(ptr,1); if (jl_is_symbol(t0)) f_name = ((jl_sym_t*)t0)->name; else if (jl_is_byte_string(t0)) f_name = jl_string_data(t0); else JL_TYPECHK(ccall, symbol, t0); if (jl_is_symbol(t1)) f_lib = ((jl_sym_t*)t1)->name; else if (jl_is_byte_string(t1)) f_lib = jl_string_data(t1); else JL_TYPECHK(ccall, symbol, t1); } else { JL_TYPECHK(ccall, pointer, ptr); } if (f_name == NULL && fptr == NULL) { JL_GC_POP(); emit_error("ccall: null function pointer", ctx); return literal_pointer_val(jl_nothing); } JL_TYPECHK(ccall, type, rt); JL_TYPECHK(ccall, tuple, at); JL_TYPECHK(ccall, type, at); jl_tuple_t *tt = (jl_tuple_t*)at; std::vector<Type *> fargt(0); std::vector<Type *> fargt_sig(0); Type *lrt = julia_type_to_llvm(rt); if (lrt == NULL) { JL_GC_POP(); return literal_pointer_val(jl_nothing); } size_t i; bool haspointers = false; bool isVa = false; for(i=0; i < jl_tuple_len(tt); i++) { jl_value_t *tti = jl_tupleref(tt,i); if (jl_is_seq_type(tti)) { isVa = true; tti = jl_tparam0(tti); } Type *t = julia_type_to_llvm(tti); if (t == NULL) { JL_GC_POP(); return literal_pointer_val(jl_nothing); } fargt.push_back(t); if (!isVa) fargt_sig.push_back(t); } // check for calling convention specifier CallingConv::ID cc = CallingConv::C; jl_value_t *last = args[nargs]; if (jl_is_expr(last)) { jl_sym_t *lhd = ((jl_expr_t*)last)->head; if (lhd == jl_symbol("stdcall")) { cc = CallingConv::X86_StdCall; nargs--; } else if (lhd == jl_symbol("cdecl")) { cc = CallingConv::C; nargs--; } else if (lhd == jl_symbol("fastcall")) { cc = CallingConv::X86_FastCall; nargs--; } } if ((!isVa && jl_tuple_len(tt) != (nargs-2)/2) || ( isVa && jl_tuple_len(tt)-1 > (nargs-2)/2)) jl_error("ccall: wrong number of arguments to C function"); // some special functions if (fptr == &jl_array_ptr) { Value *ary = emit_expr(args[4], ctx); JL_GC_POP(); return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt), rt); } // see if there are & arguments for(i=4; i < nargs+1; i+=2) { jl_value_t *argi = args[i]; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { haspointers = true; break; } } // make LLVM function object for the target Constant *llvmf; FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa); if (fptr != NULL) { Type *funcptype = PointerType::get(functype,0); llvmf = ConstantExpr::getIntToPtr( ConstantInt::get(funcptype, (uint64_t)fptr), funcptype); } else { if (f_lib != NULL) add_library_sym(f_name, f_lib); llvmf = jl_Module->getOrInsertFunction(f_name, functype); } // save temp argument area stack pointer Value *saveloc=NULL; Value *stacksave=NULL; if (haspointers) { // TODO: inline this saveloc = builder.CreateCall(save_arg_area_loc_func); stacksave = builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stacksave)); } // emit arguments Value *argvals[(nargs-3)/2]; int last_depth = ctx->argDepth; int nargty = jl_tuple_len(tt); for(i=4; i < nargs+1; i+=2) { int ai = (i-4)/2; jl_value_t *argi = args[i]; bool addressOf = false; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { addressOf = true; argi = jl_exprarg(argi,0); } Type *largty; jl_value_t *jargty; if (isVa && ai >= nargty-1) { largty = fargt[nargty-1]; jargty = jl_tparam0(jl_tupleref(tt,nargty-1)); } else { largty = fargt[ai]; jargty = jl_tupleref(tt,ai); } Value *arg; if (largty == jl_pvalue_llvmt) { arg = emit_expr(argi, ctx, true); } else { arg = emit_unboxed(argi, ctx); if (jl_is_bits_type(expr_type(argi, ctx))) { if (addressOf) arg = emit_unbox(largty->getContainedType(0), largty, arg); else arg = emit_unbox(largty, PointerType::get(largty,0), arg); } } /* #ifdef JL_GC_MARKSWEEP // make sure args are rooted if (largty->isPointerTy() && (largty == jl_pvalue_llvmt || !jl_is_bits_type(expr_type(args[i], ctx)))) { make_gcroot(boxed(arg), ctx); } #endif */ argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf, ai+1, ctx); } // the actual call Value *result = builder.CreateCall(llvmf, ArrayRef<Value*>(&argvals[0],(nargs-3)/2)); if (cc != CallingConv::C) ((CallInst*)result)->setCallingConv(cc); // restore temp argument area stack pointer if (haspointers) { assert(saveloc != NULL); builder.CreateCall(restore_arg_area_loc_func, saveloc); assert(stacksave != NULL); builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stackrestore), stacksave); } ctx->argDepth = last_depth; if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall ctx->f->addFnAttr(Attribute::StackProtectReq); } JL_GC_POP(); if (lrt == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); return mark_julia_type(result, rt); }
// ccall(pointer, rettype, (argtypes...), args...) static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { JL_NARGSV(ccall, 3); jl_value_t *rt=NULL, *at=NULL; JL_GC_PUSH2(&rt, &at); native_sym_arg_t symarg = interpret_symbol_arg(args[1], ctx, "ccall"); Value *jl_ptr=NULL; void *fptr = NULL; char *f_name = NULL, *f_lib = NULL; jl_ptr = symarg.jl_ptr; fptr = symarg.fptr; f_name = symarg.f_name; f_lib = symarg.f_lib; if (f_name == NULL && fptr == NULL && jl_ptr == NULL) { JL_GC_POP(); emit_error("ccall: null function pointer", ctx); return literal_pointer_val(jl_nothing); } rt = jl_interpret_toplevel_expr_in(ctx->module, args[2], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); if (jl_is_tuple(rt)) { std::string msg = "in " + ctx->funcName + ": ccall: missing return type"; jl_error(msg.c_str()); } if (rt == (jl_value_t*)jl_pointer_type) jl_error("ccall: return type Ptr should have an element type, Ptr{T}"); at = jl_interpret_toplevel_expr_in(ctx->module, args[3], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); JL_TYPECHK(ccall, type, rt); JL_TYPECHK(ccall, tuple, at); JL_TYPECHK(ccall, type, at); jl_tuple_t *tt = (jl_tuple_t*)at; std::vector<Type *> fargt(0); std::vector<Type *> fargt_sig(0); Type *lrt = julia_struct_to_llvm(rt); if (lrt == NULL) { JL_GC_POP(); emit_error("ccall: return type doesn't correspond to a C type", ctx); return literal_pointer_val(jl_nothing); } size_t i; bool isVa = false; size_t nargt = jl_tuple_len(tt); std::vector<AttributeWithIndex> attrs; for(i=0; i < nargt; i++) { jl_value_t *tti = jl_tupleref(tt,i); if (tti == (jl_value_t*)jl_pointer_type) jl_error("ccall: argument type Ptr should have an element type, Ptr{T}"); if (jl_is_vararg_type(tti)) { isVa = true; tti = jl_tparam0(tti); } if (jl_is_bitstype(tti)) { // see pull req #978. need to annotate signext/zeroext for // small integer arguments. jl_datatype_t *bt = (jl_datatype_t*)tti; if (bt->size < 4) { if (jl_signed_type == NULL) { jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed")); } #ifdef LLVM32 Attributes::AttrVal av; if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) av = Attributes::SExt; else av = Attributes::ZExt; attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1, ArrayRef<Attributes::AttrVal>(&av, 1))); #else Attribute::AttrConst av; if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) av = Attribute::SExt; else av = Attribute::ZExt; attrs.push_back(AttributeWithIndex::get(i+1, av)); #endif } } Type *t = julia_struct_to_llvm(tti); if (t == NULL) { JL_GC_POP(); std::stringstream msg; msg << "ccall: the type of argument "; msg << i+1; msg << " doesn't correspond to a C type"; emit_error(msg.str(), ctx); return literal_pointer_val(jl_nothing); } fargt.push_back(t); if (!isVa) fargt_sig.push_back(t); } // check for calling convention specifier CallingConv::ID cc = CallingConv::C; jl_value_t *last = args[nargs]; if (jl_is_expr(last)) { jl_sym_t *lhd = ((jl_expr_t*)last)->head; if (lhd == jl_symbol("stdcall")) { cc = CallingConv::X86_StdCall; nargs--; } else if (lhd == jl_symbol("cdecl")) { cc = CallingConv::C; nargs--; } else if (lhd == jl_symbol("fastcall")) { cc = CallingConv::X86_FastCall; nargs--; } else if (lhd == jl_symbol("thiscall")) { cc = CallingConv::X86_ThisCall; nargs--; } } if ((!isVa && jl_tuple_len(tt) != (nargs-2)/2) || ( isVa && jl_tuple_len(tt)-1 > (nargs-2)/2)) jl_error("ccall: wrong number of arguments to C function"); // some special functions if (fptr == &jl_array_ptr) { assert(lrt->isPointerTy()); Value *ary = emit_expr(args[4], ctx); JL_GC_POP(); return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt), rt); } if (fptr == &jl_value_ptr) { assert(lrt->isPointerTy()); jl_value_t *argi = args[4]; bool addressOf = false; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { addressOf = true; argi = jl_exprarg(argi,0); } Value *ary = boxed(emit_expr(argi, ctx)); JL_GC_POP(); return mark_julia_type( builder.CreateBitCast(emit_nthptr_addr(ary, addressOf?1:0),lrt), rt); } // make LLVM function object for the target Value *llvmf; FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa); if (jl_ptr != NULL) { null_pointer_check(jl_ptr,ctx); Type *funcptype = PointerType::get(functype,0); llvmf = builder.CreateIntToPtr(jl_ptr, funcptype); } else if (fptr != NULL) { Type *funcptype = PointerType::get(functype,0); llvmf = literal_pointer_val(fptr, funcptype); } else { void *symaddr; if (f_lib != NULL) symaddr = add_library_sym(f_name, f_lib); else symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name); if (symaddr == NULL) { JL_GC_POP(); std::stringstream msg; msg << "ccall: could not find function "; msg << f_name; if (f_lib != NULL) { msg << " in library "; msg << f_lib; } emit_error(msg.str(), ctx); return literal_pointer_val(jl_nothing); } llvmf = jl_Module->getOrInsertFunction(f_name, functype); } // save place before arguments, for possible insertion of temp arg // area saving code. Value *saveloc=NULL; Value *stacksave=NULL; BasicBlock::InstListType &instList = builder.GetInsertBlock()->getInstList(); Instruction *savespot; if (instList.empty()) { savespot = NULL; } else { // hey C++, there's this thing called pointers... Instruction &_savespot = builder.GetInsertBlock()->back(); savespot = &_savespot; } // emit arguments Value *argvals[(nargs-3)/2]; int last_depth = ctx->argDepth; int nargty = jl_tuple_len(tt); bool needTempSpace = false; for(i=4; i < nargs+1; i+=2) { int ai = (i-4)/2; jl_value_t *argi = args[i]; bool addressOf = false; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { addressOf = true; argi = jl_exprarg(argi,0); } Type *largty; jl_value_t *jargty; if (isVa && ai >= nargty-1) { largty = fargt[nargty-1]; jargty = jl_tparam0(jl_tupleref(tt,nargty-1)); } else { largty = fargt[ai]; jargty = jl_tupleref(tt,ai); } Value *arg; if (largty == jl_pvalue_llvmt || largty->isStructTy()) { arg = emit_expr(argi, ctx, true); } else { arg = emit_unboxed(argi, ctx); if (jl_is_bitstype(expr_type(argi, ctx))) { if (addressOf) arg = emit_unbox(largty->getContainedType(0), largty, arg); else arg = emit_unbox(largty, PointerType::get(largty,0), arg); } } /* #ifdef JL_GC_MARKSWEEP // make sure args are rooted if (largty->isPointerTy() && (largty == jl_pvalue_llvmt || !jl_is_bits_type(expr_type(args[i], ctx)))) { make_gcroot(boxed(arg), ctx); } #endif */ bool mightNeed=false; argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf, ai+1, ctx, &mightNeed); needTempSpace |= mightNeed; } if (needTempSpace) { // save temp argument area stack pointer // TODO: inline this saveloc = CallInst::Create(save_arg_area_loc_func); stacksave = CallInst::Create(Intrinsic::getDeclaration(jl_Module, Intrinsic::stacksave)); if (savespot) instList.insertAfter(savespot, (Instruction*)saveloc); else instList.push_front((Instruction*)saveloc); instList.insertAfter((Instruction*)saveloc, (Instruction*)stacksave); } // the actual call Value *result = builder.CreateCall(llvmf, ArrayRef<Value*>(&argvals[0],(nargs-3)/2)); if (cc != CallingConv::C) ((CallInst*)result)->setCallingConv(cc); #ifdef LLVM32 ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef<AttributeWithIndex>(attrs))); #else ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size())); #endif if (needTempSpace) { // restore temp argument area stack pointer assert(saveloc != NULL); builder.CreateCall(restore_arg_area_loc_func, saveloc); assert(stacksave != NULL); builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stackrestore), stacksave); } ctx->argDepth = last_depth; if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall #ifdef LLVM32 ctx->f->addFnAttr(Attributes::StackProtectReq); #else ctx->f->addFnAttr(Attribute::StackProtectReq); #endif } JL_GC_POP(); if (lrt == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); if (lrt->isStructTy()) { //fprintf(stderr, "ccall rt: %s -> %s\n", f_name, ((jl_tag_type_t*)rt)->name->name->name); assert(jl_is_structtype(rt)); Value *strct = builder.CreateCall(jlallocobj_func, ConstantInt::get(T_size, sizeof(void*)+((jl_datatype_t*)rt)->size)); builder.CreateStore(literal_pointer_val((jl_value_t*)rt), emit_nthptr_addr(strct, (size_t)0)); builder.CreateStore(result, builder.CreateBitCast( emit_nthptr_addr(strct, (size_t)1), PointerType::get(lrt,0))); return mark_julia_type(strct, rt); } return mark_julia_type(result, rt); }
bool PythonScript::compile(bool for_eval) { // Support for the convenient col() and cell() functions. // This can't be done anywhere else, because we need access to the local // variables self, i and j. if(Context->inherits("Table")) { // A bit of a hack, but we need either IndexError or len() from __builtins__. PyDict_SetItemString(localDict, "__builtins__", PyDict_GetItemString(env()->globalDict(), "__builtins__")); PyObject *ret = PyRun_String( "def col(c,*arg):\n" "\ttry: return self.cell(c,arg[0])\n" "\texcept(IndexError): return self.cell(c,i)\n" "def cell(c,r):\n" "\treturn self.cell(c,r)\n" "def tablecol(t,c):\n" "\treturn self.folder().rootFolder().table(t,True).cell(c,i)\n" "def _meth_table_col_(t,c):\n" "\treturn t.cell(c,i)\n" "self.__class__.col = _meth_table_col_", Py_file_input, localDict, localDict); if (ret) Py_DECREF(ret); else PyErr_Print(); } else if(Context->inherits("Matrix")) { // A bit of a hack, but we need either IndexError or len() from __builtins__. PyDict_SetItemString(localDict, "__builtins__", PyDict_GetItemString(env()->globalDict(), "__builtins__")); PyObject *ret = PyRun_String( "def cell(*arg):\n" "\ttry: return self.cell(arg[0],arg[1])\n" "\texcept(IndexError): return self.cell(i,j)\n", Py_file_input, localDict, localDict); if (ret) Py_DECREF(ret); else PyErr_Print(); } bool success=false; Py_XDECREF(PyCode); // Simplest case: Code is a single expression PyCode = Py_CompileString(Code, Name, Py_eval_input); if (PyCode) success = true; else if (for_eval) { // Code contains statements (or errors) and we want to get a return // value from it. // So we wrap the code into a function definition, // execute that (as Py_file_input) and store the function object in PyCode. // See http://mail.python.org/pipermail/python-list/2001-June/046940.html // for why there isn't an easier way to do this in Python. PyErr_Clear(); // silently ignore errors PyObject *key, *value; #if PY_VERSION_HEX >= 0x02050000 Py_ssize_t i=0; #else int i=0; #endif QString signature = ""; while(PyDict_Next(localDict, &i, &key, &value)) signature.append(PyString_AsString(key)).append(","); signature.truncate(signature.length()-1); QString fdef = "def __doit__("+signature+"):\n"; fdef.append(Code); fdef.replace('\n',"\n\t"); PyCode = Py_CompileString(fdef, Name, Py_file_input); if (PyCode) { PyObject *tmp = PyDict_New(); Py_XDECREF(PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), tmp)); Py_DECREF(PyCode); PyCode = PyDict_GetItemString(tmp,"__doit__"); Py_XINCREF(PyCode); Py_DECREF(tmp); } success = (PyCode != NULL); } else { // Code contains statements (or errors), but we do not need to get // a return value. PyErr_Clear(); // silently ignore errors PyCode = Py_CompileString(Code, Name, Py_file_input); success = (PyCode != NULL); } if (!success) { compiled = compileErr; emit_error(env()->errorMsg(), 0); } else compiled = isCompiled; return success; }
/** * \brief Do in-place translation of overloaded functions. * * Recursively replaces: * - col("name") with column("name") * - col(arg) with column("arg") if the current table contains a column named * "arg" and * with column_(arg) otherwise * - col("name", row) with cell("name", row) * - col(arg, row) with cell("arg", row) if the current table contains a column * named "arg" and * with cell_(arg, row) otherwise * - tablecol("tableName", "columnName") with column("tableName/columnName") * - tablecol("tableName", columnIndex) with column__("tableName", columnIndex) * - cell(columnIndex, rowIndex) with cell_(columnIndex, rowIndex) * * Also escapes occurences of / in table/column names, so that legacy formulas * work with the path * argument of the new column() and cell() functions (see resolveColumnPath()). */ bool MuParserScript::translateLegacyFunctions(QString &input) { QRegExp legacyFunction("(\\W||^)(col|tablecol|cell)\\s*\\("); int functionStart = legacyFunction.indexIn(input, 0); while (functionStart != -1) { QStringList arguments; int functionEnd = functionStart; // initialization is a failsafe QString replacement; // parse arguments of function QString currentArgument; for (int i = functionStart + legacyFunction.matchedLength(), parenthesisLevel = 1; parenthesisLevel > 0 && i < input.size(); i++) { switch (input.at(i).toAscii()) { case '"': currentArgument += '"'; for (i++; i < input.size() && input.at(i) != QChar('"'); i++) if (input.at(i) == QChar('\\')) { currentArgument += '\\'; currentArgument += input.at(++i); } else currentArgument += input.at(i); currentArgument += '"'; break; case '\\': currentArgument += '\\'; currentArgument += input.at(++i); break; case '(': parenthesisLevel++; currentArgument += '('; break; case ')': parenthesisLevel--; if (parenthesisLevel > 0) currentArgument += ')'; else functionEnd = i; break; case ',': if (parenthesisLevel == 1) { arguments << currentArgument; currentArgument.clear(); } else currentArgument += ','; break; default: currentArgument += input.at(i); break; } } arguments << currentArgument; // select replacement function call Table *table = qobject_cast<Table *>(Context); if (legacyFunction.cap(2) == "col") { QString columnArgument; bool numericColumn = false; if (arguments.at(0).startsWith("\"")) { // col("name") -> column("name") columnArgument = arguments.at(0); // do escaping of path argument columnArgument.replace("\\", "\\\\"); columnArgument.replace("/", "\\/"); } else if (table && table->d_future_table->column(arguments.at(0), false)) { // hack for ambiguous legacy syntax: // col(name) -> column("name"), if name is a column of the current table columnArgument = "\"" + arguments.at(0) + "\""; // do escaping of path argument columnArgument.replace("\\", "\\\\"); columnArgument.replace("/", "\\/"); } else { // col(expression) -> column_(expression) columnArgument = arguments.at(0); if (!translateLegacyFunctions(columnArgument)) return false; numericColumn = true; } if (arguments.size() > 1) { QString rowArgument = arguments.at(1); if (!translateLegacyFunctions(rowArgument)) return false; replacement = QString("cell") + (numericColumn ? "_" : "") + "(" + columnArgument + "," + rowArgument + ")"; } else replacement = QString("column") + (numericColumn ? "_" : "") + "(" + columnArgument + ")"; } else if (legacyFunction.cap(2) == "tablecol") { // assert number of arguments == 2 if (arguments.size() != 2) { emit_error(tr("tablecol: wrong number of arguments (need 2, got %1)") .arg(arguments.size()), 0); compiled = Script::compileErr; return false; } if (arguments.at(1).startsWith("\"")) { // tablecol("table", "column") -> column("table/column") // do escaping of path argument QString tableArgument = arguments.at(0); tableArgument.replace("\\", "\\\\"); tableArgument.replace("/", "\\/"); QString columnArgument = arguments.at(1); columnArgument.replace("\\", "\\\\"); columnArgument.replace("/", "\\/"); // remove quotation marks tableArgument.remove(tableArgument.size() - 1, 1); columnArgument.remove(0, 1); replacement = QString("column(") + tableArgument + "/" + columnArgument + ")"; } else { // tablecol("table", column) -> column__("table", column) QString rowArgument = arguments.at(1); if (!translateLegacyFunctions(rowArgument)) return false; replacement = QString("column__(") + arguments.at(0) + "," + rowArgument + ")"; } } else { // legacyFunction.cap(2) == "cell" // assert number of arguments == 2 if (arguments.size() != 2) { emit_error(tr("cell: wrong number of arguments (need 2, got %1)") .arg(arguments.size()), 0); compiled = Script::compileErr; return false; } if (arguments.at(0).startsWith("\"")) { // keep cell("column",row) -- this is new-style syntax QString rowArgument = arguments.at(1); if (!translateLegacyFunctions(rowArgument)) return false; replacement = QString("cell(") + arguments.at(0) + "," + rowArgument + ")"; } else { // cell(column,row) -> cell_(column,row) QString columnArgument = arguments.at(0); if (!translateLegacyFunctions(columnArgument)) return false; QString rowArgument = arguments.at(1); if (!translateLegacyFunctions(rowArgument)) return false; replacement = QString("cell_(") + columnArgument + "," + rowArgument + ")"; } } // do replacement if (legacyFunction.cap(1).isEmpty()) // matched with ^, not \W (lookbehind assertion would be darn handy...) input.replace(functionStart, functionEnd - functionStart + 1, replacement); else // need to adjust for the additional matched character input.replace(functionStart + 1, functionEnd - functionStart, replacement); // search for next match, starting at the end of the replaced text functionStart = legacyFunction.indexIn(input, functionStart + replacement.length()); } // while (functionStart != -1) return true; }
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jl_value_t *argex, bool addressOf, int argn, jl_codectx_t *ctx, bool *mightNeedTempSpace, bool *needStackRestore) { Type *vt = jv->getType(); if (ty == jl_pvalue_llvmt) { return boxed(jv,ctx); } else if (ty == vt && !addressOf) { return jv; } else if (vt != jl_pvalue_llvmt) { // argument value is unboxed if (addressOf) { if (ty->isPointerTy() && ty->getContainedType(0)==vt) { // pass the address of an alloca'd thing, not a box // since those are immutable. *needStackRestore = true; Value *slot = builder.CreateAlloca(vt); builder.CreateStore(jv, slot); return builder.CreateBitCast(slot, ty); } } else if ((vt->isIntegerTy() && ty->isIntegerTy()) || (vt->isFloatingPointTy() && ty->isFloatingPointTy()) || (vt->isPointerTy() && ty->isPointerTy())) { if (vt->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits()) { return builder.CreateBitCast(jv, ty); } } // error. box for error handling. jv = boxed(jv,ctx); } else if (jl_is_cpointer_type(jt)) { assert(ty->isPointerTy()); jl_value_t *aty = expr_type(argex, ctx); if (jl_is_array_type(aty) && (jl_tparam0(jt) == jl_tparam0(aty) || jl_tparam0(jt) == (jl_value_t*)jl_bottom_type)) { // array to pointer return builder.CreateBitCast(emit_arrayptr(jv), ty); } if (aty == (jl_value_t*)jl_ascii_string_type || aty == (jl_value_t*)jl_utf8_string_type) { return builder.CreateBitCast(emit_arrayptr(emit_nthptr(jv,1,tbaa_const)), ty); } if (jl_is_structtype(aty) && jl_is_leaf_type(aty) && !jl_is_array_type(aty)) { if (!addressOf) { emit_error("ccall: expected & on argument", ctx); return literal_pointer_val(jl_nothing); } return builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), ty); // skip type tag field } *mightNeedTempSpace = true; Value *p = builder.CreateCall4(prepare_call(value_to_pointer_func), literal_pointer_val(jl_tparam0(jt)), jv, ConstantInt::get(T_int32, argn), ConstantInt::get(T_int32, (int)addressOf)); return builder.CreateBitCast(p, ty); } else if (jl_is_structtype(jt)) { if (addressOf) jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct assert (ty->isStructTy() && (Type*)((jl_datatype_t*)jt)->struct_decl == ty); jl_value_t *aty = expr_type(argex, ctx); if (aty != jt) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); } //TODO: check instead that prefix matches //if (!jl_is_structtype(aty)) // emit_typecheck(emit_typeof(jv), (jl_value_t*)jl_struct_kind, "ccall: Struct argument called with something that isn't a struct", ctx); // //safe thing would be to also check that jl_typeof(aty)->size > sizeof(ty) here and/or at runtime Value *pjv = builder.CreateBitCast(emit_nthptr_addr(jv, (size_t)1), PointerType::get(ty,0)); return builder.CreateLoad(pjv, false); } else if (jl_is_tuple(jt)) { return emit_unbox(ty,jv,jt); } // TODO: error for & with non-pointer argument type assert(jl_is_bitstype(jt)); std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); Value *p = data_pointer(jv); return builder.CreateLoad(builder.CreateBitCast(p, PointerType::get(ty,0)), false); }
/** * Evaluate the code and return the value * @return */ QVariant PythonScript::evaluateImpl() { ScopedPythonGIL lock; PyObject *compiledCode = this->compileToByteCode(true); if (!compiledCode) { return QVariant(""); } PyObject *pyret; beginStdoutRedirect(); if (PyCallable_Check(compiledCode)) { PyObject *empty_tuple = PyTuple_New(0); pyret = PyObject_Call(compiledCode, empty_tuple, localDict); Py_DECREF(empty_tuple); } else { pyret = PyEval_EvalCode(CODE_OBJECT(compiledCode), localDict, localDict); } endStdoutRedirect(); if (!pyret) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(); return QVariant(); } } QVariant qret = QVariant(); /* None */ if (pyret == Py_None) { qret = QVariant(""); } /* numeric types */ else if (PyFloat_Check(pyret)) { qret = QVariant(PyFloat_AS_DOUBLE(pyret)); } else if (INT_CHECK(pyret)) { qret = QVariant((qlonglong)TO_LONG(pyret)); } #if !defined(IS_PY3K) else if (PyLong_Check(pyret)) { qret = QVariant((qlonglong)PyLong_AsLongLong(pyret)); } #endif else if (PyNumber_Check(pyret)) { PyObject *number = PyNumber_Float(pyret); if (number) { qret = QVariant(PyFloat_AS_DOUBLE(number)); Py_DECREF(number); } } /* bool */ else if (PyBool_Check(pyret)) { qret = QVariant(pyret == Py_True); } // could handle advanced types (such as PyList->QValueList) here if needed /* fallback: try to convert to (unicode) string */ if (!qret.isValid()) { #if defined(IS_PY3K) // In 3 everything is unicode PyObject *pystring = PyObject_Str(pyret); if (pystring) { qret = QVariant(QString::fromUtf8(_PyUnicode_AsString(pystring))); } #else PyObject *pystring = PyObject_Unicode(pyret); if (pystring) { PyObject *asUTF8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(pystring), (int)PyUnicode_GET_DATA_SIZE(pystring), nullptr); Py_DECREF(pystring); if (asUTF8) { qret = QVariant(QString::fromUtf8(PyString_AS_STRING(asUTF8))); Py_DECREF(asUTF8); } else if ((pystring = PyObject_Str(pyret))) { qret = QVariant(QString(PyString_AS_STRING(pystring))); Py_DECREF(pystring); } } #endif } Py_DECREF(pyret); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(); } return QVariant(); } return qret; }
int run_em(EM_ENG_PTR em_ptr) { int r, iterate, old_valid, converged, saved = 0; double likelihood, log_prior; double lambda, old_lambda = 0.0; config_em(em_ptr); for (r = 0; r < num_restart; r++) { SHOW_PROGRESS_HEAD("#em-iters", r); initialize_params(); itemp = daem ? itemp_init : 1.0; iterate = 0; /* [21 Aug 2007, by yuizumi] * while-loop for inversed temperature (DAEM). Note that this * loop is evaluated only once for EM without annealing, since * itemp initially set to 1.0 by the code above. */ while (1) { if (daem) { SHOW_PROGRESS_TEMP(itemp); } old_valid = 0; while (1) { if (CTRLC_PRESSED) { SHOW_PROGRESS_INTR(); RET_ERR(err_ctrl_c_pressed); } RET_ON_ERR(em_ptr->compute_inside()); RET_ON_ERR(em_ptr->examine_inside()); likelihood = em_ptr->compute_likelihood(); log_prior = em_ptr->smooth ? em_ptr->compute_log_prior() : 0.0; lambda = likelihood + log_prior; if (verb_em) { if (em_ptr->smooth) { prism_printf("Iteration #%d:\tlog_likelihood=%.9f\tlog_prior=%.9f\tlog_post=%.9f\n", iterate, likelihood, log_prior, lambda); } else { prism_printf("Iteration #%d:\tlog_likelihood=%.9f\n", iterate, likelihood); } } if (debug_level) { prism_printf("After I-step[%d]:\n", iterate); prism_printf("likelihood = %.9f\n", likelihood); print_egraph(debug_level, PRINT_EM); } if (!isfinite(lambda)) { emit_internal_error("invalid log likelihood or log post: %s (at iteration #%d)", isnan(lambda) ? "NaN" : "infinity", iterate); RET_ERR(ierr_invalid_likelihood); } if (old_valid && old_lambda - lambda > prism_epsilon) { emit_error("log likelihood or log post decreased [old: %.9f, new: %.9f] (at iteration #%d)", old_lambda, lambda, iterate); RET_ERR(err_invalid_likelihood); } if (itemp == 1.0 && likelihood > 0.0) { emit_error("log likelihood greater than zero [value: %.9f] (at iteration #%d)", likelihood, iterate); RET_ERR(err_invalid_likelihood); } converged = (old_valid && lambda - old_lambda <= prism_epsilon); if (converged || REACHED_MAX_ITERATE(iterate)) { break; } old_lambda = lambda; old_valid = 1; RET_ON_ERR(em_ptr->compute_expectation()); if (debug_level) { prism_printf("After O-step[%d]:\n", iterate); print_egraph(debug_level, PRINT_EM); } SHOW_PROGRESS(iterate); RET_ON_ERR(em_ptr->update_params()); iterate++; } /* [21 Aug 2007, by yuizumi] * Note that 1.0 can be represented exactly in IEEE 754. */ if (itemp == 1.0) { break; } itemp *= itemp_rate; if (itemp >= 1.0) { itemp = 1.0; } } SHOW_PROGRESS_TAIL(converged, iterate, lambda); if (r == 0 || lambda > em_ptr->lambda) { em_ptr->lambda = lambda; em_ptr->likelihood = likelihood; em_ptr->iterate = iterate; saved = (r < num_restart - 1); if (saved) { save_params(); } } } if (saved) { restore_params(); } em_ptr->bic = compute_bic(em_ptr->likelihood); em_ptr->cs = em_ptr->smooth ? compute_cs(em_ptr->likelihood) : 0.0; return BP_TRUE; }
/* main loop */ static int run_grd(CRF_ENG_PTR crf_ptr) { int r,iterate,old_valid,converged,conv_time,saved = 0; double likelihood,old_likelihood = 0.0; double crf_max_iterate = 0.0; double tmp_epsilon,alpha0,gf_sd,old_gf_sd = 0.0; config_crf(crf_ptr); initialize_weights(); if (crf_learn_mode == 1) { initialize_LBFGS(); printf("L-BFGS mode\n"); } if (crf_learning_rate==1) { printf("learning rate:annealing\n"); } else if (crf_learning_rate==2) { printf("learning rate:backtrack\n"); } else if (crf_learning_rate==3) { printf("learning rate:golden section\n"); } if (max_iterate == -1) { crf_max_iterate = DEFAULT_MAX_ITERATE; } else if (max_iterate >= +1) { crf_max_iterate = max_iterate; } for (r = 0; r < num_restart; r++) { SHOW_PROGRESS_HEAD("#crf-iters", r); initialize_crf_count(); initialize_lambdas(); initialize_visited_flags(); old_valid = 0; iterate = 0; tmp_epsilon = crf_epsilon; LBFGS_index = 0; conv_time = 0; while (1) { if (CTRLC_PRESSED) { SHOW_PROGRESS_INTR(); RET_ERR(err_ctrl_c_pressed); } RET_ON_ERR(crf_ptr->compute_feature()); crf_ptr->compute_crf_probs(); likelihood = crf_ptr->compute_likelihood(); if (verb_em) { prism_printf("Iteration #%d:\tlog_likelihood=%.9f\n", iterate, likelihood); } if (debug_level) { prism_printf("After I-step[%d]:\n", iterate); prism_printf("likelihood = %.9f\n", likelihood); print_egraph(debug_level, PRINT_EM); } if (!isfinite(likelihood)) { emit_internal_error("invalid log likelihood: %s (at iteration #%d)", isnan(likelihood) ? "NaN" : "infinity", iterate); RET_ERR(ierr_invalid_likelihood); } /* if (old_valid && old_likelihood - likelihood > prism_epsilon) { emit_error("log likelihood decreased [old: %.9f, new: %.9f] (at iteration #%d)", old_likelihood, likelihood, iterate); RET_ERR(err_invalid_likelihood); }*/ if (likelihood > 0.0) { emit_error("log likelihood greater than zero [value: %.9f] (at iteration #%d)", likelihood, iterate); RET_ERR(err_invalid_likelihood); } if (crf_learn_mode == 1 && iterate > 0) restore_old_gradient(); RET_ON_ERR(crf_ptr->compute_gradient()); if (crf_learn_mode == 1 && iterate > 0) { compute_LBFGS_y_rho(); compute_hessian(iterate); } else if (crf_learn_mode == 1 && iterate == 0) { initialize_LBFGS_q(); } converged = (old_valid && fabs(likelihood - old_likelihood) <= prism_epsilon); if (converged || REACHED_MAX_ITERATE(iterate)) { break; } old_likelihood = likelihood; old_valid = 1; if (debug_level) { prism_printf("After O-step[%d]:\n", iterate); print_egraph(debug_level, PRINT_EM); } SHOW_PROGRESS(iterate); if (crf_learning_rate == 1) { // annealing tmp_epsilon = (annealing_weight / (annealing_weight + iterate)) * crf_epsilon; } else if (crf_learning_rate == 2) { // line-search(backtrack) if (crf_learn_mode == 1) { gf_sd = compute_gf_sd_LBFGS(); } else { gf_sd = compute_gf_sd(); } if (iterate==0) { alpha0 = 1; } else { alpha0 = tmp_epsilon * old_gf_sd / gf_sd; } if (crf_learn_mode == 1) { tmp_epsilon = line_search_LBFGS(crf_ptr,alpha0,crf_ls_rho,crf_ls_c1,likelihood,gf_sd); } else { tmp_epsilon = line_search(crf_ptr,alpha0,crf_ls_rho,crf_ls_c1,likelihood,gf_sd); } if (tmp_epsilon < EPS) { emit_error("invalid alpha in line search(=0.0) (at iteration #%d)",iterate); RET_ERR(err_line_search); } old_gf_sd = gf_sd; } else if (crf_learning_rate == 3) { // line-search(golden section) if (crf_learn_mode == 1) { tmp_epsilon = golden_section_LBFGS(crf_ptr,0,crf_golden_b); } else { tmp_epsilon = golden_section(crf_ptr,0,crf_golden_b); } } crf_ptr->update_lambdas(tmp_epsilon); iterate++; } SHOW_PROGRESS_TAIL(converged, iterate, likelihood); if (r == 0 || likelihood > crf_ptr->likelihood) { crf_ptr->likelihood = likelihood; crf_ptr->iterate = iterate; saved = (r < num_restart - 1); if (saved) { save_params(); } } } if (crf_learn_mode == 1) clean_LBFGS(); INIT_VISITED_FLAGS; return BP_TRUE; }
static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, jl_value_t *aty, bool addressOf, bool byRef, bool inReg, bool needCopy, int argn, jl_codectx_t *ctx, bool *needStackRestore) { Type *vt = jv->getType(); // We're passing any if (ty == jl_pvalue_llvmt) { return boxed(jv,ctx); } if (ty == vt && !addressOf && !byRef) { return jv; } if (vt != jl_pvalue_llvmt) { // argument value is unboxed if (addressOf || (byRef && inReg)) { if (ty->isPointerTy() && ty->getContainedType(0)==vt) { // pass the address of an alloca'd thing, not a box // since those are immutable. *needStackRestore = true; Value *slot = builder.CreateAlloca(vt); builder.CreateStore(jv, slot); return builder.CreateBitCast(slot, ty); } } else if ((vt->isIntegerTy() && ty->isIntegerTy()) || (vt->isFloatingPointTy() && ty->isFloatingPointTy()) || (vt->isPointerTy() && ty->isPointerTy())) { if (vt->getPrimitiveSizeInBits() == ty->getPrimitiveSizeInBits()) { if (!byRef) { return builder.CreateBitCast(jv, ty); } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateStore(jv,builder.CreateBitCast(mem,vt->getPointerTo())); return mem; } } } else if (vt->isStructTy()) { if (!byRef) { return jv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(vt); builder.CreateStore(jv,mem); return mem; } } emit_error("ccall: argument type did not match declaration", ctx); } if (jl_is_tuple(jt)) { return emit_unbox(ty,jv,jt); } if (jl_is_cpointer_type(jt) && addressOf) { assert(ty->isPointerTy()); jl_value_t *ety = jl_tparam0(jt); if (aty != ety && ety != (jl_value_t*)jl_any_type && jt != (jl_value_t*)jl_voidpointer_type) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, ety, msg.str(), ctx); } if (jl_is_mutable_datatype(ety)) { // no copy, just reference the data field return builder.CreateBitCast(jv, ty); } else if (jl_is_immutable_datatype(ety) && jt != (jl_value_t*)jl_voidpointer_type) { // yes copy Value *nbytes; if (jl_is_leaf_type(ety)) nbytes = ConstantInt::get(T_int32, jl_datatype_size(ety)); else nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(emit_typeof(jv), T_pint32), ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))), false)); *needStackRestore = true; AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreateBitCast(jv, T_pint8), nbytes, 1); return builder.CreateBitCast(ai, ty); } // emit maybe copy *needStackRestore = true; Value *jvt = emit_typeof(jv); BasicBlock *mutableBB = BasicBlock::Create(getGlobalContext(),"is-mutable",ctx->f); BasicBlock *immutableBB = BasicBlock::Create(getGlobalContext(),"is-immutable",ctx->f); BasicBlock *afterBB = BasicBlock::Create(getGlobalContext(),"after",ctx->f); Value *ismutable = builder.CreateTrunc( tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t,mutabl))), false)), T_int1); builder.CreateCondBr(ismutable, mutableBB, immutableBB); builder.SetInsertPoint(mutableBB); Value *p1 = builder.CreatePointerCast(jv, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(immutableBB); Value *nbytes = tbaa_decorate(tbaa_datatype, builder.CreateLoad( builder.CreateGEP(builder.CreatePointerCast(jvt, T_pint32), ConstantInt::get(T_size, offsetof(jl_datatype_t,size)/sizeof(int32_t))), false)); AllocaInst *ai = builder.CreateAlloca(T_int8, nbytes); ai->setAlignment(16); builder.CreateMemCpy(ai, builder.CreatePointerCast(jv, T_pint8), nbytes, 1); Value *p2 = builder.CreatePointerCast(ai, ty); builder.CreateBr(afterBB); builder.SetInsertPoint(afterBB); PHINode *p = builder.CreatePHI(ty, 2); p->addIncoming(p1, mutableBB); p->addIncoming(p2, immutableBB); return p; } if (addressOf) jl_error("ccall: unexpected & on argument"); // the only "safe" thing to emit here is the expected struct assert(jl_is_datatype(jt)); if (aty != jt) { std::stringstream msg; msg << "ccall argument "; msg << argn; emit_typecheck(jv, jt, msg.str(), ctx); } Value *p = data_pointer(jv); Value *pjv = builder.CreatePointerCast(p, PointerType::get(ty,0)); if (byRef) { if (!needCopy) { return pjv; } else { *needStackRestore = true; Value *mem = builder.CreateAlloca(ty); builder.CreateMemCpy(mem,pjv,(uint64_t)jl_datatype_size(jt),(uint64_t)((jl_datatype_t*)jt)->alignment); return mem; } } else { return builder.CreateLoad(pjv,false); } }
QVariant PythonScript::eval() { if (!isFunction) compiled = notCompiled; if (compiled != isCompiled && !compile(true)) return QVariant(); PyObject *pyret; beginStdoutRedirect(); if (PyCallable_Check(PyCode)) { PyObject *empty_tuple = PyTuple_New(0); pyret = PyObject_Call(PyCode, empty_tuple, localDict); Py_DECREF(empty_tuple); } else pyret = PyEval_EvalCode((PyCodeObject*)PyCode, env()->globalDict(), localDict); endStdoutRedirect(); if (!pyret) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(env()->errorMsg(), 0); return QVariant(); } } QVariant qret = QVariant(); /* None */ if (pyret == Py_None) qret = QVariant(""); /* numeric types */ else if (PyFloat_Check(pyret)) qret = QVariant(PyFloat_AS_DOUBLE(pyret)); else if (PyInt_Check(pyret)) qret = QVariant((qlonglong)PyInt_AS_LONG(pyret)); else if (PyLong_Check(pyret)) qret = QVariant((qlonglong)PyLong_AsLongLong(pyret)); else if (PyNumber_Check(pyret)) { PyObject *number = PyNumber_Float(pyret); if (number) { qret = QVariant(PyFloat_AS_DOUBLE(number)); Py_DECREF(number); } /* bool */ } else if (PyBool_Check(pyret)) qret = QVariant(pyret==Py_True, 0); // could handle advanced types (such as PyList->QValueList) here if needed /* fallback: try to convert to (unicode) string */ if(!qret.isValid()) { PyObject *pystring = PyObject_Unicode(pyret); if (pystring) { PyObject *asUTF8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(pystring), PyUnicode_GET_DATA_SIZE(pystring), 0); Py_DECREF(pystring); if (asUTF8) { qret = QVariant(QString::fromUtf8(PyString_AS_STRING(asUTF8))); Py_DECREF(asUTF8); } else if (pystring = PyObject_Str(pyret)) { qret = QVariant(QString(PyString_AS_STRING(pystring))); Py_DECREF(pystring); } } } Py_DECREF(pyret); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { PyErr_Clear(); // silently ignore errors return QVariant(""); } else { emit_error(env()->errorMsg(), 0); return QVariant(); } } else return qret; }
// ccall(pointer, rettype, (argtypes...), args...) static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) { JL_NARGSV(ccall, 3); jl_value_t *ptr=NULL, *rt=NULL, *at=NULL; Value *jl_ptr=NULL; JL_GC_PUSH(&ptr, &rt, &at); ptr = static_eval(args[1], ctx, true); if (ptr == NULL) { jl_value_t *ptr_ty = expr_type(args[1], ctx); Value *arg1 = emit_unboxed(args[1], ctx); if (!jl_is_cpointer_type(ptr_ty)) { emit_typecheck(arg1, (jl_value_t*)jl_voidpointer_type, "ccall: function argument not a pointer or valid constant", ctx); } jl_ptr = emit_unbox(T_size, T_psize, arg1); } rt = jl_interpret_toplevel_expr_in(ctx->module, args[2], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); if (jl_is_tuple(rt)) { std::string msg = "in " + ctx->funcName + ": ccall: missing return type"; jl_error(msg.c_str()); } at = jl_interpret_toplevel_expr_in(ctx->module, args[3], &jl_tupleref(ctx->sp,0), jl_tuple_len(ctx->sp)/2); void *fptr=NULL; char *f_name=NULL, *f_lib=NULL; if (ptr != NULL) { if (jl_is_tuple(ptr) && jl_tuple_len(ptr)==1) { ptr = jl_tupleref(ptr,0); } if (jl_is_symbol(ptr)) f_name = ((jl_sym_t*)ptr)->name; else if (jl_is_byte_string(ptr)) f_name = jl_string_data(ptr); if (f_name != NULL) { // just symbol, default to JuliaDLHandle #ifdef __WIN32__ fptr = jl_dlsym_e(jl_dl_handle, f_name); if (!fptr) { //TODO: when one of these succeeds, store the f_lib name (and clear fptr) fptr = jl_dlsym_e(jl_kernel32_handle, f_name); if (!fptr) { fptr = jl_dlsym_e(jl_ntdll_handle, f_name); if (!fptr) { fptr = jl_dlsym_e(jl_crtdll_handle, f_name); if (!fptr) { fptr = jl_dlsym(jl_winsock_handle, f_name); } } } } else { // available in process symbol table fptr = NULL; } #else // will look in process symbol table #endif } else if (jl_is_cpointer_type(jl_typeof(ptr))) { fptr = *(void**)jl_bits_data(ptr); } else if (jl_is_tuple(ptr) && jl_tuple_len(ptr)>1) { jl_value_t *t0 = jl_tupleref(ptr,0); jl_value_t *t1 = jl_tupleref(ptr,1); if (jl_is_symbol(t0)) f_name = ((jl_sym_t*)t0)->name; else if (jl_is_byte_string(t0)) f_name = jl_string_data(t0); else JL_TYPECHK(ccall, symbol, t0); if (jl_is_symbol(t1)) f_lib = ((jl_sym_t*)t1)->name; else if (jl_is_byte_string(t1)) f_lib = jl_string_data(t1); else JL_TYPECHK(ccall, symbol, t1); } else { JL_TYPECHK(ccall, pointer, ptr); } } if (f_name == NULL && fptr == NULL && jl_ptr == NULL) { JL_GC_POP(); emit_error("ccall: null function pointer", ctx); return literal_pointer_val(jl_nothing); } JL_TYPECHK(ccall, type, rt); JL_TYPECHK(ccall, tuple, at); JL_TYPECHK(ccall, type, at); jl_tuple_t *tt = (jl_tuple_t*)at; std::vector<Type *> fargt(0); std::vector<Type *> fargt_sig(0); Type *lrt = julia_type_to_llvm(rt); if (lrt == NULL) { JL_GC_POP(); return literal_pointer_val(jl_nothing); } size_t i; bool haspointers = false; bool isVa = false; size_t nargt = jl_tuple_len(tt); std::vector<AttributeWithIndex> attrs; for(i=0; i < nargt; i++) { jl_value_t *tti = jl_tupleref(tt,i); if (jl_is_seq_type(tti)) { isVa = true; tti = jl_tparam0(tti); } if (jl_is_bits_type(tti)) { // see pull req #978. need to annotate signext/zeroext for // small integer arguments. jl_bits_type_t *bt = (jl_bits_type_t*)tti; if (bt->nbits < 32) { if (jl_signed_type == NULL) { jl_signed_type = jl_get_global(jl_core_module,jl_symbol("Signed")); } #ifdef LLVM32 Attributes::AttrVal av; if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) av = Attributes::SExt; else av = Attributes::ZExt; attrs.push_back(AttributeWithIndex::get(getGlobalContext(), i+1, ArrayRef<Attributes::AttrVal>(&av, 1))); #else Attribute::AttrConst av; if (jl_signed_type && jl_subtype(tti, jl_signed_type, 0)) av = Attribute::SExt; else av = Attribute::ZExt; attrs.push_back(AttributeWithIndex::get(i+1, av)); #endif } } Type *t = julia_type_to_llvm(tti); if (t == NULL) { JL_GC_POP(); return literal_pointer_val(jl_nothing); } fargt.push_back(t); if (!isVa) fargt_sig.push_back(t); } // check for calling convention specifier CallingConv::ID cc = CallingConv::C; jl_value_t *last = args[nargs]; if (jl_is_expr(last)) { jl_sym_t *lhd = ((jl_expr_t*)last)->head; if (lhd == jl_symbol("stdcall")) { cc = CallingConv::X86_StdCall; nargs--; } else if (lhd == jl_symbol("cdecl")) { cc = CallingConv::C; nargs--; } else if (lhd == jl_symbol("fastcall")) { cc = CallingConv::X86_FastCall; nargs--; } else if (lhd == jl_symbol("thiscall")) { cc = CallingConv::X86_ThisCall; nargs--; } } if ((!isVa && jl_tuple_len(tt) != (nargs-2)/2) || ( isVa && jl_tuple_len(tt)-1 > (nargs-2)/2)) jl_error("ccall: wrong number of arguments to C function"); // some special functions if (fptr == &jl_array_ptr) { Value *ary = emit_expr(args[4], ctx); JL_GC_POP(); return mark_julia_type(builder.CreateBitCast(emit_arrayptr(ary),lrt), rt); } // see if there are & arguments for(i=4; i < nargs+1; i+=2) { jl_value_t *argi = args[i]; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { haspointers = true; break; } } // make LLVM function object for the target Value *llvmf; FunctionType *functype = FunctionType::get(lrt, fargt_sig, isVa); if (jl_ptr != NULL) { null_pointer_check(jl_ptr,ctx); Type *funcptype = PointerType::get(functype,0); llvmf = builder.CreateIntToPtr(jl_ptr, funcptype); } else if (fptr != NULL) { Type *funcptype = PointerType::get(functype,0); llvmf = literal_pointer_val(fptr, funcptype); } else { void *symaddr; if (f_lib != NULL) symaddr = add_library_sym(f_name, f_lib); else symaddr = sys::DynamicLibrary::SearchForAddressOfSymbol(f_name); if (symaddr == NULL) { JL_GC_POP(); std::stringstream msg; msg << "ccall: could not find function "; msg << f_name; if (f_lib != NULL) { msg << " in library "; msg << f_lib; } emit_error(msg.str(), ctx); return literal_pointer_val(jl_nothing); } llvmf = jl_Module->getOrInsertFunction(f_name, functype); } // save temp argument area stack pointer Value *saveloc=NULL; Value *stacksave=NULL; if (haspointers) { // TODO: inline this saveloc = builder.CreateCall(save_arg_area_loc_func); stacksave = builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stacksave)); } // emit arguments Value *argvals[(nargs-3)/2]; int last_depth = ctx->argDepth; int nargty = jl_tuple_len(tt); for(i=4; i < nargs+1; i+=2) { int ai = (i-4)/2; jl_value_t *argi = args[i]; bool addressOf = false; if (jl_is_expr(argi) && ((jl_expr_t*)argi)->head == amp_sym) { addressOf = true; argi = jl_exprarg(argi,0); } Type *largty; jl_value_t *jargty; if (isVa && ai >= nargty-1) { largty = fargt[nargty-1]; jargty = jl_tparam0(jl_tupleref(tt,nargty-1)); } else { largty = fargt[ai]; jargty = jl_tupleref(tt,ai); } Value *arg; if (largty == jl_pvalue_llvmt) { arg = emit_expr(argi, ctx, true); } else { arg = emit_unboxed(argi, ctx); if (jl_is_bits_type(expr_type(argi, ctx))) { if (addressOf) arg = emit_unbox(largty->getContainedType(0), largty, arg); else arg = emit_unbox(largty, PointerType::get(largty,0), arg); } } /* #ifdef JL_GC_MARKSWEEP // make sure args are rooted if (largty->isPointerTy() && (largty == jl_pvalue_llvmt || !jl_is_bits_type(expr_type(args[i], ctx)))) { make_gcroot(boxed(arg), ctx); } #endif */ argvals[ai] = julia_to_native(largty, jargty, arg, argi, addressOf, ai+1, ctx); } // the actual call Value *result = builder.CreateCall(llvmf, ArrayRef<Value*>(&argvals[0],(nargs-3)/2)); if (cc != CallingConv::C) ((CallInst*)result)->setCallingConv(cc); #ifdef LLVM32 ((CallInst*)result)->setAttributes(AttrListPtr::get(getGlobalContext(), ArrayRef<AttributeWithIndex>(attrs))); #else ((CallInst*)result)->setAttributes(AttrListPtr::get(attrs.data(),attrs.size())); #endif // restore temp argument area stack pointer if (haspointers) { assert(saveloc != NULL); builder.CreateCall(restore_arg_area_loc_func, saveloc); assert(stacksave != NULL); builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::stackrestore), stacksave); } ctx->argDepth = last_depth; if (0) { // Enable this to turn on SSPREQ (-fstack-protector) on the function containing this ccall #ifdef LLVM32 ctx->f->addFnAttr(Attributes::StackProtectReq); #else ctx->f->addFnAttr(Attribute::StackProtectReq); #endif } JL_GC_POP(); if (lrt == T_void) return literal_pointer_val((jl_value_t*)jl_nothing); return mark_julia_type(result, rt); }
int mpm_run_em(EM_ENG_PTR emptr) { int r, iterate, old_valid, converged, saved=0; double likelihood, log_prior; double lambda, old_lambda=0.0; config_em(emptr); for (r = 0; r < num_restart; r++) { SHOW_PROGRESS_HEAD("#em-iters", r); initialize_params(); mpm_bcast_inside(); clear_sw_msg_send(); itemp = daem ? itemp_init : 1.0; iterate = 0; while (1) { if (daem) { SHOW_PROGRESS_TEMP(itemp); } old_valid = 0; while (1) { if (CTRLC_PRESSED) { SHOW_PROGRESS_INTR(); RET_ERR(err_ctrl_c_pressed); } if (failure_observed) { inside_failure = mp_sum_value(0.0); } log_prior = emptr->smooth ? emptr->compute_log_prior() : 0.0; lambda = mp_sum_value(log_prior); likelihood = lambda - log_prior; mp_debug("local lambda = %.9f, lambda = %.9f", log_prior, lambda); if (verb_em) { if (emptr->smooth) { prism_printf("Iteration #%d:\tlog_likelihood=%.9f\tlog_prior=%.9f\tlog_post=%.9f\n", iterate, likelihood, log_prior, lambda); } else { prism_printf("Iteration #%d:\tlog_likelihood=%.9f\n", iterate, likelihood); } } if (!isfinite(lambda)) { emit_internal_error("invalid log likelihood or log post: %s (at iterateion #%d)", isnan(lambda) ? "NaN" : "infinity", iterate); RET_ERR(ierr_invalid_likelihood); } if (old_valid && old_lambda - lambda > prism_epsilon) { emit_error("log likelihood or log post decreased [old: %.9f, new: %.9f] (at iteration #%d)", old_lambda, lambda, iterate); RET_ERR(err_invalid_likelihood); } if (itemp == 1.0 && likelihood > 0.0) { emit_error("log likelihood greater than zero [value: %.9f] (at iteration #%d)", likelihood, iterate); RET_ERR(err_invalid_likelihood); } converged = (old_valid && lambda - old_lambda <= prism_epsilon); if (converged || REACHED_MAX_ITERATE(iterate)) { break; } old_lambda = lambda; old_valid = 1; mpm_share_expectation(); SHOW_PROGRESS(iterate); RET_ON_ERR(emptr->update_params()); iterate++; } if (itemp == 1.0) { break; } itemp *= itemp_rate; if (itemp >= 1.0) { itemp = 1.0; } } SHOW_PROGRESS_TAIL(converged, iterate, lambda); if (r == 0 || lambda > emptr->lambda) { emptr->lambda = lambda; emptr->likelihood = likelihood; emptr->iterate = iterate; saved = (r < num_restart - 1); if (saved) { save_params(); } } } if (saved) { restore_params(); } emptr->bic = compute_bic(emptr->likelihood); emptr->cs = emptr->smooth ? compute_cs(emptr->likelihood) : 0.0; return BP_TRUE; }