void
ASTvariable_declaration::typecheck_initlist (ref init, TypeSpec type,
                                             const char *name)
{
    // Loop over a list of initializers (it's just 1 if not an array)...
    for (int i = 0;  init;  init = init->next(), ++i) {
        // Check for too many initializers for an array
        if (type.is_array() && i > type.arraylength()) {
            error ("Too many initializers for a '%s'", type_c_str(type));
            break;
        }
        // Special case: ok to assign a literal 0 to a closure to
        // initialize it.
        if (type.is_closure() && ! init->typespec().is_closure() &&
              init->typespec().is_int_or_float() &&
              init->nodetype() == literal_node &&
            ((ASTliteral *)init.get())->floatval() == 0.0f) {
            continue;  // it's ok
        }
        if (! type.is_array() && i > 0)
            error ("Can't assign array initializers to non-array %s %s",
                   type_c_str(type), name);
        if (! assignable(type.elementtype(), init->typespec()))
            error ("Can't assign '%s' to %s %s", type_c_str(init->typespec()),
                   type_c_str(type), name);
    }
}
Example #2
0
/// Return the symbol pointer to the individual field that this
/// structselect represents; also set structid to the ID of the
/// structure type, and fieldid to the field index within the struct.
Symbol *
ASTstructselect::find_fieldsym (int &structid, int &fieldid)
{
    if (! lvalue()->typespec().is_structure() &&
        ! lvalue()->typespec().is_structure_array()) {
        return NULL;
    }

    ustring structsymname;
    TypeSpec structtype;
    find_structsym (lvalue().get(), structsymname, structtype);

    structid = structtype.structure();
    StructSpec *structspec (structtype.structspec());
    fieldid = -1;
    for (int i = 0;  i < (int)structspec->numfields();  ++i) {
        if (structspec->field(i).name == m_field) {
            fieldid = i;
            break;
        }
    }

    if (fieldid < 0) {
        error ("struct type '%s' does not have a member '%s'",
               structspec->name().c_str(), m_field.c_str());
        return NULL;
    }

    const StructSpec::FieldSpec &fieldrec (structspec->field(fieldid));
    ustring fieldsymname = ustring::format ("%s.%s", structsymname.c_str(),
                                            fieldrec.name.c_str());
    Symbol *sym = m_compiler->symtab().find (fieldsymname);
    return sym;
}
TypeSpec
ASTunary_expression::typecheck (TypeSpec expected)
{
    // FIXME - closures
    typecheck_children (expected);
    TypeSpec t = expr()->typespec();
    if (t.is_structure()) {
        error ("Can't do '%s' to a %s.", opname(), type_c_str(t));
        return TypeSpec ();
    }
    switch (m_op) {
    case Sub :
    case Add :
        if (t.is_string()) {
            error ("Can't do '%s' to a %s.", opname(), type_c_str(t));
            return TypeSpec ();
        }
        m_typespec = t;
        break;
    case Not :
        m_typespec = TypeDesc::TypeInt;  // ! is always an int
        break;
    case Compl :
        if (! t.is_int()) {
            error ("Operator '~' can only be done to an int");
            return TypeSpec ();
        }
        m_typespec = t;
        break;
    default:
        error ("unknown unary operator");
    }
    return m_typespec;
}
TypeSpec
ASTternary_expression::typecheck (TypeSpec expected)
{
    // FIXME - closures
    TypeSpec c = typecheck_list (cond(), TypeDesc::TypeInt);
    TypeSpec t = typecheck_list (trueexpr(), expected);
    TypeSpec f = typecheck_list (falseexpr(), expected);

    if (c.is_closure())
        error ("Cannot use a closure as a condition");
    if (c.is_structure())
        error ("Cannot use a struct as a condition");
    if (c.is_array())
        error ("Cannot use an array as a condition");

    // No arrays
    if (t.is_array() || t.is_array()) {
        error ("Not allowed: '%s ? %s : %s'",
               type_c_str(c), type_c_str(t), type_c_str(f));
        return TypeSpec ();
    }

    // The true and false clauses need to be equivalent types, or one
    // needs to be assignable to the other (so one can be upcast).
    if (assignable (t, f) || assignable (f, t))
        m_typespec = higherprecision (t.simpletype(), f.simpletype());
    else
        error ("Not allowed: '%s ? %s : %s'",
               type_c_str(c), type_c_str(t), type_c_str(f));

    return m_typespec;
}
TypeSpec
OSLCompilerImpl::type_from_code (const char *code, int *advance)
{
    TypeSpec t;
    int i = 0;
    switch (code[i]) {
    case 'i' : t = TypeDesc::TypeInt;          break;
    case 'f' : t = TypeDesc::TypeFloat;        break;
    case 'c' : t = TypeDesc::TypeColor;        break;
    case 'p' : t = TypeDesc::TypePoint;        break;
    case 'v' : t = TypeDesc::TypeVector;       break;
    case 'n' : t = TypeDesc::TypeNormal;       break;
    case 'm' : t = TypeDesc::TypeMatrix;       break;
    case 's' : t = TypeDesc::TypeString;       break;
    case 'x' : t = TypeDesc (TypeDesc::NONE);  break;
    case 'X' : t = TypeDesc (TypeDesc::PTR);   break;
    case 'L' : t = TypeDesc (TypeDesc::LONGLONG); break;
    case 'C' : // color closure
        t = TypeSpec (TypeDesc::TypeColor, true);
        break;
    case 'S' : // structure
        // Following the 'S' is the numeric structure ID
        t = TypeSpec ("struct", atoi (code+i+1));
        // Skip to the last digit
        while (isdigit(code[i+1]))
            ++i;
        break;
    case '?' : break; // anything will match, so keep 'UNKNOWN'
    case '*' : break; // anything will match, so keep 'UNKNOWN'
    case '.' : break; // anything will match, so keep 'UNKNOWN'
    default:
        std::cerr << "Don't know how to decode type code '" 
                  << code << "' " << (int)code[0] << "\n";
        ASSERT (0);   // FIXME
        if (advance)
            *advance = 1;
        return TypeSpec();
    }
    ++i;

    if (code[i] == '[') {
        ++i;
        t.make_array (-1);   // signal arrayness, unknown length
        if (isdigit(code[i]) || code[i] == ']') {
            if (isdigit(code[i]))
                t.make_array (atoi (code+i));
            while (isdigit(code[i]))
                ++i;
            if (code[i] == ']')
                ++i;
        }
    }

    if (advance)
        *advance = i;
    return t;
}
llvm::Type *
BackendLLVM::llvm_type_groupdata ()
{
    // If already computed, return it
    if (m_llvm_type_groupdata)
        return m_llvm_type_groupdata;

    std::vector<llvm::Type*> fields;

    // First, add the array that tells if each layer has run.  But only make
    // slots for the layers that may be called/used.
    int sz = (m_num_used_layers + 3) & (~3);  // Round up to 32 bit boundary
    fields.push_back (ll.type_array (ll.type_bool(), sz));
    size_t offset = sz * sizeof(bool);

    // For each layer in the group, add entries for all params that are
    // connected or interpolated, and output params.  Also mark those
    // symbols with their offset within the group struct.
    if (llvm_debug() >= 2)
        std::cout << "Group param struct:\n";
    m_param_order_map.clear ();
    int order = 1;
    for (int layer = 0;  layer < group().nlayers();  ++layer) {
        ShaderInstance *inst = group()[layer];
        if (inst->unused())
            continue;
        FOREACH_PARAM (Symbol &sym, inst) {
            TypeSpec ts = sym.typespec();
            if (ts.is_structure())  // skip the struct symbol itself
                continue;
            int arraylen = std::max (1, sym.typespec().arraylength());
            int deriv_mult = sym.has_derivs() ? 3 : 1;
            int n = arraylen * deriv_mult;
            ts.make_array (n);
            fields.push_back (llvm_type (ts));

            // Alignment
            size_t align = sym.typespec().is_closure_based() ? sizeof(void*) :
                    sym.typespec().simpletype().basesize();
            if (offset & (align-1))
                offset += align - (offset & (align-1));
            if (llvm_debug() >= 2)
                std::cout << "  " << inst->layername() 
                          << " (" << inst->id() << ") " << sym.mangled()
                          << " " << ts.c_str() << ", field " << order 
                          << ", offset " << offset << std::endl;
            sym.dataoffset ((int)offset);
            offset += int(sym.size()) * deriv_mult;

            m_param_order_map[&sym] = order;
            ++order;
        }
    }
TypeSpec
ASTtypecast_expression::typecheck (TypeSpec expected)
{
    // FIXME - closures
    typecheck_children (m_typespec);
    TypeSpec t = expr()->typespec();
    if (! assignable (m_typespec, t) &&
        ! (m_typespec.is_int() && t.is_float()) && // (int)float is ok
        ! (m_typespec.is_triple() && t.is_triple()))
        error ("Cannot cast '%s' to '%s'", type_c_str(t),
               type_c_str(m_typespec));
    return m_typespec;
}
void
OSOReaderToMaster::symbol (SymType symtype, TypeSpec typespec, const char *name_)
{
    ustring name(name_);
    Symbol sym (name, typespec, symtype);
    TypeDesc t = typespec.simpletype();
    int nvals = t.aggregate * (t.is_unsized_array() ? 1 : t.numelements());
    if (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam) {
        // Skip structs for now, they're just placeholders
        if (typespec.is_structure()) {
        }
        else if (typespec.simpletype().basetype == TypeDesc::FLOAT) {
            sym.dataoffset ((int) m_master->m_fdefaults.size());
            expand (m_master->m_fdefaults, nvals);
        } else if (typespec.simpletype().basetype == TypeDesc::INT) {
            sym.dataoffset ((int) m_master->m_idefaults.size());
            expand (m_master->m_idefaults, nvals);
        } else if (typespec.simpletype().basetype == TypeDesc::STRING) {
            sym.dataoffset ((int) m_master->m_sdefaults.size());
            expand (m_master->m_sdefaults, nvals);
        } else if (typespec.is_closure_based()) {
            // Closures are pointers, so we allocate a string default taking
            // adventage of their default being NULL as well.
            sym.dataoffset ((int) m_master->m_sdefaults.size());
            expand (m_master->m_sdefaults, nvals);
        } else {
            ASSERT (0 && "unexpected type");
        }
    }
    if (sym.symtype() == SymTypeConst) {
        if (typespec.simpletype().basetype == TypeDesc::FLOAT) {
            sym.dataoffset ((int) m_master->m_fconsts.size());
            expand (m_master->m_fconsts, nvals);
        } else if (typespec.simpletype().basetype == TypeDesc::INT) {
            sym.dataoffset ((int) m_master->m_iconsts.size());
            expand (m_master->m_iconsts, nvals);
        } else if (typespec.simpletype().basetype == TypeDesc::STRING) {
            sym.dataoffset ((int) m_master->m_sconsts.size());
            expand (m_master->m_sconsts, nvals);
        } else {
            ASSERT (0 && "unexpected type");
        }
    }
#if 0
    // FIXME -- global_heap_offset is quite broken.  But also not necessary.
    // We made need to fix this later.
    if (sym.symtype() == SymTypeGlobal) {
        sym.dataoffset (m_shadingsys.global_heap_offset (sym.name()));
    }
#endif
    sym.lockgeom (m_shadingsys.lockgeom_default());
    m_master->m_symbols.push_back (sym);
    m_symmap[name] = int(m_master->m_symbols.size()) - 1;
    // Start the index at which we add specified defaults
    m_sym_default_index = 0;
}
Example #9
0
ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
                                                  const TypeSpec &type,
                                                  ustring name, ASTNode *init,
                                                  bool isparam, bool ismeta,
                                                  bool isoutput, bool initlist)
    : ASTNode (variable_declaration_node, comp, 0, init, NULL /* meta */),
      m_name(name), m_sym(NULL),
      m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
      m_initlist(initlist)
{
    m_typespec = type;
    Symbol *f = comp->symtab().clash (name);
    if (f  &&  ! m_ismetadata) {
        std::string e = Strutil::format ("\"%s\" already declared in this scope", name.c_str());
        if (f->node()) {
            std::string filename = OIIO::Filesystem::filename(f->node()->sourcefile().string());
            e += Strutil::format ("\n\t\tprevious declaration was at %s:%d",
                                  filename, f->node()->sourceline());
        }
        if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
            // special case: only a warning for param to mask global function
            warning ("%s", e.c_str());
        } else {
            error ("%s", e.c_str());
        }
    }
    if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
        error ("\"%s\" : sorry, can't start with three underscores",
               name.c_str());
    }
    SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
                              : SymTypeLocal;
    // Sneaky debugging aid: a local that starts with "__debug_tmp__"
    // gets declared as a temp. Don't do this on purpose!!!
    if (symtype == SymTypeLocal && Strutil::starts_with (name, "__debug_tmp__"))
        symtype = SymTypeTemp;
    m_sym = new Symbol (name, type, symtype, this);
    if (! m_ismetadata)
        oslcompiler->symtab().insert (m_sym);

    // A struct really makes several subvariables
    if (type.is_structure() || type.is_structure_array()) {
        ASSERT (! m_ismetadata);
        // Add the fields as individual declarations
        m_compiler->add_struct_fields (type.structspec(), m_sym->name(), symtype,
                                       type.is_unsized_array() ? -1 : type.arraylength(),
                                       this, init);
    }
}
Example #10
0
void scContUnit::PasteText( const scContUnit*	srcPara,
							long&				offset )
{
	try {
		if ( offset == 0 ) {
			TypeSpec ts = srcPara->GetDefaultSpec();
			if ( ts.ptr() )
				SetDefaultSpec( ts );
		}
			
			// paste the specs in
		fSpecRun.InsertRun( offset, srcPara->GetContentSize(), srcPara->GetSpecRun() );

			// paste the text in
		fCharArray.Paste( ((scContUnit*)srcPara)->GetCharArray(), offset );
		Mark( scREBREAK );

#ifdef _RUBI_SUPPORT
			// paste the rubis in
		if ( fRubiArray || srcPara->GetRubiArray() ) {
	
			if ( fRubiArray && !srcPara->GetRubiArray() )
				fRubiArray->BumpRubiData( offset, srcPara->GetContentSize() );
			else if ( !fRubiArray && srcPara->GetRubiArray() ) {
				AllocRubiArray( *srcPara->GetRubiArray() );
				fRubiArray->BumpRubiData( 0, offset );
			}
			else
				fRubiArray->Paste( *srcPara->GetRubiArray(), offset, srcPara->GetContentSize() );
		}
#endif

		scTextline* txl = FindLine( offset );
		if ( txl )
			txl->Mark( scREPAINT ); /* force repaint */

		long startOffset = offset;
		offset += srcPara->GetContentSize();

		fSpecRun.SetContentSize( GetContentSize() );
		
		fCharArray.RepairText( fSpecRun, startOffset, offset );
	} 
	catch( ... ) {
		SCDebugBreak(); // remove stuff from the paragraph
		throw;
	} 
}
Example #11
0
/// structnode is an AST node representing a struct.  It could be a
/// struct variable, or a field of a struct (which is itself a struct),
/// or an array element of a struct.  Whatever, here we figure out some
/// vital information about it: the name of the symbol representing the
/// struct, and its type.
void
ASTstructselect::find_structsym (ASTNode *structnode, ustring &structname,
                                 TypeSpec &structtype)
{
    // This node selects a field from a struct. The purpose of this
    // method is to "flatten" the possibly-nested (struct in struct, and
    // or array of structs) down to a symbol that represents the
    // particular field.  In the process, we set structname and its
    // type structtype.
    ASSERT (structnode->typespec().is_structure() ||
            structnode->typespec().is_structure_array());
    if (structnode->nodetype() == variable_ref_node) {
        // The structnode is a top-level struct variable
        ASTvariable_ref *var = (ASTvariable_ref *) structnode;
        structname = var->name();
        structtype = var->typespec();
    }
    else if (structnode->nodetype() == structselect_node) {
        // The structnode is itself a field of another struct.
        ASTstructselect *thestruct = (ASTstructselect *) structnode;
        int structid, fieldid;
        Symbol *sym = thestruct->find_fieldsym (structid, fieldid);
        structname = sym->name();
        structtype = sym->typespec();
    }
    else if (structnode->nodetype() == index_node) {
        // The structnode is an element of an array of structs:
        ASTindex *arrayref = (ASTindex *) structnode;
        find_structsym (arrayref->lvalue().get(), structname, structtype);
        structtype.make_array (0);  // clear its arrayness
    }
    else {
        ASSERT (0 && "Malformed ASTstructselect");
    }
}
Example #12
0
void scContUnit::ChInfo( long			offset,
						 UCS2&			ch, 		/* character at offset */
						 ulong& 		flags,
						 MicroPoint&	escapement, /* escapement at offset */
						 MicroPoint&	wordspace,	/* ws escapement at offset */
						 TypeSpec&		ts, 		/* typespec at offset */
						 eUnitType& 	unitType )	/* relative or absolute */
{
	if ( offset == 0 ) {
		ch			= scParaStart;	
		flags		= 0;		
		escapement	= 0;
		ts			= fSpecRun.SpecAtOffset( offset );
		unitType	= eAbsUnit;
	}
	else if ( offset == GetContentSize() + 1 ) {
		ch			= scParaEnd;
		flags		= 0;
		escapement	= 0;
		ts			= fSpecRun.SpecAtOffset( GetContentSize() );
		unitType	= eAbsUnit;
	}
	else if ( offset > GetContentSize() ) {
		ch			= 0;
		flags		= 0;
		escapement	= 0;
		ts.clear();
		unitType	= eAbsUnit;
	}
	else
		fCharArray.CharInfo( fSpecRun, offset, ch, flags, escapement, ts, unitType );

	fCharArray.WordSpaceInfo( offset, wordspace );
}
Example #13
0
void scCachedStyle::SetParaStyle( const scContUnit* cu, TypeSpec& ts )
{
	if ( ts.ptr() == cachedParaStyle_.fSpec.ptr() )
		return;
	cachedPara_ = cu;
	cachedParaStyle_.Init( ts );
}
Example #14
0
void scTypeSpecList::Insert( TypeSpec& ts )
{	
	for ( int i = 0; i < NumItems(); i++ ) {
		if ( ts.ptr() == (*this)[i].ptr() )
			return;
	}
	Append( ts );
}
Example #15
0
void scContUnit::SetDefaultSpec( TypeSpec& ts )
{
	if ( ts.ptr() != defspec_.ptr() ) {
		defspec_ = ts;
		Mark( scREBREAK );
	}
	ForceRepaint( 0, LONG_MAX );
}
void
OSOReaderQuery::symbol (SymType symtype, TypeSpec typespec, const char *name)
{
    if (symtype == SymTypeParam || symtype == SymTypeOutputParam) {
        m_reading_param = true;
        OSLQuery::Parameter p;
        p.name = name;
        p.type = typespec.simpletype();   // FIXME -- struct & closure
        p.isoutput = (symtype == SymTypeOutputParam);
        p.varlenarray = (typespec.arraylength() < 0);
        p.isstruct = typespec.is_structure();
        p.isclosure = typespec.is_closure();
        m_query.m_params.push_back (p);
    } else {
        m_reading_param = false;
    }
}
Example #17
0
TypeSpec
ASTconditional_statement::typecheck (TypeSpec expected)
{
    typecheck_list (cond ());
    oslcompiler->push_nesting (false);
    typecheck_list (truestmt ());
    typecheck_list (falsestmt ());
    oslcompiler->pop_nesting (false);

    TypeSpec c = cond()->typespec();
    if (c.is_closure())
        error ("Cannot use a closure as an 'if' condition");
    if (c.is_structure())
        error ("Cannot use a struct as an 'if' condition");
    if (c.is_array())
        error ("Cannot use an array as an 'if' condition");
    return m_typespec = TypeDesc (TypeDesc::NONE);
}
Example #18
0
TypeSpec
ASTloop_statement::typecheck (TypeSpec expected)
{
    typecheck_list (init ());
    oslcompiler->push_nesting (true);
    typecheck_list (cond ());
    typecheck_list (iter ());
    typecheck_list (stmt ());
    oslcompiler->pop_nesting (true);

    TypeSpec c = cond()->typespec();
    if (c.is_closure())
        error ("Cannot use a closure as an '%s' condition", opname());
    if (c.is_structure())
        error ("Cannot use a struct as an '%s' condition", opname());
    if (c.is_array())
        error ("Cannot use an array as an '%s' condition", opname());
    return m_typespec = TypeDesc (TypeDesc::NONE);
}
void
BackendLLVM::initialize_llvm_group ()
{
    ll.setup_optimization_passes (shadingsys().llvm_optimize());

    // Clear the shaderglobals and groupdata types -- they will be
    // created on demand.
    m_llvm_type_sg = NULL;
    m_llvm_type_groupdata = NULL;
    m_llvm_type_closure_component = NULL;
    m_llvm_type_closure_component_attr = NULL;

    for (int i = 0;  llvm_helper_function_table[i];  i += 2) {
        const char *funcname = llvm_helper_function_table[i];
        bool varargs = false;
        const char *types = llvm_helper_function_table[i+1];
        int advance;
        TypeSpec rettype = OSLCompilerImpl::type_from_code (types, &advance);
        types += advance;
        std::vector<llvm::Type*> params;
        while (*types) {
            TypeSpec t = OSLCompilerImpl::type_from_code (types, &advance);
            if (t.simpletype().basetype == TypeDesc::UNKNOWN) {
                if (*types == '*')
                    varargs = true;
                else
                    ASSERT (0);
            } else {
                params.push_back (llvm_pass_type (t));
            }
            types += advance;
        }
        ll.make_function (funcname, false, llvm_type(rettype), params, varargs);
    }

    // Needed for closure setup
    std::vector<llvm::Type*> params(3);
    params[0] = (llvm::Type *) ll.type_char_ptr();
    params[1] = ll.type_int();
    params[2] = (llvm::Type *) ll.type_char_ptr();
    m_llvm_type_prepare_closure_func = ll.type_function_ptr (ll.type_void(), params);
    m_llvm_type_setup_closure_func = m_llvm_type_prepare_closure_func;
}
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());
    }
}
Example #21
0
void scContUnit::Insert( const CharRecord&	ch,
						 TypeSpec&			spec,
						 long				offset )
{
	CharRecordP chRec = (CharRecordP)&ch;
	fCharArray.Insert( chRec, offset, 1 );
	fSpecRun.BumpOffset( offset, fCharArray.GetNumItems() );

	if ( spec.ptr() )
		fSpecRun.ApplySpec( spec, offset, offset + 1 );

	Mark( scREBREAK );
}
Example #22
0
/* return true if a spec exists on a line */
BOOL scTextline::ContainTS( TypeSpec ts )
{
	scSpecRun&		run = fPara->GetSpecRun();

	int i = run.indexAtOffset( fStartOffset );

	do {
		if ( run[i].spec().ptr() == ts.ptr() )
			return true;			
	} while ( run[++i].offset() < fEndOffset );

	return false;
}
Example #23
0
	TiXmlElement* GetSParamElement(Parameter *param)
	{
		TiXmlElement *gParamEl = new TiXmlElement("SPar");

		TypeSpec *tSpec = dynamic_cast<TypeSpec*>(param->type);
		TypeRef *tRef = dynamic_cast<TypeRef*>(param->type);
		if (tRef)
			tSpec = static_cast<TypeSpec*>(tRef->type);

		gParamEl->SetAttribute("Qual", tSpec->GetParentModule()->Name.c_str());

		//if (tSpec->IsTagged)
		//	gParamEl->SetAttribute("Name", (tSpec->base ? tSpec->base->Name.c_str() : "NIL"));
		//else
		//	gParamEl->SetAttribute("Name", (tSpec->base ? tSpec->Name.c_str() : "NIL"));
		gParamEl->SetAttribute("Name", tSpec->GetCPPTypeName(false).c_str());

		if (tSpec->IsTagged)
			gParamEl->SetAttribute("Tag", tSpec->Name.c_str());

		return gParamEl;
	}
Example #24
0
void scCachedStyle::StyleInvalidateCache( TypeSpec& ts )
{
	int i;

	TypeSpec nullSpec;

	for ( i = 0; i < fEntries; i++ ) {
		if ( ts.ptr() == fCachedStyles[i].GetSpec().ptr() )
			fCachedStyles[i].Init( nullSpec );
		else
			fCachedStyles[i].Init( nullSpec );			
	}
	cachedParaStyle_.Init( nullSpec );
}
Example #25
0
bool
ASTNode::check_arglist (const char *funcname, ASTNode::ref arg,
                        const char *formals, bool coerce)
{
    // std::cerr << "ca " << funcname << " formals='" << formals << "\n";
    for ( ;  arg;  arg = arg->next()) {
        if (! *formals)   // More formal args, but no more actual args
            return false;
        if (*formals == '*')  // Will match anything left
            return true;
        if (*formals == '.') {  // Special case for token/value pairs
            // FIXME -- require that the tokens be string literals
            if (arg->typespec().is_string() && arg->next() != NULL) {
                arg = arg->next();
                continue;
            }
            return false;
        }
        if (*formals == '?') {
            if (formals[1] == '[' && formals[2] == ']') {
                // Any array
                formals += 3;
                if (arg->typespec().is_array())
                    continue;  // match
                else return false;  // wanted an array, didn't get one
            }
            if (arg->typespec().is_array())
                return false;   // wanted any scalar, got an array
            formals += 1;
            continue;  // match anything
        }

        TypeSpec argtype = arg->typespec();
        int advance;
        TypeSpec formaltype = m_compiler->type_from_code (formals, &advance);
        formals += advance;
        // std::cerr << "\targ is " << argtype.string() 
        //           << ", formal is " << formaltype.string() << "\n";
        if (argtype == formaltype)
            continue;   // ok, move on to next arg
        if (coerce && assignable (formaltype, argtype))
            continue;
        // Allow a fixed-length array match to a formal array with
        // unspecified length, if the element types are the same.
        if (formaltype.arraylength() < 0 && argtype.arraylength() &&
              formaltype.elementtype() == argtype.elementtype())
            continue;

        // anything that gets this far we don't consider a match
        return false;
    }
    if (*formals && *formals != '*' && *formals != '.') 
        return false;  // Non-*, non-... formals expected, no more actuals

    return true;  // Is this safe?
}
Example #26
0
File: type.cpp Project: StetHD/hhvm
Type Type::specialize(TypeSpec spec) const {
  assertx(!spec.arrSpec() || supports(SpecKind::Array));
  assertx(!spec.clsSpec() || supports(SpecKind::Class));

  // If we don't have exactly one kind of specialization, or if our bits
  // support both kinds, don't specialize.
  if ((bool)spec.arrSpec() == (bool)spec.clsSpec() ||
      (supports(SpecKind::Array) && supports(SpecKind::Class))) {
    return *this;
  }

  if (spec.arrSpec() != ArraySpec::Bottom) {
    return Type{*this, spec.arrSpec()};
  }

  assertx(spec.clsSpec() != ClassSpec::Bottom);
  return Type{*this, spec.clsSpec()};
}
Example #27
0
void scCachedStyle::Init( TypeSpec& ts )
{
	if ( ts.ptr() ) {
		TSGetStyle( ts, *this );
		
		SetSpec( ts );
		fTimeStamp = ++scCachedStyle::fCacheTime;

		fPtConv 	= (REAL)GetGlyphHeight() / scBaseRLUsystem;
		fSetConv	= (REAL)GetGlyphWidth()  / scBaseRLUsystem;
		 
		InitWidths();
		ComputeExtentsnCursor();
	}
	else {
		TypeSpec nullSpec;
		SetSpec( nullSpec );
		fPtConv 	= 0;
		fSetConv	= 0;
		InitWidths();
		fTimeStamp = 0;
	}
		
}
Example #28
0
std::string
OSLCompilerImpl::code_from_type (TypeSpec type) const
{
    std::string out;
    TypeDesc elem = type.elementtype().simpletype();
    if (type.is_structure()) {
        out = Strutil::format ("S%d", type.structure());
    } else if (type.is_closure()) {
        out = 'C';
    } else {
        if (elem == TypeDesc::TypeInt)
            out = 'i';
        else if (elem == TypeDesc::TypeFloat)
            out = 'f';
        else if (elem == TypeDesc::TypeColor)
            out = 'c';
        else if (elem == TypeDesc::TypePoint)
            out = 'p';
        else if (elem == TypeDesc::TypeVector)
            out = 'v';
        else if (elem == TypeDesc::TypeNormal)
            out = 'n';
        else if (elem == TypeDesc::TypeMatrix)
            out = 'm';
        else if (elem == TypeDesc::TypeString)
            out = 's';
        else if (elem == TypeDesc::NONE)
            out = 'x';
        else
            ASSERT (0);
    }

    if (type.is_array()) {
        int len = type.arraylength ();
        if (len > 0)
            out += Strutil::format ("[%d]", len);
        else
            out += "[]";
    }

    return out;
}
Example #29
0
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 ("} ");
}
void
BackendLLVM::llvm_assign_initial_value (const Symbol& sym)
{
    // Don't write over connections!  Connection values are written into
    // our layer when the earlier layer is run, as part of its code.  So
    // we just don't need to initialize it here at all.
    if (sym.valuesource() == Symbol::ConnectedVal &&
          !sym.typespec().is_closure_based())
        return;
    if (sym.typespec().is_closure_based() && sym.symtype() == SymTypeGlobal)
        return;

    int arraylen = std::max (1, sym.typespec().arraylength());

    // Closures need to get their storage before anything can be
    // assigned to them.  Unless they are params, in which case we took
    // care of it in the group entry point.
    if (sym.typespec().is_closure_based() &&
        sym.symtype() != SymTypeParam && sym.symtype() != SymTypeOutputParam) {
        llvm_assign_zero (sym);
        return;
    }

    if ((sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp)
          && shadingsys().debug_uninit()) {
        // Handle the "debug uninitialized values" case
        bool isarray = sym.typespec().is_array();
        int alen = isarray ? sym.typespec().arraylength() : 1;
        llvm::Value *u = NULL;
        if (sym.typespec().is_closure_based()) {
            // skip closures
        }
        else if (sym.typespec().is_floatbased())
            u = ll.constant (std::numeric_limits<float>::quiet_NaN());
        else if (sym.typespec().is_int_based())
            u = ll.constant (std::numeric_limits<int>::min());
        else if (sym.typespec().is_string_based())
            u = ll.constant (Strings::uninitialized_string);
        if (u) {
            for (int a = 0;  a < alen;  ++a) {
                llvm::Value *aval = isarray ? ll.constant(a) : NULL;
                for (int c = 0;  c < (int)sym.typespec().aggregate(); ++c)
                    llvm_store_value (u, sym, 0, aval, c);
            }
        }
        return;
    }

    if ((sym.symtype() == SymTypeLocal || sym.symtype() == SymTypeTemp) &&
        sym.typespec().is_string_based()) {
        // Strings are pointers.  Can't take any chance on leaving
        // local/tmp syms uninitialized.
        llvm_assign_zero (sym);
        return;  // we're done, the parts below are just for params
    }
    ASSERT_MSG (sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam,
                "symtype was %d, data type was %s", (int)sym.symtype(), sym.typespec().c_str());

    if (sym.has_init_ops() && sym.valuesource() == Symbol::DefaultVal) {
        // Handle init ops.
        build_llvm_code (sym.initbegin(), sym.initend());
    } else if (! sym.lockgeom() && ! sym.typespec().is_closure()) {
        // geometrically-varying param; memcpy its default value
        TypeDesc t = sym.typespec().simpletype();
        ll.op_memcpy (llvm_void_ptr (sym), ll.constant_ptr (sym.data()),
                      t.size(), t.basesize() /*align*/);
        if (sym.has_derivs())
            llvm_zero_derivs (sym);
    } else {
        // Use default value
        int num_components = sym.typespec().simpletype().aggregate;
        TypeSpec elemtype = sym.typespec().elementtype();
        for (int a = 0, c = 0; a < arraylen;  ++a) {
            llvm::Value *arrind = sym.typespec().is_array() ? ll.constant(a) : NULL;
            if (sym.typespec().is_closure_based())
                continue;
            for (int i = 0; i < num_components; ++i, ++c) {
                // Fill in the constant val
                llvm::Value* init_val = 0;
                if (elemtype.is_floatbased())
                    init_val = ll.constant (((float*)sym.data())[c]);
                else if (elemtype.is_string())
                    init_val = ll.constant (((ustring*)sym.data())[c]);
                else if (elemtype.is_int())
                    init_val = ll.constant (((int*)sym.data())[c]);
                ASSERT (init_val);
                llvm_store_value (init_val, sym, 0, arrind, i);
            }
        }
        if (sym.has_derivs())
            llvm_zero_derivs (sym);
    }

    // Handle interpolated params.
    // FIXME -- really, we shouldn't assign defaults or run init ops if
    // the values are interpolated.  The perf hit is probably small, since
    // there are so few interpolated params, but we should come back and
    // fix this later.
    if ((sym.symtype() == SymTypeParam || sym.symtype() == SymTypeOutputParam)
        && ! sym.lockgeom()) {
        std::vector<llvm::Value*> args;
        args.push_back (sg_void_ptr());
        args.push_back (ll.constant (sym.name()));
        args.push_back (ll.constant (sym.typespec().simpletype()));
        args.push_back (ll.constant ((int) sym.has_derivs()));
        args.push_back (llvm_void_ptr (sym));
        ll.call_function ("osl_bind_interpolated_param",
                          &args[0], args.size());                            
    }
}