コード例 #1
0
ファイル: opcodes.cpp プロジェクト: ronaldnsabiyera/eliot
void Opcode::Enter(Context *context)
// ----------------------------------------------------------------------------
//   Enter all the opcodes declared using the macros
// ----------------------------------------------------------------------------
{
    for (Opcodes::iterator o = opcodes->begin(); o != opcodes->end(); o++)
    {
        Opcode *opcode = *o;
        opcode->Register(context);
    }
}
コード例 #2
0
ファイル: vmmethod.cpp プロジェクト: marnen/rubinius
  /*
   * Turns a VMMethod into a C++ vector of Opcodes.
   */
  std::vector<Opcode*> VMMethod::create_opcodes() {
    std::vector<Opcode*> ops;
    std::map<int, size_t> stream2opcode;

    VMMethod::Iterator iter(this);

    /* Fill +ops+ with all our Opcode objects, maintain
     * the map from stream position to instruction. */
    for(size_t ipos = 0; !iter.end(); ipos++, iter.inc()) {
      stream2opcode[iter.position] = ipos;
      Opcode* lop = new Opcode(iter);
      ops.push_back(lop);
    }

    /* Iterate through the ops, fixing goto locations to point
     * to opcodes and set start_block on any opcode that is
     * the beginning of a block */
    bool next_new = false;

    for(std::vector<Opcode*>::iterator i = ops.begin(); i != ops.end(); i++) {
      Opcode* op = *i;
      if(next_new) {
        op->start_block = true;
        next_new = false;
      }

      /* We patch and mark where we branch to. */
      if(op->is_goto()) {
        op->arg1 = stream2opcode[op->arg1];
        ops.at(op->arg1)->start_block = true;
      }

      /* This terminates the block. */
      if(op->is_terminator()) {
        /* this ends a block. */
        next_new = true;
      }
    }

    // TODO take the exception table into account here

    /* Go through again and assign each opcode a block
     * number. */
    size_t block = 0;
    for(std::vector<Opcode*>::iterator i = ops.begin(); i != ops.end(); i++) {
      Opcode* op = *i;

      if(op->start_block) block++;
      op->block = block;
    }

    return ops;
  }
コード例 #3
0
ファイル: opcodes.cpp プロジェクト: ronaldnsabiyera/eliot
Opcode * Opcode::Find(Tree *self, text name)
// ----------------------------------------------------------------------------
//   Find an opcode that matches the name if there is  one
// ----------------------------------------------------------------------------
{
    for (Opcodes::iterator o = opcodes->begin(); o != opcodes->end(); o++)
    {
        Opcode *opcode = *o;
        if (opcode->OpID() == name)
            return opcode;
    }
    Ooops("Invalid opcode name in $1", self);
    return NULL;
}
コード例 #4
0
/// Verify that the given symbol (written by the given op) is legal to
/// be written.
void
OSLCompilerImpl::check_write_legality (const Opcode &op, int opnum,
                                       const Symbol *sym)
{
    // We can never write to constant symbols
    if (sym->symtype() == SymTypeConst) {
        error (op.sourcefile(), op.sourceline(),
               "Attempted to write to a constant value");
    }

    // Params can only write if it's part of their initialization
    if (sym->symtype() == SymTypeParam && 
        (opnum < sym->initbegin() || opnum >= sym->initend())) {
        error (op.sourcefile(), op.sourceline(),
               "Cannot write to input parameter '%s' (op %d)",
               sym->name().c_str(), opnum);
    }

    // FIXME -- check for writing to globals.  But it's tricky, depends on
    // what kind of shader we are.
}
コード例 #5
0
void
RuntimeOptimizer::llvm_generate_debugnan (const Opcode &op)
{
    for (int i = 0;  i < op.nargs();  ++i) {
        Symbol &sym (*opargsym (op, i));
        if (! op.argwrite(i))
            continue;
        TypeDesc t = sym.typespec().simpletype();
        if (t.basetype != TypeDesc::FLOAT)
            continue;  // just check float-based types
        int ncomps = t.numelements() * t.aggregate;
        llvm::Value *args[] = { llvm_constant(ncomps),
                                llvm_void_ptr(sym),
                                llvm_constant((int)sym.has_derivs()),
                                sg_void_ptr(), 
                                llvm_constant(op.sourcefile()),
                                llvm_constant(op.sourceline()),
                                llvm_constant(sym.name()) };
        llvm_call_function ("osl_naninf_check", args, 7);
    }
}
コード例 #6
0
void
BackendLLVM::llvm_generate_debug_uninit (const Opcode &op)
{
    for (int i = 0;  i < op.nargs();  ++i) {
        Symbol &sym (*opargsym (op, i));
        if (! op.argread(i))
            continue;
        if (sym.typespec().is_closure_based())
            continue;
        TypeDesc t = sym.typespec().simpletype();
        if (t.basetype != TypeDesc::FLOAT && t.basetype != TypeDesc::INT &&
            t.basetype != TypeDesc::STRING)
            continue;  // just check float, int, string based types
        llvm::Value *ncheck = ll.constant (int(t.numelements() * t.aggregate));
        llvm::Value *offset = ll.constant(0);
        // Some special cases...
        if (op.opname() == Strings::op_for && i == 0) {
            // The first argument of 'for' is the condition temp, but
            // note that it may not have had its initializer run yet, so
            // don't generate uninit test code for it.
            continue;
        }
        if (op.opname() == op_aref && i == 1) {
            // Special case -- array assignment -- only check one element
            llvm::Value *ind = llvm_load_value (*opargsym (op, 2));
            llvm::Value *agg = ll.constant(t.aggregate);
            offset = t.aggregate == 1 ? ind : ll.op_mul (ind, agg);
            ncheck = agg;
        } else if (op.opname() == op_compref && i == 1) {
            // Special case -- component assignment -- only check one channel
            llvm::Value *ind = llvm_load_value (*opargsym (op, 2));
            offset = ind;
            ncheck = ll.constant(1);
        }

        llvm::Value *args[] = { ll.constant(t),
                                llvm_void_ptr(sym),
                                sg_void_ptr(), 
                                ll.constant(op.sourcefile()),
                                ll.constant(op.sourceline()),
                                ll.constant(sym.name()),
                                offset,
                                ncheck
                              };
        ll.call_function ("osl_uninit_check", args, 8);
    }
}
コード例 #7
0
void
BackendLLVM::llvm_generate_debugnan (const Opcode &op)
{
    for (int i = 0;  i < op.nargs();  ++i) {
        Symbol &sym (*opargsym (op, i));
        if (! op.argwrite(i))
            continue;
        TypeDesc t = sym.typespec().simpletype();
        if (t.basetype != TypeDesc::FLOAT)
            continue;  // just check float-based types
        llvm::Value *ncomps = ll.constant (int(t.numelements() * t.aggregate));
        llvm::Value *offset = ll.constant(0);
        llvm::Value *ncheck = ncomps;
        if (op.opname() == op_aassign) {
            // Special case -- array assignment -- only check one element
            ASSERT (i == 0 && "only arg 0 is written for aassign");
            llvm::Value *ind = llvm_load_value (*opargsym (op, 1));
            llvm::Value *agg = ll.constant(t.aggregate);
            offset = t.aggregate == 1 ? ind : ll.op_mul (ind, agg);
            ncheck = agg;
        } else if (op.opname() == op_compassign) {
            // Special case -- component assignment -- only check one channel
            ASSERT (i == 0 && "only arg 0 is written for compassign");
            llvm::Value *ind = llvm_load_value (*opargsym (op, 1));
            offset = ind;
            ncheck = ll.constant(1);
        }

        llvm::Value *args[] = { ncomps,
                                llvm_void_ptr(sym),
                                ll.constant((int)sym.has_derivs()),
                                sg_void_ptr(), 
                                ll.constant(op.sourcefile()),
                                ll.constant(op.sourceline()),
                                ll.constant(sym.name()),
                                offset,
                                ncheck,
                                ll.constant(op.opname())
                              };
        ll.call_function ("osl_naninf_check", args, 10);
    }
}
コード例 #8
0
IntermediateData *ScriptParser::generateOCode(FunctionData *fdata)
{
    //Z_message("yes");
    bool failure = false;
    vector<ASTFuncDecl *> funcs = fdata->functions;
    vector<ASTVarDecl *> globals = fdata->globalVars;
    vector<ASTArrayDecl *> globalas = fdata->globalArrays;
    
    //we have no need of newglobals at this point anymore
    for(vector<ASTVarDecl *>::iterator it = fdata->newGlobalVars.begin(); it != fdata->newGlobalVars.end(); it++)
        globals.push_back(*it);
        
    for(vector<ASTArrayDecl *>::iterator it = fdata->newGlobalArrays.begin(); it != fdata->newGlobalArrays.end(); it++)
        globalas.push_back(*it);
        
    map<string, int> runsymbols = fdata->scriptRunSymbols;
    SymbolTable *symbols = fdata->symbols;
    map<string, int> numparams = fdata->numParams;
    map<string, int> scripttypes = fdata->scriptTypes;
    map<string, int> thisptr = fdata->thisPtr;
    delete fdata;
    LinkTable lt;
    
    for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++)
    {
        int vid2 = symbols->getID(*it);
        lt.addGlobalVar(vid2);
    }
    
    for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++)
    {
        int vid2 = symbols->getID(*it);
        lt.addGlobalVar(vid2);
    }
    
    //Z_message("yes");
    //and add the this pointers
    for(vector<int>::iterator it = symbols->getGlobalPointers().begin(); it != symbols->getGlobalPointers().end(); it++)
    {
        lt.addGlobalPointer(*it);
    }
    
    for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++)
    {
        int fid2 = symbols->getID(*it);
        lt.functionToLabel(fid2);
    }
    
    //Z_message("yes");
    
    //we now have labels for the functions and ids for the global variables.
    //we can now generate the code to intialize the globals
    IntermediateData *rval = new IntermediateData();
    
    //Link against the global symbols, and add their labels
    map<int, vector<Opcode *> > globalcode = GlobalSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = FFCSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ItemSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ItemclassSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = LinkSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = ScreenSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = GameSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = NPCSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = LinkWeaponSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    globalcode = EnemyWeaponSymbols::getInst().addSymbolsCode(lt);
    
    for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++)
    {
        rval->funcs[it->first] = it->second;
    }
    
    //Z_message("yes");
    
    for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++)
    {
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = NULL;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
        {
            failure = true;
        }
        
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++)
        {
            rval->globalsInit.push_back(*it2);
        }
        
        delete *it; //say so long to our lovely data structure the AST
    }
    
    //Z_message("yes");
    for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++)
    {
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = NULL;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
        {
            failure = true;
        }
        
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++)
        {
            rval->globalasInit.push_back(*it2);
        }
        
        delete *it; //say so long to our lovely data structure the AST
    }
    
    //Z_message("yes");
    
    //globals have been initialized, now we repeat for the functions
    for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++)
    {
        bool isarun = false;
        string scriptname;
        
        for(map<string,int>::iterator it2 = runsymbols.begin(); it2 != runsymbols.end(); it2++)
        {
            if(it2->second == symbols->getID(*it))
            {
                isarun=true;
                scriptname = it2->first;
                break;
            }
        }
        
        vector<Opcode *> funccode;
        //count the number of stack-allocated variables
        vector<int> stackvars;
        pair<vector<int> *, SymbolTable *> param = pair<vector<int> *, SymbolTable *>(&stackvars, symbols);
        CountStackSymbols temp;
        (*it)->execute(temp, &param);
        int offset = 0;
        StackFrame sf;
        
        //if this is a run, there is the this pointer
        if(isarun)
        {
            sf.addToFrame(thisptr[scriptname], offset);
            offset += 10000;
        }
        
        //the params are now the first elements of this list
        //so assign them depths in reverse order
        for(vector<int>::reverse_iterator it2 = stackvars.rbegin(); it2 != stackvars.rend(); it2++)
        {
            sf.addToFrame(*it2, offset);
            offset += 10000;
        }
        
        //start of the function
        Opcode *first = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0));
        first->setLabel(lt.functionToLabel(symbols->getID(*it)));
        funccode.push_back(first);
        //push on the 0s
        int numtoallocate = (unsigned int)stackvars.size()-(unsigned int)symbols->getFuncParams(symbols->getID(*it)).size();
        
        for(int i = 0; i < numtoallocate; i++)
        {
            funccode.push_back(new OPushRegister(new VarArgument(EXP1)));
        }
        
        //push on the this, if a script
        if(isarun)
        {
            switch(scripttypes[scriptname])
            {
            case ScriptParser::TYPE_FFC:
                funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFFFC)));
                break;
                
            case ScriptParser::TYPE_ITEMCLASS:
                funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFITEMCLASS)));
                break;
                
            case ScriptParser::TYPE_GLOBAL:
                //don't care, we don't have a valid this pointer
                break;
            }
            
            funccode.push_back(new OPushRegister(new VarArgument(EXP2)));
        }
        
        //set up the stack frame register
        funccode.push_back(new OSetRegister(new VarArgument(SFRAME), new VarArgument(SP)));
        OpcodeContext oc;
        oc.linktable = &lt;
        oc.symbols = symbols;
        oc.stackframe = &sf;
        BuildOpcodes bo;
        (*it)->execute(bo, &oc);
        
        if(!bo.isOK())
            failure = true;
            
        vector<Opcode *> code = bo.getResult();
        
        for(vector<Opcode *>::iterator it2 = code.begin(); it2 != code.end(); it2++)
        {
            funccode.push_back(*it2);
        }
        
        //add appendix code
        //nop label
        Opcode *next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0));
        next->setLabel(bo.getReturnLabelID());
        funccode.push_back(next);
        
        //pop off everything
        for(unsigned int i=0; i< stackvars.size(); i++)
        {
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
        }
        
        //if it's a main script, quit.
        if(isarun)
            funccode.push_back(new OQuit());
        else
        {
            //pop off the return address
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
            //and return
            funccode.push_back(new OGotoRegister(new VarArgument(EXP2)));
        }
        
        rval->funcs[lt.functionToLabel(symbols->getID(*it))]=funccode;
        delete *it;
    }
    
    //Z_message("yes");
    
    //update the run symbols
    for(map<string, int>::iterator it = runsymbols.begin(); it != runsymbols.end(); it++)
    {
        int labelid = lt.functionToLabel(it->second);
        rval->scriptRunLabels[it->first] = labelid;
        rval->numParams[it->first] = numparams[it->first];
        rval->scriptTypes[it->first] = scripttypes[it->first];
    }
    
    delete symbols; //and so long to our beloved ;) symbol table
    //Z_message("yes");
    
    if(failure)
    {
        //delete all kinds of crap if there was a problem :-/
        for(map<int, vector<Opcode *> >::iterator it = rval->funcs.begin(); it != rval->funcs.end(); it++)
        {
            for(vector<Opcode *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
            {
                delete *it2;
            }
        }
        
        for(vector<Opcode *>::iterator it = rval->globalsInit.begin(); it != rval->globalsInit.end(); it++)
        {
            delete *it;
        }
        
        for(vector<Opcode *>::iterator it = rval->globalasInit.begin(); it != rval->globalasInit.end(); it++)
        {
            delete *it;
        }
        
        delete rval;
        return NULL;
    }
    
    //Z_message("yes");
    return rval;
}
コード例 #9
0
IntermediateData* ScriptParser::generateOCode(FunctionData& fdata)
{
	Program& program = fdata.program;
	TypeStore& typeStore = program.getTypeStore();
	vector<Datum*>& globalVariables = fdata.globalVariables;

    // Z_message("yes");
    bool failure = false;

    //we now have labels for the functions and ids for the global variables.
    //we can now generate the code to intialize the globals
    IntermediateData *rval = new IntermediateData(fdata);

    // Push 0s for init stack space.
    rval->globalsInit.push_back(
		    new OSetImmediate(new VarArgument(EXP1),
		                      new LiteralArgument(0)));
    int globalStackSize = *program.getScope().getRootStackSize();
    for (int i = 0; i < globalStackSize; ++i)
	    rval->globalsInit.push_back(
			    new OPushRegister(new VarArgument(EXP1)));
    
    // Generate variable init code.
    for (vector<Datum*>::iterator it = globalVariables.begin();
		 it != globalVariables.end(); ++it)
    {
		Datum& variable = **it;
		AST& node = *variable.getNode();

        OpcodeContext oc;
        oc.typeStore = &typeStore;

        BuildOpcodes bo(typeStore);
        node.execute(bo, &oc);
        if (bo.hasFailed()) failure = true;
        appendElements(rval->globalsInit, oc.initCode);
        appendElements(rval->globalsInit, bo.getResult());
    }

    // Pop off everything.
    for (int i = 0; i < globalStackSize; ++i)
	    rval->globalsInit.push_back(
			    new OPopRegister(new VarArgument(EXP2)));
        
    //globals have been initialized, now we repeat for the functions
	vector<Function*> funs = program.getUserFunctions();
	for (vector<Function*>::iterator it = funs.begin();
	     it != funs.end(); ++it)
    {
		Function& function = **it;
		ASTFuncDecl& node = *function.node;

		bool isRun = ZScript::isRun(function);
		string scriptname;
		Script* functionScript = function.getScript();
		if (functionScript)
			scriptname = functionScript->getName();

        vector<Opcode *> funccode;

		int stackSize = getStackSize(function);

        // Start of the function.
        Opcode* first = new OSetImmediate(new VarArgument(EXP1),
                                          new LiteralArgument(0));
        first->setLabel(function.getLabel());
        funccode.push_back(first);

        // Push 0s for the local variables.
        for (int i = stackSize - getParameterCount(function); i > 0; --i)
            funccode.push_back(new OPushRegister(new VarArgument(EXP1)));
        
        // Push on the this, if a script
        if (isRun)
        {
	        ScriptType type = program.getScript(scriptname)->getType();
	        if (type == ScriptType::getFfc())
                funccode.push_back(
		                new OSetRegister(new VarArgument(EXP2),
		                                 new VarArgument(REFFFC)));
	        else if (type == ScriptType::getItem())
                funccode.push_back(
		                new OSetRegister(new VarArgument(EXP2),
		                                 new VarArgument(REFITEMCLASS)));
            
            funccode.push_back(new OPushRegister(new VarArgument(EXP2)));
        }
        
        // Set up the stack frame register
        funccode.push_back(new OSetRegister(new VarArgument(SFRAME),
                                            new VarArgument(SP)));
        OpcodeContext oc;
        oc.typeStore = &typeStore;
        BuildOpcodes bo(typeStore);
        node.execute(bo, &oc);

        if (bo.hasFailed()) failure = true;

        appendElements(funccode, bo.getResult());
        
        // Add appendix code.
        Opcode* next = new OSetImmediate(new VarArgument(EXP2),
                                         new LiteralArgument(0));
        next->setLabel(bo.getReturnLabelID());
        funccode.push_back(next);
        
        // Pop off everything.
        for (int i = 0; i < stackSize; ++i)
        {
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
        }
        
        //if it's a main script, quit.
		if (isRun)
		{
			// Note: the stack still contains the "this" pointer
			// But since the script is about to terminate, we don't
			// care about popping it off.
			funccode.push_back(new OQuit());
		}
        else
        {
			// Not a script's run method, so no "this" pointer to
			// pop off. The top of the stack is now the function
			// return address (pushed on by the caller).
            //pop off the return address
            funccode.push_back(new OPopRegister(new VarArgument(EXP2)));
            //and return
            funccode.push_back(new OGotoRegister(new VarArgument(EXP2)));
        }
        
		function.giveCode(funccode);
    }
    
    if (failure)
    {
        delete rval;
        return NULL;
    }
    
    //Z_message("yes");
    return rval;
}