void OSLCompilerImpl::write_oso_const_value (const ConstantSymbol *sym) const { ASSERT (sym); if (sym->typespec().is_string()) oso ("\"%s\"", sym->strval().c_str()); else if (sym->typespec().is_int()) oso ("%d", sym->intval()); else if (sym->typespec().is_float()) oso ("%.8g", sym->floatval()); else if (sym->typespec().is_triple()) oso ("%.8g %.8g %.8g", sym->vecval()[0], sym->vecval()[1], sym->vecval()[2]); else { ASSERT (0 && "Only know how to output const vals that are single int, float, string"); } }
void OSLCompilerImpl::write_oso_const_value (const ConstantSymbol *sym) const { ASSERT (sym); TypeDesc type = sym->typespec().simpletype(); TypeDesc elemtype = type.elementtype(); int nelements = std::max (1, type.arraylen); if (elemtype == TypeDesc::STRING) for (int i = 0; i < nelements; ++i) oso ("\"%s\"%s", sym->strval(i).c_str(), nelements>1 ? " " : ""); else if (elemtype == TypeDesc::INT) for (int i = 0; i < nelements; ++i) oso ("%d%s", sym->intval(i), nelements>1 ? " " : ""); else if (elemtype == TypeDesc::FLOAT) for (int i = 0; i < nelements; ++i) oso ("%.8g%s", sym->floatval(i), nelements>1 ? " " : ""); else if (equivalent (elemtype, TypeDesc::TypeVector)) for (int i = 0; i < nelements; ++i) oso ("%.8g %.8g %.8g%s", sym->vecval(i)[0], sym->vecval(i)[1], sym->vecval(i)[2], nelements>1 ? " " : ""); else { ASSERT (0 && "Don't know how to output this constant type"); } }
void OSLCompilerImpl::write_oso_metadata (const ASTNode *metanode) const { ASSERT (metanode->nodetype() == ASTNode::variable_declaration_node); const ASTvariable_declaration *metavar = static_cast<const ASTvariable_declaration *>(metanode); Symbol *metasym = metavar->sym(); ASSERT (metasym); TypeSpec ts = metasym->typespec(); std::string pdl; bool ok = metavar->param_default_literals (metasym, pdl, ","); if (ok) { oso ("%%meta{%s,%s,%s} ", ts.string().c_str(), metasym->name(), pdl); } else { error (metanode->sourcefile(), metanode->sourceline(), "Don't know how to print metadata %s (%s) with node type %s", metasym->name().c_str(), ts.string().c_str(), metavar->init()->nodetypename()); } }
auto_ptr<oadrPayload> UpdateReport::generatePayload() { auto_ptr<oadrUpdateReportType> request( new oadrUpdateReportType(requestID())); request->schemaVersion("2.0b"); request->venID(venID()); oadrUpdateReportType::oadrReport_sequence sequence; m_reports->addReportIntervalsToSequence(sequence, m_dtstart, m_reportRequestID, m_createdDateTime); request->oadrReport(sequence); // generate the oadrPayload auto_ptr<oadrSignedObject> oso(new oadrSignedObject()); oso->oadrUpdateReport(request); auto_ptr<oadrPayload> payload(new oadrPayload(oso)); return payload; }
void OSLCompilerImpl::write_oso_file (const std::string &outfilename) { ASSERT (m_osofile == NULL); m_osofile = fopen (outfilename.c_str(), "w"); if (! m_osofile) { error (ustring(), 0, "Could not open \"%s\"", outfilename.c_str()); return; } // FIXME -- remove the hard-coded version! oso ("OpenShadingLanguage %d.%02d\n", OSO_FILE_VERSION_MAJOR, OSO_FILE_VERSION_MINOR); oso ("# Compiled by oslc %s\n", OSL_LIBRARY_VERSION_STRING); ASTshader_declaration *shaderdecl = shader_decl(); oso ("%s %s", shaderdecl->shadertypename(), shaderdecl->shadername().c_str()); // FIXME -- output global hints and metadata oso ("\n"); // Output params, so they are first BOOST_FOREACH (const Symbol *s, symtab()) { if (s->symtype() == SymTypeParam || s->symtype() == SymTypeOutputParam) write_oso_symbol (s); } // Output globals, locals, temps, const BOOST_FOREACH (const Symbol *s, symtab()) { if (s->symtype() == SymTypeLocal || s->symtype() == SymTypeTemp || s->symtype() == SymTypeGlobal || s->symtype() == SymTypeConst) { // Don't bother writing symbols that are never used if (s->lastuse() >= 0) { write_oso_symbol (s); } } } // Output all opcodes int lastline = -1; ustring lastfile; ustring lastmethod ("___uninitialized___"); for (OpcodeVec::iterator op = m_ircode.begin(); op != m_ircode.end(); ++op) { if (lastmethod != op->method()) { oso ("code %s\n", op->method().c_str()); lastmethod = op->method(); lastfile = ustring(); lastline = -1; } if (/*m_debug &&*/ op->sourcefile()) { ustring file = op->sourcefile(); int line = op->sourceline(); if (file != lastfile || line != lastline) oso ("# %s:%d\n# %s\n", file.c_str(), line, retrieve_source (file, line).c_str()); } // Op name oso ("\t%s", op->opname().c_str()); // Register arguments if (op->nargs()) oso (op->opname().length() < 8 ? "\t\t" : "\t"); for (int i = 0; i < op->nargs(); ++i) { int arg = op->firstarg() + i; oso ("%s ", m_opargs[arg]->dealias()->mangled().c_str()); } // Jump targets for (size_t i = 0; i < Opcode::max_jumps; ++i) if (op->jump(i) >= 0) oso ("%d ", op->jump(i)); // // Opcode Hints // bool firsthint = true; // %filename and %line document the source code file and line that // contained code that generated this op. To avoid clutter, we // only output these hints when they DIFFER from the previous op. if (op->sourcefile()) { if (op->sourcefile() != lastfile) { lastfile = op->sourcefile(); oso ("%c%%filename{\"%s\"}", firsthint ? '\t' : ' ', lastfile.c_str()); firsthint = false; } if (op->sourceline() != lastline) { lastline = op->sourceline(); oso ("%c%%line{%d}", firsthint ? '\t' : ' ', lastline); firsthint = false; } } // %argrw documents which arguments are read, written, or both (rwW). if (op->nargs()) { oso ("%c%%argrw{\"", firsthint ? '\t' : ' '); for (int i = 0; i < op->nargs(); ++i) { if (op->argwrite(i)) oso (op->argread(i) ? "W" : "w"); else oso (op->argread(i) ? "r" : "-"); } oso ("\"}"); firsthint = false; } // %argderivs documents which arguments have derivs taken of // them by the op. if (op->argtakesderivs_all()) { oso (" %%argderivs{"); int any = 0; for (int i = 0; i < op->nargs(); ++i) if (op->argtakesderivs(i)) { if (any++) oso (","); oso ("%d", i); } oso ("}"); firsthint = false; } oso ("\n"); } if (lastmethod != main_method_name()) // If no code, still need a code marker oso ("code %s\n", main_method_name().c_str()); oso ("\tend\n"); fclose (m_osofile); m_osofile = NULL; }
void OSLCompilerImpl::write_oso_symbol (const Symbol *sym) { // symtype / datatype / name oso ("%s\t%s\t%s", sym->symtype_shortname(), type_c_str(sym->typespec()), sym->mangled().c_str()); ASTvariable_declaration *v = NULL; if (sym->node() && sym->node()->nodetype() == ASTNode::variable_declaration_node) v = static_cast<ASTvariable_declaration *>(sym->node()); // Print default values bool isparam = (sym->symtype() == SymTypeParam || sym->symtype() == SymTypeOutputParam); if (sym->symtype() == SymTypeConst) { oso ("\t"); write_oso_const_value (static_cast<const ConstantSymbol *>(sym)); oso ("\t"); } else if (v && isparam) { std::string out; v->param_default_literals (sym, out); oso ("\t%s\t", out.c_str()); } // // Now output all the hints, which is most of the work! // int hints = 0; // %meta{} encodes metadata (handled by write_oso_metadata) if (v) { ASSERT (v); for (ASTNode::ref m = v->meta(); m; m = m->next()) { if (hints++ == 0) oso ("\t"); write_oso_metadata (m.get()); } } // %read and %write give the range of ops over which a symbol is used. if (hints++ == 0) oso ("\t"); oso (" %%read{%d,%d} %%write{%d,%d}", sym->firstread(), sym->lastread(), sym->firstwrite(), sym->lastwrite()); // %struct, %structfields, and %structfieldtypes document the // definition of a structure and which other symbols comprise the // individual fields. if (sym->typespec().is_structure()) { if (hints++ == 0) oso ("\t"); const StructSpec *structspec (sym->typespec().structspec()); std::string fieldlist, signature; for (int i = 0; i < (int)structspec->numfields(); ++i) { if (i > 0) fieldlist += ","; fieldlist += structspec->field(i).name.string(); signature += code_from_type (structspec->field(i).type); } oso (" %%struct{\"%s\"} %%structfields{%s} %%structfieldtypes{\"%s\"} %%structnfields{%d}", structspec->mangled().c_str(), fieldlist.c_str(), signature.c_str(), structspec->numfields()); } // %mystruct and %mystructfield document the symbols holding structure // fields, linking them back to the structures they are part of. if (sym->fieldid() >= 0) { if (hints++ == 0) oso ("\t"); ASTvariable_declaration *vd = (ASTvariable_declaration *) sym->node(); oso (" %%mystruct{%s} %%mystructfield{%d}", vd->sym()->mangled().c_str(), sym->fieldid()); } // %derivs hint marks symbols that need to carry derivatives if (sym->has_derivs()) { if (hints++ == 0) oso ("\t"); oso (" %%derivs"); } #if 0 // this is recomputed by the runtime optimizer, no need to bloat the .oso with these // %depends marks, for potential OUTPUTs, which symbols they depend // upon. This is so that derivativeness, etc., may be // back-propagated as shader networks are linked together. if (isparam || sym->symtype() == SymTypeGlobal) { // FIXME const SymPtrSet &deps (m_symdeps[sym]); std::vector<const Symbol *> inputdeps; BOOST_FOREACH (const Symbol *d, deps) if (d->symtype() == SymTypeParam || d->symtype() == SymTypeOutputParam || d->symtype() == SymTypeGlobal || d->symtype() == SymTypeLocal || d->symtype() == SymTypeTemp) inputdeps.push_back (d); if (inputdeps.size()) { if (hints++ == 0) oso ("\t"); oso (" %%depends{"); int deps = 0; for (size_t i = 0; i < inputdeps.size(); ++i) { if (inputdeps[i]->symtype() == SymTypeTemp && inputdeps[i]->dealias() != inputdeps[i]) continue; // Skip aliased temporaries if (deps++) oso (","); oso ("%s", inputdeps[i]->mangled().c_str()); } oso ("}"); } } #endif oso ("\n"); }
bool OSLCompilerImpl::compile (const std::string &filename, const std::vector<std::string> &options) { if (! boost::filesystem::exists (filename)) { error (ustring(), 0, "Input file \"%s\" not found", filename.c_str()); return false; } std::string stdinclude; #ifdef USE_BOOST_WAVE std::vector<std::string> defines; std::vector<std::string> undefines; std::vector<std::string> includepaths; #else std::string cppoptions; #endif // Determine where the installed shader include directory is, and // look for ../shaders/stdosl.h and force it to include. std::string program = Sysutil::this_program_path (); if (program.size()) { boost::filesystem::path path (program); // our program #if BOOST_VERSION >= 103600 path = path.parent_path (); // now the bin dir of our program path = path.parent_path (); // now the parent dir #else path = path.branch_path (); // now the bin dir of our program path = path.branch_path (); // now the parent dir #endif path = path / "shaders"; bool found = false; if (boost::filesystem::exists (path)) { path = path / "stdosl.h"; if (boost::filesystem::exists (path)) { stdinclude = path.string(); found = true; } } if (! found) warning (ustring(filename), 0, "Unable to find \"%s\"", path.string().c_str()); } m_output_filename.clear (); bool preprocess_only = false; for (size_t i = 0; i < options.size(); ++i) { if (options[i] == "-v") { // verbose mode m_verbose = true; } else if (options[i] == "-q") { // quiet mode m_quiet = true; } else if (options[i] == "-d") { // debug mode m_debug = true; } else if (options[i] == "-E") { preprocess_only = true; } else if (options[i] == "-o" && i < options.size()-1) { ++i; m_output_filename = options[i]; } else if (options[i] == "-O0") { m_optimizelevel = 0; } else if (options[i] == "-O" || options[i] == "-O1") { m_optimizelevel = 1; } else if (options[i] == "-O2") { m_optimizelevel = 2; #ifdef USE_BOOST_WAVE } else if (options[i].c_str()[0] == '-' && options[i].size() > 2) { // options meant for the preprocessor if(options[i].c_str()[1] == 'D') defines.push_back(options[i].substr(2)); else if(options[i].c_str()[1] == 'U') undefines.push_back(options[i].substr(2)); else if(options[i].c_str()[1] == 'I') includepaths.push_back(options[i].substr(2)); #else } else { // something meant for the cpp command cppoptions += "\""; cppoptions += options[i]; cppoptions += "\" "; #endif } } std::string preprocess_result; #ifdef USE_BOOST_WAVE if (! preprocess(filename, stdinclude, defines, undefines, includepaths, preprocess_result)) { #else if (! preprocess(filename, stdinclude, cppoptions, preprocess_result)) { #endif return false; } else if (preprocess_only) { std::cout << preprocess_result; } else { std::istringstream in (preprocess_result); oslcompiler = this; // Create a lexer, parse the file, delete the lexer m_lexer = new oslFlexLexer (&in); oslparse (); bool parseerr = error_encountered(); delete m_lexer; if (! parseerr) { shader()->typecheck (); } // Print the parse tree if there were no errors if (m_debug) { symtab().print (); if (shader()) shader()->print (std::cout); } if (! error_encountered()) { shader()->codegen (); // add_useparam (); track_variable_dependencies (); track_variable_lifetimes (); check_for_illegal_writes (); // if (m_optimizelevel >= 1) // coalesce_temporaries (); } if (! error_encountered()) { if (m_output_filename.size() == 0) m_output_filename = default_output_filename (); write_oso_file (m_output_filename); } oslcompiler = NULL; } return ! error_encountered(); } struct GlobalTable { const char *name; TypeSpec type; }; static GlobalTable globals[] = { { "P", TypeDesc::TypePoint }, { "I", TypeDesc::TypeVector }, { "N", TypeDesc::TypeNormal }, { "Ng", TypeDesc::TypeNormal }, { "u", TypeDesc::TypeFloat }, { "v", TypeDesc::TypeFloat }, { "dPdu", TypeDesc::TypeVector }, { "dPdv", TypeDesc::TypeVector }, #if 0 // Light variables -- we don't seem to be on a route to support this // kind of light shader, so comment these out for now. { "L", TypeDesc::TypeVector }, { "Cl", TypeDesc::TypeColor }, { "Ns", TypeDesc::TypeNormal }, { "Pl", TypeDesc::TypePoint }, { "Nl", TypeDesc::TypeNormal }, #endif { "Ps", TypeDesc::TypePoint }, { "Ci", TypeSpec (TypeDesc::TypeColor, true) }, { "time", TypeDesc::TypeFloat }, { "dtime", TypeDesc::TypeFloat }, { "dPdtime", TypeDesc::TypeVector }, { NULL } }; void OSLCompilerImpl::initialize_globals () { for (int i = 0; globals[i].name; ++i) { Symbol *s = new Symbol (ustring(globals[i].name), globals[i].type, SymTypeGlobal); symtab().insert (s); } } std::string OSLCompilerImpl::default_output_filename () { if (m_shader && shader_decl()) return shader_decl()->shadername().string() + ".oso"; return std::string(); } void OSLCompilerImpl::write_oso_metadata (const ASTNode *metanode) const { ASSERT (metanode->nodetype() == ASTNode::variable_declaration_node); const ASTvariable_declaration *metavar = static_cast<const ASTvariable_declaration *>(metanode); Symbol *metasym = metavar->sym(); ASSERT (metasym); TypeSpec ts = metasym->typespec(); oso ("%%meta{%s,%s,", ts.string().c_str(), metasym->name().c_str()); const ASTNode *init = metavar->init().get(); ASSERT (init); if (ts.is_string() && init->nodetype() == ASTNode::literal_node) oso ("\"%s\"", ((const ASTliteral *)init)->strval()); else if (ts.is_int() && init->nodetype() == ASTNode::literal_node) oso ("%d", ((const ASTliteral *)init)->intval()); else if (ts.is_float() && init->nodetype() == ASTNode::literal_node) oso ("%.8g", ((const ASTliteral *)init)->floatval()); // FIXME -- what about type constructors? else { std::cout << "Error, don't know how to print metadata " << ts.string() << " with node type " << init->nodetypename() << "\n"; ASSERT (0); // FIXME } oso ("} "); }