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); }
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); }
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 }
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; }
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); } }
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(); } }
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()); }
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; }
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); }
/***************************************** * 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; }
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; }
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; }
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); }