CompoundStmt* wrapInCompoundStmt(clang::ASTContext& C) const {
   assert(!isSingleStmt() && "Must be more than 1");
   llvm::ArrayRef<Stmt*> stmts
     = llvm::makeArrayRef(m_Stmts.data(), m_Stmts.size());
   clang::SourceLocation noLoc;
   return new (C) clang::CompoundStmt(C, stmts, noLoc, noLoc);
 }
Exemple #2
0
Statement *CompoundStatement::doInlineStatement(InlineDoState *ids)
{
    //printf("CompoundStatement::doInlineStatement() %d\n", statements->dim);
    Statements *as = new Statements();
    as->reserve(statements->dim);
    for (size_t i = 0; i < statements->dim; i++)
    {   Statement *s = (*statements)[i];
        if (s)
        {
            as->push(s->doInlineStatement(ids));
            if (s->isReturnStatement())
                break;

            /* Check for:
             *  if (condition)
             *      return exp1;
             *  else
             *      return exp2;
             */
            IfStatement *ifs = s->isIfStatement();
            if (ifs && ifs->elsebody && ifs->ifbody &&
                ifs->ifbody->isReturnStatement() &&
                ifs->elsebody->isReturnStatement()
               )
                break;
        }
        else
            as->push(NULL);
    }
    return new CompoundStatement(loc, as);
}
Exemple #3
0
    static int _requiredMaxStackSizeFor(Statement* statement, int depth = 0) {
        if (!statement) return 1;

        switch (statement->statementType()) {
            case STMT_LEAF:
                #if DEBUG_SCRIPTVM_CORE
                _printIndents(depth);
                printf("-> STMT_LEAF\n");
                #endif
                return 1;

            case STMT_LIST: {
                #if DEBUG_SCRIPTVM_CORE
                _printIndents(depth);
                printf("-> STMT_LIST\n");
                #endif
                Statements* stmts = (Statements*) statement;
                int max = 0;
                for (int i = 0; stmts->statement(i); ++i) {
                    int size = _requiredMaxStackSizeFor( stmts->statement(i), depth+1 );
                    if (max < size) max = size;
                }
                return max + 1;
            }

            case STMT_BRANCH: {
                #if DEBUG_SCRIPTVM_CORE
                _printIndents(depth);
                printf("-> STMT_BRANCH\n");
                #endif
                BranchStatement* branchStmt = (BranchStatement*) statement;
                int max = 0;
                for (int i = 0; branchStmt->branch(i); ++i) {
                    int size = _requiredMaxStackSizeFor( branchStmt->branch(i), depth+1 );
                    if (max < size) max = size;
                }
                return max + 1;
            }

            case STMT_LOOP: {
                #if DEBUG_SCRIPTVM_CORE
                _printIndents(depth);
                printf("-> STMT_LOOP\n");
                #endif
                While* whileStmt = (While*) statement;
                if (whileStmt->statements())
                    return _requiredMaxStackSizeFor( whileStmt->statements() ) + 1;
                else
                    return 1;
            }
        }

        return 1; // actually just to avoid compiler warning
    }
Exemple #4
0
Statement *AsmBlockStatement::syntaxCopy()
{
    Statements *a = new Statements();
    a->setDim(statements->dim);
    for (size_t i = 0; i < statements->dim; i++)
    {
        Statement *s = static_cast<Statement *>(statements->data[i]);
        if (s)
            s = s->syntaxCopy();
        a->data[i] = s;
    }
    AsmBlockStatement *cs = new AsmBlockStatement(loc, a);
    return cs;
}
Exemple #5
0
Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids)
{
    //printf("UnrolledLoopStatement::doInlineStatement() %d\n", statements->dim);
    Statements *as = new Statements();
    as->reserve(statements->dim);
    for (size_t i = 0; i < statements->dim; i++)
    {   Statement *s = (*statements)[i];
        if (s)
        {
            as->push(s->doInlineStatement(ids));
            if (ids->foundReturn)
                break;
        }
        else
            as->push(NULL);
    }
    return new UnrolledLoopStatement(loc, as);
}
inline void forward_statements(P& problem, O& OUT, I& IN, OS& OUT_S, IS& IN_S, Statements& statements, mtac::basic_block_p& B, bool& changes){
    if(statements.size() > 0){
        IN_S[statements.front()] = IN[B];

        for(unsigned i = 0; i < statements.size(); ++i){
            auto& statement = statements[i];

            assign(OUT_S[statement], problem.transfer(B, statement, IN_S[statement]), changes);

            //The entry value of the next statement are the exit values of the current statement
            if(i != statements.size() - 1){
                IN_S[statements[i+1]] = OUT_S[statement];
            }
        }

        assign(OUT[B], OUT_S[statements.back()], changes);
    } else {
        //If the basic block is empty, the OUT values are the IN values
        assign(OUT[B], IN[B], changes);
    }
}
inline void backward_statements(P& problem, O& OUT, I& IN, OS& OUT_S, IS& IN_S, Statements& statements, mtac::basic_block_p& B, bool& changes){
    if(statements.size() > 0){
        log::emit<Dev>("Data-Flow") << "OUT_S[" << (statements.size() - 1) << "] before transfer " << OUT_S[statements[statements.size() - 1]] << log::endl;
        assign(OUT_S[statements.back()], OUT[B], changes);
        log::emit<Dev>("Data-Flow") << "OUT_S[" << (statements.size() - 1) << "] after  transfer " << OUT_S[statements[statements.size() - 1]] << log::endl;

        for(unsigned i = statements.size() - 1; i > 0; --i){
            auto& statement = statements[i];

            log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] before transfer " << IN_S[statement] << log::endl;
            assign(IN_S[statement], problem.transfer(B, statement, OUT_S[statement]), changes);
            log::emit<Dev>("Data-Flow") << "IN_S[" << i << "] after  transfer " << IN_S[statement] << log::endl;

            log::emit<Dev>("Data-Flow") << "OUT_S[" << (i - 1) << "] before transfer " << OUT_S[statements[i - 1]] << log::endl;
            OUT_S[statements[i-1]] = IN_S[statement];
            log::emit<Dev>("Data-Flow") << "OUT_S[" << (i - 1) << "] after  transfer " << OUT_S[statements[i - 1]] << log::endl;
        }

        log::emit<Dev>("Data-Flow") << "IN_S[" << 0 << "] before transfer " << IN_S[statements[0]] << log::endl;
        assign(IN_S[statements[0]], problem.transfer(B, statements[0], OUT_S[statements[0]]), changes);
        log::emit<Dev>("Data-Flow") << "IN_S[" << 0 << "] after  transfer " << IN_S[statements[0]] << log::endl;

        assign(IN[B], IN_S[statements.front()], changes);
    } else {
        //If the basic block is empty, the IN values are the OUT values
        assign(IN[B], OUT[B], changes);
    }
}
Exemple #8
0
Statements* Parser::statements(){
        if (checkToken(Token::IDENTIFIER) || checkToken(Token::WRITE) ||
            checkToken(Token::READ) || checkToken(Token::CURLYBRACKETOPEN) ||
            checkToken(Token::IF) || checkToken(Token::WHILE)) {
                Statements* myStatements = new Statements();
                if (error) {
                        return myStatements;
                }
                myStatements->addNode(statement());
                if (checkToken(Token::SEMICOLON)) {
                        nextToken();
                        if (error) {
                                return myStatements;
                        }
                        myStatements->addNode(statements());
                } else {
                        syntaxError();
                }
                return myStatements;
        } else {
                // Epsilon
                return new StatementsEpsilon();
        }
}
Exemple #9
0
 void Fix(CompoundStmt* CS) {
   if (!CS->size())
     return;
   typedef llvm::SmallVector<Stmt*, 32> Statements;
   Statements Stmts;
   Stmts.append(CS->body_begin(), CS->body_end());
   for (Statements::iterator I = Stmts.begin(); I != Stmts.end(); ++I) {
     if (!TraverseStmt(*I) && !m_HandledDecls.count(m_FoundDRE->getDecl())) {
       Sema::DeclGroupPtrTy VDPtrTy 
         = m_Sema->ConvertDeclToDeclGroup(m_FoundDRE->getDecl());
       StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, 
                                             m_FoundDRE->getLocStart(), 
                                             m_FoundDRE->getLocEnd());
       assert(!DS.isInvalid() && "Invalid DeclStmt.");
       I = Stmts.insert(I, DS.take());
       m_HandledDecls.insert(m_FoundDRE->getDecl());
     }
   }
   CS->setStmts(m_Sema->getASTContext(), Stmts.data(), Stmts.size());
 }
Exemple #10
0
Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps)
{
    InlineDoState ids;
    DeclarationExp *de;
    Expression *e = NULL;
    Statements *as = NULL;

#if LOG || CANINLINE_LOG
    printf("FuncDeclaration::expandInline('%s')\n", toChars());
#endif

    memset(&ids, 0, sizeof(ids));
    ids.parent = iss->fd;
    ids.fd = this;

    if (ps)
        as = new Statements();

    // Set up vthis
    if (ethis)
    {
        VarDeclaration *vthis;
        ExpInitializer *ei;
        VarExp *ve;

#if STRUCTTHISREF
        if (ethis->type->ty == Tpointer)
        {   Type *t = ethis->type->nextOf();
            ethis = new PtrExp(ethis->loc, ethis);
            ethis->type = t;
        }
        ei = new ExpInitializer(ethis->loc, ethis);

        vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
        if (ethis->type->ty != Tclass)
            vthis->storage_class = STCref;
        else
            vthis->storage_class = STCin;
#else
        if (ethis->type->ty != Tclass && ethis->type->ty != Tpointer)
        {
            ethis = ethis->addressOf(NULL);
        }

        ei = new ExpInitializer(ethis->loc, ethis);

        vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
        vthis->storage_class = STCin;
#endif
        vthis->linkage = LINKd;
        vthis->parent = iss->fd;

        ve = new VarExp(vthis->loc, vthis);
        ve->type = vthis->type;

        ei->exp = new AssignExp(vthis->loc, ve, ethis);
        ei->exp->type = ve->type;
#if STRUCTTHISREF
        if (ethis->type->ty != Tclass)
        {   /* This is a reference initialization, not a simple assignment.
             */
            ei->exp->op = TOKconstruct;
        }
#endif

        ids.vthis = vthis;
    }

    // Set up parameters
    if (ethis)
    {
        e = new DeclarationExp(0, ids.vthis);
        e->type = Type::tvoid;
        if (as)
            as->push(new ExpStatement(e->loc, e));
    }

    if (arguments && arguments->dim)
    {
        assert(parameters->dim == arguments->dim);

        for (size_t i = 0; i < arguments->dim; i++)
        {
            VarDeclaration *vfrom = parameters->tdata()[i];
            VarDeclaration *vto;
            Expression *arg = arguments->tdata()[i];
            ExpInitializer *ei;
            VarExp *ve;

            ei = new ExpInitializer(arg->loc, arg);

            vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
            vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref);
            vto->linkage = vfrom->linkage;
            vto->parent = iss->fd;
            //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
            //printf("vto->parent = '%s'\n", iss->fd->toChars());

            ve = new VarExp(vto->loc, vto);
            //ve->type = vto->type;
            ve->type = arg->type;

            ei->exp = new ConstructExp(vto->loc, ve, arg);
            ei->exp->type = ve->type;
//ve->type->print();
//arg->type->print();
//ei->exp->print();

            ids.from.push(vfrom);
            ids.to.push(vto);

            de = new DeclarationExp(0, vto);
            de->type = Type::tvoid;

            if (as)
                as->push(new ExpStatement(0, de));
            else
                e = Expression::combine(e, de);
        }
    }

    if (ps)
    {
        inlineNest++;
        Statement *s = fbody->doInlineStatement(&ids);
        as->push(s);
        *ps = new ScopeStatement(0, new CompoundStatement(0, as));
        inlineNest--;
    }
    else
    {
        inlineNest++;
        Expression *eb = fbody->doInline(&ids);
        e = Expression::combine(e, eb);
        inlineNest--;
        //eb->type->print();
        //eb->print();
        //eb->dump(0);
    }

    /* There's a problem if what the function returns is used subsequently as an
     * lvalue, as in a struct return that is then used as a 'this'.
     * If we take the address of the return value, we will be taking the address
     * of the original, not the copy. Fix this by assigning the return value to
     * a temporary, then returning the temporary. If the temporary is used as an
     * lvalue, it will work.
     * This only happens with struct returns.
     * See Bugzilla 2127 for an example.
     */
    TypeFunction *tf = (TypeFunction*)type;
    if (!ps && tf->next->ty == Tstruct)
    {
        /* Generate a new variable to hold the result and initialize it with the
         * inlined body of the function:
         *   tret __inlineretval = e;
         */
        ExpInitializer* ei = new ExpInitializer(loc, e);

        Identifier* tmp = Identifier::generateId("__inlineretval");
        VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
        vd->storage_class = tf->isref ? STCref : 0;
        vd->linkage = tf->linkage;
        vd->parent = iss->fd;

        VarExp *ve = new VarExp(loc, vd);
        ve->type = tf->next;

        ei->exp = new ConstructExp(loc, ve, e);
        ei->exp->type = ve->type;

        DeclarationExp* de = new DeclarationExp(0, vd);
        de->type = Type::tvoid;

        // Chain the two together:
        //   ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval
        e = Expression::combine(de, ve);

        //fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
    }

    // Need to reevaluate whether parent can now be inlined
    // in expressions, as we might have inlined statements
    iss->fd->inlineStatusExp = ILSuninitialized;
    return e;
}
Exemple #11
0
void Parser::buildStatement(Statement** toBuild, TokenSequence* relatedSequence) {
	if (StatementSetValue::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementSetValue();
		((StatementSetValue*)(*toBuild))->identifier = relatedSequence->tokenAt(0, false);
		TokenSequence* exceptIdentifier = nullptr;
		TokenSequence* isolatedIdentifier = relatedSequence->splitOn(0, &exceptIdentifier);
		if (isolatedIdentifier != nullptr) {
			isolatedIdentifier->prepareDelete(true);
			delete isolatedIdentifier;
		}
		TokenSequence* assigningCore = nullptr;
		TokenSequence* indexPart = exceptIdentifier->splitOn(ParseTree::splitIndexes->pop(), &assigningCore);
		if (exceptIdentifier != nullptr) {
			exceptIdentifier->prepareDelete(true);
			delete exceptIdentifier;
		}
		((StatementSetValue*)(*toBuild))->index = this->buildIndex(indexPart);
		if (indexPart != nullptr) {
			indexPart->prepareDelete(true);
			delete indexPart;
		}
		TokenSequence* expression = nullptr;
		TokenSequence* assignment = assigningCore->splitOn(0, &expression);
		if (assigningCore != nullptr) {
			assigningCore->prepareDelete(true);
			delete assigningCore;
		}
		if (assignment != nullptr) {
			assignment->prepareDelete(true);
			delete assignment;
		}
		((StatementSetValue*)(*toBuild))->aimValue = this->buildExp(expression);
		if (expression != nullptr) {
			expression->prepareDelete(true);
			delete expression;
		}
	} else if (StatementWrite::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementWrite();
		TokenSequence* exp = nullptr;
		TokenSequence* preExp = relatedSequence->splitOn(1, &exp);
		TokenSequence* postExp = nullptr;
		TokenSequence* actualExp = exp->splitOn(exp->getSize() - 2, &postExp);
		((StatementWrite*)(*toBuild))->toPrint = this->buildExp(actualExp);
		if (exp != nullptr) {
			exp->prepareDelete(true);
			delete exp;
		}
		if (actualExp != nullptr) {
			actualExp->prepareDelete(true);
			delete actualExp;
		}
		if (preExp != nullptr) {
			preExp->prepareDelete(true);
			delete preExp;
		}
		if (postExp != nullptr) {
			postExp->prepareDelete(true);
			delete postExp;
		}
	} else if (StatementRead::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementRead();
		TokenSequence* sub = nullptr;
		TokenSequence* post = nullptr;
		TokenSequence* pre = relatedSequence->splitOn(2, &sub);
		TokenSequence* core = sub->splitOn(sub->getSize()-2, &post);
		((StatementRead*)(*toBuild))->identifier = pre->tokenAt(2, false);
		((StatementRead*)(*toBuild))->index = this->buildIndex(core);
		if (sub != nullptr) {
			sub->prepareDelete(true);
			delete sub;
		}
		if (pre != nullptr) {
			pre->prepareDelete(true);
			delete pre;
		}
		if (core != nullptr) {
			core->prepareDelete(true);
			delete core;
		}
		if (post != nullptr) {
			post->prepareDelete(true);
			delete post;
		}
	} else if (StatementBlock::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementBlock();
		TokenSequence* subcore0 = nullptr;
		TokenSequence* preBrace = relatedSequence->splitOn(0, &subcore0);
		if (preBrace != nullptr) {
			preBrace->prepareDelete(true);
			delete preBrace;
		}
		TokenSequence* postBrace = nullptr;
		TokenSequence* statementCore = subcore0->splitOn(subcore0->getSize() - 2, &postBrace);
		Statements* currentStatements = ((StatementBlock*)(*toBuild))->blockContent;
		if (statementCore->getSize() != 0) {
			currentStatements = new StatementsSeq();
			TokenSequence* singleStatement = nullptr;
			TokenSequence* rest0 = nullptr;
			TokenSequence* semicolon = nullptr;
			TokenSequence* otherStatements = nullptr;
			do {
				singleStatement = statementCore->splitOn(ParseTree::splitIndexes->pop(), &rest0);
				semicolon = rest0->splitOn(0, &otherStatements);
				this->buildStatement(&(((StatementsSeq*)currentStatements)->firstStatement), singleStatement);
				((StatementsSeq*) currentStatements)->restOfStatements = (otherStatements->getSize() == 0 ? ((Statements*)new StatementsSeq()) : ((Statements*)new StatementsEps()));
				if (singleStatement != nullptr) {
					singleStatement->prepareDelete(true);
					delete singleStatement;
				}
				if (rest0 != nullptr) {
					rest0->prepareDelete(true);
					delete rest0;
				}
				if (semicolon != nullptr) {
					semicolon->prepareDelete(true);
					delete semicolon;
				}
				if (statementCore != nullptr) {
					statementCore->prepareDelete(true);
					delete statementCore;
				}
				statementCore = otherStatements;
				currentStatements = ((StatementsSeq*) currentStatements)->restOfStatements;
			} while(!currentStatements->isEps());
		} else {
			currentStatements = new StatementsEps();
		}
	} else if (StatementIfElse::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementIfElse();
		TokenSequence* majorPrefix = nullptr;
		TokenSequence* elseStatement = nullptr;
		TokenSequence* elsePart = nullptr;
		TokenSequence* ifAndItsStatement = nullptr;
		TokenSequence* ifPart = nullptr;
		TokenSequence* semiCore = nullptr;
		TokenSequence* ifExpression = nullptr;
		TokenSequence* endOfIf = nullptr;
		TokenSequence* core = nullptr;
		TokenSequence* ifStatement = nullptr;
		majorPrefix = relatedSequence->splitOn(ParseTree::splitIndexes->pop(), &elseStatement);
		this->buildStatement(&(((StatementIfElse*)(*toBuild))->elseCase), elseStatement);
		if (elseStatement != nullptr) {
			elseStatement->prepareDelete(true);
			delete elseStatement;
		}
		ifAndItsStatement = majorPrefix->splitOn(majorPrefix->getSize() - 3, &elsePart);
		if (majorPrefix != nullptr) {
			majorPrefix->prepareDelete(true);
			delete majorPrefix;
		}
		if (elsePart != nullptr) {
			elsePart->prepareDelete(true);
			delete elsePart;
		}
		ifPart = ifAndItsStatement->splitOn(1, &semiCore);
		if (ifAndItsStatement != nullptr) {
			ifAndItsStatement->prepareDelete(true);
			delete ifAndItsStatement;
		}
		if (ifPart != nullptr) {
			ifPart->prepareDelete(true);
			delete ifPart;
		}
		ifExpression = semiCore->splitOn(ParseTree::splitIndexes->pop(), &endOfIf);
		((StatementIfElse*)(*toBuild))->condition = this->buildExp(ifExpression);
		if (ifExpression != nullptr) {
			ifExpression->prepareDelete(true);
			delete ifExpression;
		}
		if (semiCore != nullptr) {
			semiCore->prepareDelete(true);
			delete semiCore;
		}
		core = endOfIf->splitOn(0, &ifStatement);
		if (core != nullptr) {
			core->prepareDelete(true);
			delete core;
		}
		if (endOfIf != nullptr) {
			endOfIf->prepareDelete(true);
			delete endOfIf;
		}
		this->buildStatement(&(((StatementIfElse*)(*toBuild))->thenCase), ifStatement);
		if (ifStatement != nullptr) {
			ifStatement->prepareDelete(true);
			delete ifStatement;
		}
	} else if (StatementWhile::first()->isSet(relatedSequence->tokenAt(0, false))) {
		*toBuild = new StatementWhile();
		TokenSequence* remainings = nullptr;
		TokenSequence* whileBeginning = relatedSequence->splitOn(1, &remainings);
		if (whileBeginning != nullptr) {
			whileBeginning->prepareDelete(true);
			delete whileBeginning;
		}
		TokenSequence* parStat = nullptr;
		TokenSequence* exp = remainings->splitOn(ParseTree::splitIndexes->pop(), &parStat);
		TokenSequence* statement = nullptr;
		TokenSequence* paranth = parStat->splitOn(0, &statement);
		if (paranth != nullptr) {
			paranth->prepareDelete(true);
			delete paranth;
		}
		((StatementWhile*)(*toBuild))->condition = this->buildExp(exp);
		this->buildStatement(&(((StatementWhile*)(*toBuild))->loop), statement);
		if (exp != nullptr) {
			exp->prepareDelete(true);
			delete exp;
		}
		if (statement != nullptr) {
			statement->prepareDelete(true);
			delete statement;
		}
	}
}
 NodeContext(clang::Stmt* s) { m_Stmts.push_back(s); }
Exemple #13
0
/*****************************************
 * Create inclusive postblit for struct by aggregating
 * all the postblits in postblits[] with the postblits for
 * all the members.
 * Note the close similarity with AggregateDeclaration::buildDtor(),
 * and the ordering changes (runs forward instead of backwards).
 */
FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
{
    //printf("StructDeclaration::buildPostBlit() %s\n", sd->toChars());
    StorageClass stc = STCsafe | STCnothrow | STCpure | STCnogc;
    Loc declLoc = sd->postblits.dim ? sd->postblits[0]->loc : sd->loc;
    Loc loc = Loc();    // internal code should have no loc to prevent coverage

    for (size_t i = 0; i < sd->postblits.dim; i++)
    {
        stc |= sd->postblits[i]->storage_class & STCdisable;
    }

    Statements *a = NULL;
    for (size_t i = 0; i < sd->fields.dim && !(stc & STCdisable); i++)
    {
        VarDeclaration *v = sd->fields[i];
        if (v->storage_class & STCref)
            continue;
        Type *tv = v->type->baseElemOf();
        if (tv->ty != Tstruct || !v->type->size())
            continue;
        StructDeclaration *sdv = ((TypeStruct *)tv)->sym;
        if (!sdv->postblit)
            continue;
        sdv->postblit->functionSemantic();

        stc = mergeFuncAttrs(stc, sdv->postblit);
        stc = mergeFuncAttrs(stc, sdv->dtor);
        if (stc & STCdisable)
        {
            a = NULL;
            break;
        }
        if (!a)
            a = new Statements();

        Expression *ex = new ThisExp(loc);
        ex = new DotVarExp(loc, ex, v, 0);
        if (v->type->toBasetype()->ty == Tstruct)
        {
            // this.v.__xpostblit()

            // This is a hack so we can call postblits on const/immutable objects.
            ex = new AddrExp(loc, ex);
            ex = new CastExp(loc, ex, v->type->mutableOf()->pointerTo());
            ex = new PtrExp(loc, ex);
            if (stc & STCsafe)
                stc = (stc & ~STCsafe) | STCtrusted;

            ex = new DotVarExp(loc, ex, sdv->postblit, 0);
            ex = new CallExp(loc, ex);
        }
        else
        {
            // _ArrayPostblit((cast(S*)this.v.ptr)[0 .. n])

            // This is a hack so we can call postblits on const/immutable objects.
            ex = new DotIdExp(loc, ex, Id::ptr);
            ex = new CastExp(loc, ex, sdv->type->pointerTo());
            if (stc & STCsafe)
                stc = (stc & ~STCsafe) | STCtrusted;

            uinteger_t n = v->type->size() / sdv->type->size();
            ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type::tsize_t),
                                       new IntegerExp(loc, n, Type::tsize_t));
            // Prevent redundant bounds check
            ((SliceExp *)ex)->upperIsInBounds = true;
            ((SliceExp *)ex)->lowerIsLessThanUpper = true;

            ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayPostblit), ex);
        }
        a->push(new ExpStatement(loc, ex)); // combine in forward order

        /* Bugzilla 10972: When the following field postblit calls fail,
         * this field should be destructed for Exception Safety.
         */
        if (!sdv->dtor)
            continue;
        sdv->dtor->functionSemantic();

        ex = new ThisExp(loc);
        ex = new DotVarExp(loc, ex, v, 0);
        if (v->type->toBasetype()->ty == Tstruct)
        {
            // this.v.__xdtor()

            // This is a hack so we can call destructors on const/immutable objects.
            ex = new AddrExp(loc, ex);
            ex = new CastExp(loc, ex, v->type->mutableOf()->pointerTo());
            ex = new PtrExp(loc, ex);
            if (stc & STCsafe)
                stc = (stc & ~STCsafe) | STCtrusted;

            ex = new DotVarExp(loc, ex, sdv->dtor, 0);
            ex = new CallExp(loc, ex);
        }
        else
        {
            // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n])

            // This is a hack so we can call destructors on const/immutable objects.
            ex = new DotIdExp(loc, ex, Id::ptr);
            ex = new CastExp(loc, ex, sdv->type->pointerTo());
            if (stc & STCsafe)
                stc = (stc & ~STCsafe) | STCtrusted;

            uinteger_t n = v->type->size() / sdv->type->size();
            ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type::tsize_t),
                                       new IntegerExp(loc, n, Type::tsize_t));
            // Prevent redundant bounds check
            ((SliceExp *)ex)->upperIsInBounds = true;
            ((SliceExp *)ex)->lowerIsLessThanUpper = true;

            ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), ex);
        }
        a->push(new OnScopeStatement(loc, TOKon_scope_failure, new ExpStatement(loc, ex)));
    }

    /* Build our own "postblit" which executes a
     */
    if (a || (stc & STCdisable))
    {
        //printf("Building __fieldPostBlit()\n");
        PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__fieldPostblit);
        dd->storage_class |= STCinference;
        dd->fbody = a ? new CompoundStatement(loc, a) : NULL;
        sd->postblits.shift(dd);
        sd->members->push(dd);
        dd->semantic(sc);
    }

    FuncDeclaration *xpostblit = NULL;
    switch (sd->postblits.dim)
    {
        case 0:
            break;

        case 1:
            xpostblit = sd->postblits[0];
            break;

        default:
            Expression *e = NULL;
            stc = STCsafe | STCnothrow | STCpure | STCnogc;
            for (size_t i = 0; i < sd->postblits.dim; i++)
            {
                FuncDeclaration *fd = sd->postblits[i];
                stc = mergeFuncAttrs(stc, fd);
                if (stc & STCdisable)
                {
                    e = NULL;
                    break;
                }
                Expression *ex = new ThisExp(loc);
                ex = new DotVarExp(loc, ex, fd, 0);
                ex = new CallExp(loc, ex);
                e = Expression::combine(e, ex);
            }
            PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__aggrPostblit);
            dd->storage_class |= STCinference;
            dd->fbody = new ExpStatement(loc, e);
            sd->members->push(dd);
            dd->semantic(sc);
            xpostblit = dd;
            break;
    }
    // Add an __xpostblit alias to make the inclusive postblit accessible
    if (xpostblit)
    {
        AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xpostblit, xpostblit);
        alias->semantic(sc);
        sd->members->push(alias);
        alias->addMember(sc, sd); // add to symbol table
    }
    return xpostblit;
}
Exemple #14
0
ParseTree* Parser::parse() {
	if (this->currentCodeSnippet == nullptr) {
		throw "Undefined file for parser\n";
	}
	if (!ProgOnly::isMatching(this->currentCodeSnippet)) {
		std::cerr << "error some spot: syntax error type 2 (invalid token composition)\n";
		exit(1);
	}
	// if it does match, the entire code (in the test file) is OK and all dynamic indexes the Parser must split the sequence on are in ParseTree::splitIndexes
	ProgOnly* prog = new ProgOnly();
	TokenSequence* statementPart = nullptr;
	TokenSequence* declarationPart = this->currentCodeSnippet->splitOn(ParseTree::splitIndexes->pop(), &statementPart);
	if (Decls::first()->isSet(this->currentCodeSnippet->tokenAt(0, false))) {
		prog->declarationSegment = new DeclsSeq();
		TokenSequence* singleDeclaration = nullptr;
		TokenSequence* rest0 = nullptr;
		TokenSequence* semicolon = nullptr;
		TokenSequence* otherDeclarations = nullptr;
		Decls* currentDecls = prog->declarationSegment;
		do {
			singleDeclaration = declarationPart->splitOn(ParseTree::splitIndexes->pop(), &rest0);
			semicolon = rest0->splitOn(0, &otherDeclarations);
			((DeclsSeq*) currentDecls)->firstDeclaration = new DeclOnly();
			this->buildDecl(&(((DeclsSeq*)currentDecls)->firstDeclaration), singleDeclaration);
			((DeclsSeq*) currentDecls)->restOfDeclarations = (otherDeclarations->getSize() == 0 ? ((Decls*)new DeclsSeq()) : ((Decls*)new DeclsEps()));
			if (singleDeclaration != nullptr) {
				singleDeclaration->prepareDelete(true);
				delete singleDeclaration;
			}
			if (rest0 != nullptr) {
				rest0->prepareDelete(true);
				delete rest0;
			}
			if (semicolon != nullptr) {
				semicolon->prepareDelete(true);
				delete semicolon;
			}
			if (declarationPart != nullptr) {
				declarationPart->prepareDelete(true);
				delete declarationPart;
			}
			declarationPart = otherDeclarations;
			currentDecls = ((DeclsSeq*) currentDecls)->restOfDeclarations;
		} while(!currentDecls->isEps());
	} else {
		prog->declarationSegment = new DeclsEps();
	}
	if (statementPart->getSize() != 0) {
		prog->statementSegment = new StatementsSeq();
		TokenSequence* singleStatement = nullptr;
		TokenSequence* rest0 = nullptr;
		TokenSequence* semicolon = nullptr;
		TokenSequence* otherStatements = nullptr;
		Statements* currentStatements = prog->statementSegment;
		do {
			singleStatement = statementPart->splitOn(ParseTree::splitIndexes->pop(), &rest0);
			semicolon = rest0->splitOn(0, &otherStatements);
			this->buildStatement(&(((StatementsSeq*)currentStatements)->firstStatement), singleStatement);
			((StatementsSeq*) currentStatements)->restOfStatements = (otherStatements->getSize() == 0 ? ((Statements*)new StatementsSeq()) : ((Statements*)new StatementsEps()));
			if (singleStatement != nullptr) {
				singleStatement->prepareDelete(true);
				delete singleStatement;
			}
			if (rest0 != nullptr) {
				rest0->prepareDelete(true);
				delete rest0;
			}
			if (semicolon != nullptr) {
				semicolon->prepareDelete(true);
				delete semicolon;
			}
			if (statementPart != nullptr) {
				statementPart->prepareDelete(true);
				delete statementPart;
			}
			statementPart = otherStatements;
			currentStatements = ((StatementsSeq*) currentStatements)->restOfStatements;
		} while(!currentStatements->isEps());
	} else {
		prog->statementSegment = new StatementsEps();
	}
	if (declarationPart != nullptr) {
		declarationPart->prepareDelete(true);
		delete declarationPart;
	}
	if (statementPart != nullptr) {
		statementPart->prepareDelete(true);
		delete statementPart;
	}
	std::cout << "Parsing works\n";
	return prog;
}
Exemple #15
0
    VMExecStatus_t ScriptVM::exec(VMParserContext* parserContext, VMExecContext* execContex, VMEventHandler* handler) {
        m_parserContext = dynamic_cast<ParserContext*>(parserContext);
        if (!m_parserContext) {
            std::cerr << "No VM parser context provided. Did you load a script?.\n";
            return VMExecStatus_t(VM_EXEC_NOT_RUNNING | VM_EXEC_ERROR);
        }

        // a ParserContext object is always tied to exactly one ScriptVM object
        assert(m_parserContext->functionProvider == this);

        ExecContext* ctx = dynamic_cast<ExecContext*>(execContex);
        if (!ctx) {
            std::cerr << "Invalid VM exec context.\n";
            return VMExecStatus_t(VM_EXEC_NOT_RUNNING | VM_EXEC_ERROR);
        }
        EventHandler* h = dynamic_cast<EventHandler*>(handler);
        if (!h) return VM_EXEC_NOT_RUNNING;

        m_parserContext->execContext = ctx;

        ctx->status = VM_EXEC_RUNNING;
        StmtFlags_t flags = STMT_SUCCESS;

        int& frameIdx = ctx->stackFrame;
        if (frameIdx < 0) { // start condition ...
            frameIdx = -1;
            ctx->pushStack(h);
        }

        while (flags == STMT_SUCCESS && frameIdx >= 0) {
            if (frameIdx >= ctx->stack.size()) { // should never happen, otherwise it's a bug ...
                std::cerr << "CRITICAL: VM stack overflow! (" << frameIdx << ")\n";
                flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
                break;
            }

            ExecContext::StackFrame& frame = ctx->stack[frameIdx];
            switch (frame.statement->statementType()) {
                case STMT_LEAF: {
                    #if DEBUG_SCRIPTVM_CORE
                    _printIndents(frameIdx);
                    printf("-> STMT_LEAF\n");
                    #endif
                    LeafStatement* leaf = (LeafStatement*) frame.statement;
                    flags = leaf->exec();
                    ctx->popStack();
                    break;
                }

                case STMT_LIST: {
                    #if DEBUG_SCRIPTVM_CORE
                    _printIndents(frameIdx);
                    printf("-> STMT_LIST subidx=%d\n", frame.subindex);
                    #endif
                    Statements* stmts = (Statements*) frame.statement;
                    if (stmts->statement(frame.subindex)) {
                        ctx->pushStack(
                            stmts->statement(frame.subindex++)
                        );
                    } else {
                        #if DEBUG_SCRIPTVM_CORE
                        _printIndents(frameIdx);
                        printf("[END OF LIST] subidx=%d\n", frame.subindex);
                        #endif
                        ctx->popStack();
                    }
                    break;
                }

                case STMT_BRANCH: {
                    #if DEBUG_SCRIPTVM_CORE
                    _printIndents(frameIdx);
                    printf("-> STMT_BRANCH\n");
                    #endif
                    if (frame.subindex < 0) ctx->popStack();
                    else {
                        BranchStatement* branchStmt = (BranchStatement*) frame.statement;
                        frame.subindex = branchStmt->evalBranch();
                        if (frame.subindex >= 0) {
                            ctx->pushStack(
                                branchStmt->branch(frame.subindex)
                            );
                            frame.subindex = -1;
                        } else ctx->popStack();
                    }
                    break;
                }

                case STMT_LOOP: {
                    #if DEBUG_SCRIPTVM_CORE
                    _printIndents(frameIdx);
                    printf("-> STMT_LOOP\n");
                    #endif
                    While* whileStmt = (While*) frame.statement;
                    if (whileStmt->evalLoopStartCondition() && whileStmt->statements()) {
                        ctx->pushStack(
                            whileStmt->statements()
                        );
                    } else ctx->popStack();
                }
            }
        }

        if (flags & STMT_SUSPEND_SIGNALLED) {
            ctx->status = VM_EXEC_SUSPENDED;
        } else {
            ctx->status = VM_EXEC_NOT_RUNNING;
            if (flags & STMT_ERROR_OCCURRED)
                ctx->status = VM_EXEC_ERROR;
            ctx->reset();
        }

        m_parserContext->execContext = NULL;
        m_parserContext = NULL;
        return ctx->status;
    }
 NodeContext(clang::Stmt* s0, clang::Stmt* s1) {
   m_Stmts.push_back(s0);
   m_Stmts.push_back(s1);
 }
 bool isSingleStmt() const { return m_Stmts.size() == 1; }
Exemple #18
0
Expression *FuncDeclaration::expandInline(InlineScanState *iss,
        Expression *eret, Expression *ethis, Expressions *arguments, Statement **ps)
{
    InlineDoState ids;
    Expression *e = NULL;
    Statements *as = NULL;
    TypeFunction *tf = (TypeFunction*)type;

#if LOG || CANINLINE_LOG
    printf("FuncDeclaration::expandInline('%s')\n", toChars());
#endif

    memset(&ids, 0, sizeof(ids));
    ids.parent = iss->fd;
    ids.fd = this;

    if (ps)
        as = new Statements();

    VarDeclaration *vret = NULL;
    if (eret)
    {
        if (eret->op == TOKvar)
        {
            vret = ((VarExp *)eret)->var->isVarDeclaration();
            assert(!(vret->storage_class & (STCout | STCref)));
        }
        else
        {
            /* Inlining:
             *   this.field = foo();   // inside constructor
             */
            vret = new VarDeclaration(loc, eret->type, Lexer::uniqueId("_satmp"), NULL);
            vret->storage_class |= STCtemp | STCforeach | STCref;
            vret->linkage = LINKd;
            vret->parent = iss->fd;

            Expression *de;
            de = new DeclarationExp(loc, vret);
            de->type = Type::tvoid;
            e = Expression::combine(e, de);

            Expression *ex;
            ex = new VarExp(loc, vret);
            ex->type = vret->type;
            ex = new ConstructExp(loc, ex, eret);
            ex->type = vret->type;
            e = Expression::combine(e, ex);
        }
    }

    // Set up vthis
    if (ethis)
    {
        VarDeclaration *vthis;
        ExpInitializer *ei;
        VarExp *ve;

        if (ethis->type->ty == Tpointer)
        {   Type *t = ethis->type->nextOf();
            ethis = new PtrExp(ethis->loc, ethis);
            ethis->type = t;
        }
        ei = new ExpInitializer(ethis->loc, ethis);

        vthis = new VarDeclaration(ethis->loc, ethis->type, Id::This, ei);
        if (ethis->type->ty != Tclass)
            vthis->storage_class = STCref;
        else
            vthis->storage_class = STCin;
        vthis->linkage = LINKd;
        vthis->parent = iss->fd;

        ve = new VarExp(vthis->loc, vthis);
        ve->type = vthis->type;

        ei->exp = new AssignExp(vthis->loc, ve, ethis);
        ei->exp->type = ve->type;
        if (ethis->type->ty != Tclass)
        {   /* This is a reference initialization, not a simple assignment.
             */
            ei->exp->op = TOKconstruct;
        }

        ids.vthis = vthis;
    }

    // Set up parameters
    if (ethis)
    {
        Expression *de = new DeclarationExp(Loc(), ids.vthis);
        de->type = Type::tvoid;
        e = Expression::combine(e, de);
    }

    if (!ps && nrvo_var)
    {
        if (vret)
        {
            ids.from.push(nrvo_var);
            ids.to.push(vret);
        }
        else
        {
            Identifier* tmp = Identifier::generateId("__nrvoretval");
            VarDeclaration* vd = new VarDeclaration(loc, nrvo_var->type, tmp, NULL);
            assert(!tf->isref);
            vd->storage_class = STCtemp | STCrvalue;
            vd->linkage = tf->linkage;
            vd->parent = iss->fd;

            ids.from.push(nrvo_var);
            ids.to.push(vd);

            Expression *de = new DeclarationExp(Loc(), vd);
            de->type = Type::tvoid;
            e = Expression::combine(e, de);
        }
    }
    if (arguments && arguments->dim)
    {
        assert(parameters->dim == arguments->dim);

        for (size_t i = 0; i < arguments->dim; i++)
        {
            VarDeclaration *vfrom = (*parameters)[i];
            VarDeclaration *vto;
            Expression *arg = (*arguments)[i];
            ExpInitializer *ei;
            VarExp *ve;

            ei = new ExpInitializer(arg->loc, arg);

            vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei);
            vto->storage_class |= vfrom->storage_class & (STCtemp | STCin | STCout | STClazy | STCref);
            vto->linkage = vfrom->linkage;
            vto->parent = iss->fd;
            //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class);
            //printf("vto->parent = '%s'\n", iss->fd->toChars());

            ve = new VarExp(vto->loc, vto);
            //ve->type = vto->type;
            ve->type = arg->type;

            ei->exp = new ConstructExp(vto->loc, ve, arg);
            ei->exp->type = ve->type;
            //ve->type->print();
            //arg->type->print();
            //ei->exp->print();

            ids.from.push(vfrom);
            ids.to.push(vto);

            DeclarationExp *de = new DeclarationExp(Loc(), vto);
            de->type = Type::tvoid;

            e = Expression::combine(e, de);
        }
    }

    if (ps)
    {
        if (e)
            as->push(new ExpStatement(Loc(), e));
        inlineNest++;
        Statement *s = fbody->doInlineStatement(&ids);
        as->push(s);
        *ps = new ScopeStatement(Loc(), new CompoundStatement(Loc(), as));
        inlineNest--;
    }
    else
    {
        inlineNest++;
        Expression *eb = fbody->doInline(&ids);
        e = Expression::combine(e, eb);
        inlineNest--;
        //eb->type->print();
        //eb->print();
        //eb->dump(0);

        // Bugzilla 11322:
        if (tf->isref)
            e = e->toLvalue(NULL, NULL);

        /* There's a problem if what the function returns is used subsequently as an
         * lvalue, as in a struct return that is then used as a 'this'.
         * If we take the address of the return value, we will be taking the address
         * of the original, not the copy. Fix this by assigning the return value to
         * a temporary, then returning the temporary. If the temporary is used as an
         * lvalue, it will work.
         * This only happens with struct returns.
         * See Bugzilla 2127 for an example.
         *
         * On constructor call making __inlineretval is merely redundant, because
         * the returned reference is exactly same as vthis, and the 'this' variable
         * already exists at the caller side.
         */
        if (tf->next->ty == Tstruct && !nrvo_var && !isCtorDeclaration())
        {
            /* Generate a new variable to hold the result and initialize it with the
             * inlined body of the function:
             *   tret __inlineretval = e;
             */
            ExpInitializer* ei = new ExpInitializer(loc, e);

            Identifier* tmp = Identifier::generateId("__inlineretval");
            VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei);
            vd->storage_class = (tf->isref ? STCref : 0) | STCtemp | STCrvalue;
            vd->linkage = tf->linkage;
            vd->parent = iss->fd;

            VarExp *ve = new VarExp(loc, vd);
            ve->type = tf->next;

            ei->exp = new ConstructExp(loc, ve, e);
            ei->exp->type = ve->type;

            DeclarationExp* de = new DeclarationExp(Loc(), vd);
            de->type = Type::tvoid;

            // Chain the two together:
            //   ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval
            e = Expression::combine(de, ve);

            //fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
        }
    }
    //printf("%s->expandInline = { %s }\n", fd->toChars(), e->toChars());

    // Need to reevaluate whether parent can now be inlined
    // in expressions, as we might have inlined statements
    iss->fd->inlineStatusExp = ILSuninitialized;
    return e;
}
 clang::Stmt* getStmt() {
   assert(isSingleStmt() && "Cannot get multiple stmts.");
   return m_Stmts.front();
 }
 void prepend(clang::Stmt* S) {
   m_Stmts.insert(m_Stmts.begin(), S);
 }
 void append(clang::Stmt* S) {
   m_Stmts.push_back(S);
 }