StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg exprs, Expr *asmString, MultiExprArg clobbers, SourceLocation RParenLoc) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast<StringLiteral**>(constraints.data()); Expr **Exprs = exprs.data(); StringLiteral *AsmString = cast<StringLiteral>(asmString); StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; // The parser verifies that there is a string literal here. if (!AsmString->isAscii()) return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) << AsmString->getSourceRange()); for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); StringRef OutputName; if (Names[i]) OutputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); if (!Context.getTargetInfo().validateOutputConstraint(Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) << Info.getConstraintStr()); // Check that the output exprs are valid lvalues. Expr *OutputExpr = Exprs[i]; if (CheckAsmLValue(OutputExpr, *this)) return StmtError(Diag(OutputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_output) << OutputExpr->getSourceRange()); if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); OutputConstraintInfos.push_back(Info); } SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { StringLiteral *Literal = Constraints[i]; if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); StringRef InputName; if (Names[i]) InputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), NumOutputs, Info)) { return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << Info.getConstraintStr()); } Expr *InputExpr = Exprs[i]; // Only allow void types for memory constraints. if (Info.allowsMemory() && !Info.allowsRegister()) { if (CheckAsmLValue(InputExpr, *this)) return StmtError(Diag(InputExpr->getLocStart(), diag::err_asm_invalid_lvalue_in_input) << Info.getConstraintStr() << InputExpr->getSourceRange()); } if (Info.allowsRegister()) { if (InputExpr->getType()->isVoidType()) { return StmtError(Diag(InputExpr->getLocStart(), diag::err_asm_invalid_type_in_input) << InputExpr->getType() << Info.getConstraintStr() << InputExpr->getSourceRange()); } } ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); if (Result.isInvalid()) return StmtError(); Exprs[i] = Result.take(); InputConstraintInfos.push_back(Info); const Type *Ty = Exprs[i]->getType().getTypePtr(); if (Ty->isDependentType()) continue; if (!Ty->isVoidType() || !Info.allowsMemory()) if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo().validateInputSize(Literal->getString(), Size)) return StmtError(Diag(InputExpr->getLocStart(), diag::err_asm_invalid_input_size) << Info.getConstraintStr()); } // Check that the clobbers are valid. for (unsigned i = 0; i != NumClobbers; i++) { StringLiteral *Literal = Clobbers[i]; if (!Literal->isAscii()) return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); StringRef Clobber = Literal->getString(); if (!Context.getTargetInfo().isValidClobber(Clobber)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_unknown_register_name) << Clobber); } GCCAsmStmt *NS = new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names, Constraints, Exprs, AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; unsigned DiagOffs; if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) << AsmString->getSourceRange(); return StmtError(); } // Validate constraints and modifiers. for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { GCCAsmStmt::AsmStringPiece &Piece = Pieces[i]; if (!Piece.isOperand()) continue; // Look for the correct constraint index. unsigned Idx = 0; unsigned ConstraintIdx = 0; for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) { TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; if (Idx == Piece.getOperandNo()) break; ++Idx; if (Info.isReadWrite()) { if (Idx == Piece.getOperandNo()) break; ++Idx; } } for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; if (Idx == Piece.getOperandNo()) break; ++Idx; if (Info.isReadWrite()) { if (Idx == Piece.getOperandNo()) break; ++Idx; } } // Now that we have the right indexes go ahead and check. StringLiteral *Literal = Constraints[ConstraintIdx]; const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr(); if (Ty->isDependentType() || Ty->isIncompleteType()) continue; unsigned Size = Context.getTypeSize(Ty); if (!Context.getTargetInfo() .validateConstraintModifier(Literal->getString(), Piece.getModifier(), Size)) Diag(Exprs[ConstraintIdx]->getLocStart(), diag::warn_asm_mismatched_size_modifier); } // Validate tied input operands for type mismatches. for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; // If this is a tied constraint, verify that the output and input have // either exactly the same type, or that they are int/ptr operands with the // same size (int/long, int*/long, are ok etc). if (!Info.hasTiedOperand()) continue; unsigned TiedTo = Info.getTiedOperand(); unsigned InputOpNo = i+NumOutputs; Expr *OutputExpr = Exprs[TiedTo]; Expr *InputExpr = Exprs[InputOpNo]; if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) continue; QualType InTy = InputExpr->getType(); QualType OutTy = OutputExpr->getType(); if (Context.hasSameType(InTy, OutTy)) continue; // All types can be tied to themselves. // Decide if the input and output are in the same domain (integer/ptr or // floating point. enum AsmDomain { AD_Int, AD_FP, AD_Other } InputDomain, OutputDomain; if (InTy->isIntegerType() || InTy->isPointerType()) InputDomain = AD_Int; else if (InTy->isRealFloatingType()) InputDomain = AD_FP; else InputDomain = AD_Other; if (OutTy->isIntegerType() || OutTy->isPointerType()) OutputDomain = AD_Int; else if (OutTy->isRealFloatingType()) OutputDomain = AD_FP; else OutputDomain = AD_Other; // They are ok if they are the same size and in the same domain. This // allows tying things like: // void* to int* // void* to int if they are the same size. // double to long double if they are the same size. // uint64_t OutSize = Context.getTypeSize(OutTy); uint64_t InSize = Context.getTypeSize(InTy); if (OutSize == InSize && InputDomain == OutputDomain && InputDomain != AD_Other) continue; // If the smaller input/output operand is not mentioned in the asm string, // then we can promote the smaller one to a larger input and the asm string // won't notice. bool SmallerValueMentioned = false; // If this is a reference to the input and if the input was the smaller // one, then we have to reject this asm. if (isOperandMentioned(InputOpNo, Pieces)) { // This is a use in the asm string of the smaller operand. Since we // codegen this by promoting to a wider value, the asm will get printed // "wrong". SmallerValueMentioned |= InSize < OutSize; } if (isOperandMentioned(TiedTo, Pieces)) { // If this is a reference to the output, and if the output is the larger // value, then it's ok because we'll promote the input to the larger type. SmallerValueMentioned |= OutSize < InSize; } // If the smaller value wasn't mentioned in the asm string, and if the // output was a register, just extend the shorter one to the size of the // larger one. if (!SmallerValueMentioned && InputDomain != AD_Other && OutputConstraintInfos[TiedTo].allowsRegister()) continue; // Either both of the operands were mentioned or the smaller one was // mentioned. One more special case that we'll allow: if the tied input is // integer, unmentioned, and is a constant, then we'll allow truncating it // down to the size of the destination. if (InputDomain == AD_Int && OutputDomain == AD_Int && !isOperandMentioned(InputOpNo, Pieces) && InputExpr->isEvaluatable(Context)) { CastKind castKind = (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); Exprs[InputOpNo] = InputExpr; NS->setInputExpr(i, InputExpr); continue; } Diag(InputExpr->getLocStart(), diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() << InputExpr->getSourceRange(); return StmtError(); } return Owned(NS); }
void translate_to_redlog_term(const map<Expr, unsigned>& variables, const Expr& term) { bool first; unsigned n = term.getNumChildren(); if (n == 0) { if (term.getKind() == kind::CONST_RATIONAL) { cout << term.getConst<Rational>(); } else { assert(variables.find(term) != variables.end()); cout << "x" << variables.find(term)->second; } } else { switch (term.getKind()) { case kind::PLUS: cout << "("; first = true; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " + "; } first = false; translate_to_redlog_term(variables, term[i]); } cout << ")"; break; case kind::MULT: cout << "("; first = true; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " * "; } first = false; translate_to_redlog_term(variables, term[i]); } cout << ")"; break; case kind::MINUS: cout << "("; translate_to_redlog_term(variables, term[0]); cout << " - "; translate_to_redlog_term(variables, term[1]); cout << ")"; break; case kind::DIVISION: cout << "("; translate_to_redlog_term(variables, term[0]); cout << " / "; translate_to_redlog_term(variables, term[1]); cout << ")"; break; case kind::UMINUS: cout << "(-("; translate_to_redlog_term(variables, term[0]); cout << "))"; break; default: assert(false); break; } } }
void run_the_VM() { assert(! bootstrapping, "don't get screwed again by this"); Memory->scavenge(); SignalInterface::initialize(); initHProfiler(); IntervalTimer::start_all(); ResourceMark mark; InteractiveScanner scanner; VMScanner = &scanner; resetTerminal(); if (startUpSelfFile) { ResourceMark m; FileScanner scnr(startUpSelfFile); if (scnr.fileError) { fatalNoMenu1("Couldn't read file %s!\n\n", startUpSelfFile); } else { lprintf("Reading %s...", scnr.fileName()); (void) evalExpressions(&scnr); lprintf("done\n"); } } // After reading a snapshot we need to evaluate the snapshot actions. if (postReadSnapshot) { postReadSnapshot = false; eval("snapshotAction postRead", "<postRead Snapshot>"); } // The read-eval-print loop for (;;) { ResourceMark m; fint line, len; const char* source = NULL; Parser parser(VMScanner, false); resetTerminal(); VMScanner->start_line("VM# "); processes->idle = true; if (VMScanner->is_done()) break; processes->idle = false; Expr* e = parser.readExpr(line, source, len); // dont fail if (e) { preservedObj x(e); oop res = e->Eval(true, false, true); assert(currentProcess->isClean(), "vm process should be clean now"); if (res == badOop) { VMScanner->reset(); clearerr(stdin); // don't get hung on ^D } } if (Memory->needs_scavenge()) Memory->scavenge(); } lprintf("\n"); # if TARGET_IS_PROFILED lprintf("Writing profile statistics...\n"); # endif clearerr(stdin); OS::handle_suspend_and_resume(true); // make sure stdin is in normal mode OS::terminate(0); }
inline Sacado::CacheFad::Expr< Sacado::CacheFad::SFadExprTag<T,Num> >:: Expr(const Expr< Sacado::CacheFad::SFadExprTag<T,Num> >& x) : val_(x.val()) { for (int i=0; i<Num; i++) dx_[i] = x.dx_[i]; }
Stmt *TransformVector::VisitSwitchStmt(SwitchStmt *Node) { DeclVector DeclVec; // Cond Expr *Cond = Node->getCond(); if (Cond->getType()->isVectorType()) { Node->setCond(ConvertVecLiteralInExpr(DeclVec, Cond)); } else { Node->setCond(TransformExpr(Cond)); } // Body Stmt *Body = Node->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); if (!CS) { // Convert a single stmt body into a CompoundStmt. SourceLocation loc; CS = new (ASTCtx) CompoundStmt(ASTCtx, &Body, 1, loc, loc); } // Check all SwitchCase stmts themselves. SwitchCase *CurCase = Node->getSwitchCaseList(); while (CurCase) { if (CaseStmt *CaseS = dyn_cast<CaseStmt>(CurCase)) { Expr *CaseLHS = CaseS->getLHS(); if (CaseLHS->getType()->isVectorType()) { CaseS->setLHS(ConvertVecLiteralInExpr(DeclVec, CaseLHS)); } else { CaseS->setLHS(TransformExpr(CaseLHS)); } Expr *CaseRHS = CaseS->getRHS(); if (CaseRHS && CaseRHS->getType()->isVectorType()) { CaseS->setRHS(ConvertVecLiteralInExpr(DeclVec, CaseRHS)); } else { CaseS->setRHS(TransformExpr(CaseRHS)); } } CurCase = CurCase->getNextSwitchCase(); } // Check if there was a vector literal code motion. if (DeclVec.size() > 0) { PushBackDeclStmts(*CurStmtVec, DeclVec); } // If case stmts are not CompoundStmts, convert them into CompoundStmts StmtVector BodyStmts; CompoundStmt::body_iterator I, E; for (I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { // Save the current stmt BodyStmts.push_back(*I); if (SwitchCase *SC = dyn_cast<SwitchCase>(*I)) { CompoundStmt::body_iterator NextI = I + 1; if (NextI == E) break; if (isa<SwitchCase>(*NextI)) { // No stmt between current case stmt and next case stmt. if (Stmt *SubStmt = SC->getSubStmt()) { if (!isa<CompoundStmt>(SubStmt)) { SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, &SubStmt, 1, loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } } else { StmtVector StmtVec; // SubStmt if (Stmt *SubStmt = SC->getSubStmt()) { StmtVec.push_back(SubStmt); } // Following stmts do { I = NextI; StmtVec.push_back(*I); } while ((++NextI != E) && !isa<SwitchCase>(*NextI)); // Convert all stmts into a CompoundStmt. SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, StmtVec.data(), StmtVec.size(), loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } //end if } //end for CS = new (ASTCtx) CompoundStmt(ASTCtx, BodyStmts.data(), BodyStmts.size(), SourceLocation(), SourceLocation()); ASTCtx.Deallocate(Node->getBody()); Node->setBody(TransformStmt(CS)); return Node; }
LFSCProof* LFSCProof::Make_CNF( const Expr& form, const Expr& reason, int pos ) { Expr ec = cascade_expr( form ); #ifdef PRINT_MAJOR_METHODS cout << ";[M] CNF " << reason << " " << pos << std::endl; #endif int m = queryM( ec ); if( m>0 ) { ostringstream os1; ostringstream os2; RefPtr< LFSCProof > p; if( reason==d_or_final_s ) { #if 0 //this is the version that cascades //make the proof for the or p = LFSCPfVar::Make( "@v", abs(m) ); //clausify the or statement p = LFSCClausify::Make( ec, p.get(), true ); //return return LFSCAssume::Make( m, p.get(), true ); #else //this is the version that does not expand the last ostringstream oss1, oss2; p = LFSCPfVar::Make( "@v", abs(m) ); for( int a=(form.arity()-2); a>=0; a-- ){ int m1 = queryM( form[a] ); oss1 << "(or_elim_1 _ _ "; oss1 << ( m1<0 ? "(not_not_intro _ " : "" ); oss1 << "@v" << abs( m1 ); oss1 << ( m1<0 ? ") " : " " ); oss2 << ")"; } p = LFSCProofGeneric::Make( oss1.str(), p.get(), oss2.str() ); //p = LFSCClausify::Make( form[form.arity()-1], p.get() ); p = LFSCClausify::Make( queryM( form[form.arity()-1] ), p.get() ); for( int a=0; a<(form.arity()-1); a++ ){ p = LFSCAssume::Make( queryM( form[a] ), p.get(), false ); } return LFSCAssume::Make( m, p.get() ); #endif } else if( reason==d_and_final_s ) { #if 1 //this is the version that does not expand the last p = LFSCPfVar::Make( "@v", abs(m) ); os1 << "(contra _ "; for( int a=0; a<form.arity(); a++ ){ if( a<(form.arity()-1)) os1 << "(and_intro _ _ "; os1 << "@v" << abs( queryM( form[a] ) ); if( a<(form.arity()-1)){ os1 << " "; os2 << ")"; } } os2 << " @v" << abs(m) << ")"; os1 << os2.str(); p = LFSCProofGeneric::MakeStr( os1.str().c_str() ); for( int a=0; a<form.arity(); a++ ){ p = LFSCAssume::Make( queryM( form[a] ), p.get() ); } return LFSCAssume::Make( m, p.get(), false ); #else //this is the version that cascades std::vector< Expr > assumes; Expr ce = cascade_expr( form ); Expr curr = ce; os1 << "(contra _ "; while( curr.getKind()==AND ){ os1 << "(and_intro _ _ "; os1 << "@v" << abs( queryM( curr[0] ) ) << " "; os2 << ")"; assumes.push_back( curr[0] ); curr = curr[1]; } os2 << " @v" << abs(m) << ")"; p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() ); for( int a=0; a<(int)assumes.size(); a++ ){ p = LFSCAssume::Make( queryM( assumes[a] ), p.get() ); } return LFSCAssume::Make( m, p.get(), false ); #endif } else if( reason==d_imp_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 0: break; case 1: break; case 2: { //make a proof of the RHS ostringstream os; os << "(impl_elim _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[1], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; } } else if( reason==d_ite_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 1: { ostringstream os; os << "(ite_elim_2" << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[2], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 2: { ostringstream os; os << "(not_ite_elim_2 _ _ _ @v" << (m1<0 ? "n" : "" ); os << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[2] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 3: { ostringstream os; os << "(not_ite_elim_1 _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[1] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 4: { ostringstream os; os << "(ite_elim_1";// << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[1], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 5: { ostringstream os; os << "(not_ite_elim_3 _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); Expr e = Expr( NOT, form[2] ); p = LFSCClausify::Make( e, p.get() ); p = LFSCAssume::Make( queryM( ec[1] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 6: { ostringstream os; os << "(ite_elim_3";// << (m1<0 ? "n" : "" ); os << " _ _ _ @v" << abs( m2 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[2], p.get() ); p = LFSCAssume::Make( queryM( ec[1] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; } } else if( reason==d_iff_s ) { int m1 = queryM( ec[0] ); int m2 = queryM( ec[1] ); switch( pos ) { case 0: { ostringstream os; os << "(not_iff_elim_1 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( form[1], p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get(), false ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 1: { ostringstream os; os << "(not_iff_elim_2 _ _ @v" << abs( m1 ) << " @v" << abs( m ) << ")"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); p = LFSCClausify::Make( Expr( NOT, form[1] ), p.get() ); p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get(), false ); } break; case 2: { ostringstream os; os << "(impl_elim _ _ @v" << abs( m1 ) << "(iff_elim_1 _ _ @v" << abs( m ) << "))"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[1], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[0] ), p.get() ); return LFSCAssume::Make( queryM( ec ), p.get() ); } break; case 3: { ostringstream os; os << "(impl_elim _ _ @v" << abs( m2 ) << "(iff_elim_2 _ _ @v" << abs( m ) << "))"; p = LFSCProofGeneric::MakeStr( os.str().c_str() ); //clausify the RHS p = LFSCClausify::Make( form[0], p.get() ); //cascadeOr? p = LFSCAssume::Make( queryM( ec[1] ), p.get() ); return LFSCAssume::Make( m, p.get() ); } break; } } else if( reason==d_or_mid_s ) { ostringstream os1, os2; if( form[pos].isNot() ) os1 << "(not_not_elim _ "; os1 << "(or_elim" << ( (pos==form.arity()) ? "_end" : "" ); os1 << " _ _ " << pos << " "; os2 << ")"; if( form[pos].isNot() ) os2 << ")"; p = LFSCPfVar::Make( "@v", abs( m ) ); p = LFSCProofGeneric::Make( os1.str(), p.get(), os2.str() ); Expr ea = Expr( NOT, form[pos] ); p = LFSCClausify::Make( ea, p.get() ); return LFSCAssume::Make( m, p.get(), false ); } else if( reason==d_and_mid_s ) { //make a proof of the pos-th statement p = LFSCPfVar::Make( "@v", abs( m ) ); p = LFSCProof::Make_and_elim( form, p.get(), pos, form[pos] ); p = LFSCClausify::Make( form[pos], p.get() ); return LFSCAssume::Make( m, p.get() ); } } ostringstream ose; ose << "CNF, " << reason << " unknown position = " << pos << std::endl; print_error( ose.str().c_str(), cout ); return NULL; }
bool expr_depends_on_var(Expr e, string v) { ExprDependsOnVar depends(v); e.accept(&depends); return depends.result; }
int main(int argc, char** argv) { try { MPISession::init(&argc, (void***)&argv); Expr::showAllParens() = true; Expr x = new CoordExpr(0); Expr y = new CoordExpr(1); Expr z = new CoordExpr(2); Expr dx = new Derivative(0); int ndim = 2; int order = 2; SpectralBasis SB = new HermiteSpectralBasis(ndim, order); Expr u = new UnknownFunctionStub("u", SB); Expr v = new TestFunctionStub("v", SB); Expr w = new UnknownFunctionStub("w", SB); Array<Expr> Ex1(6); Ex1[0] = 1.0; Ex1[1] = x; Ex1[2] = 0.0; Ex1[3] = x*y; Ex1[4] = x+y; Ex1[5] = y; Expr SE1 = new SpectralExpr(SB, Ex1); Array<Expr> Ex2(6); Ex2[0] = -3.0*x; Ex2[1] = 0.0; Ex2[2] = -y; Ex2[3] = x-y; Ex2[4] = -4.0*y + 2.0*x; Ex2[5] = 0.0; Expr SE2 = new SpectralExpr(SB, Ex2); Expr G = x*x; Expr Sum = (dx*v) * (dx*u) + v*x; Handle<CellFilterStub> domain = rcp(new CellFilterStub()); Handle<QuadratureFamilyStub> quad = rcp(new QuadratureFamilyStub(1)); Expr eqn = Integral(domain, Sum, quad); const SpectralExpr* se = dynamic_cast<const SpectralExpr*>(Sum.ptr().get()); if (se != 0) { SpectralBasis basis = se->getSpectralBasis(); for(int i=0; i< basis.nterms(); i++) cout << se->getCoeff(i) << std::endl; } cout << Sum << std::endl << std::endl; cout << eqn << std::endl << std::endl; } catch(std::exception& e) { std::cerr << e.what() << std::endl; } MPISession::finalize(); }
bool is_negative_negatable_const(Expr e) { return is_negative_negatable_const(e, e.type()); }
/// Emit logic to print the specified expression value with the given /// description of the pattern involved. void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) { // Always print rvalues, not lvalues. E = TC.coerceToMaterializable(E); SourceLoc Loc = E->getStartLoc(); SourceLoc EndLoc = E->getEndLoc(); // Require a non-trivial set of print functions. if (requirePrintDecls()) return; TopLevelCodeDecl *newTopLevel = new (Context) TopLevelCodeDecl(&SF); // Build function of type T->() which prints the operand. auto *Arg = new (Context) ParamDecl(/*isLet=*/true, SourceLoc(), SourceLoc(), Identifier(), Loc, Context.getIdentifier("arg"), E->getType(), /*DC*/ newTopLevel); auto params = ParameterList::createWithoutLoc(Arg); unsigned discriminator = TLC.claimNextClosureDiscriminator(); ClosureExpr *CE = new (Context) ClosureExpr(params, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(), discriminator, newTopLevel); CE->setType(ParameterList::getFullType(TupleType::getEmpty(Context), params)); // Convert the pattern to a string we can print. llvm::SmallString<16> PrefixString; PrefixString += "// "; PrefixString += NameStr; PrefixString += " : "; PrefixString += E->getType()->getWithoutParens()->getString(); PrefixString += " = "; // Unique the type string into an identifier since PrintLiteralString is // building an AST around the string that must persist beyond the lifetime of // PrefixString. auto TmpStr = Context.getIdentifier(PrefixString).str(); StmtBuilder builder(*this, CE); builder.printLiteralString(TmpStr, Loc); builder.printReplExpr(Arg, Loc); // Typecheck the function. BraceStmt *Body = builder.createBodyStmt(Loc, EndLoc); CE->setBody(Body, false); TC.typeCheckClosureBody(CE); // If the caller didn't wrap the argument in parentheses or make it a tuple, // add the extra parentheses now. Expr *TheArg = E; Type Ty = ParenType::get(TC.Context, TheArg->getType()); TheArg = new (TC.Context) ParenExpr(SourceLoc(), TheArg, SourceLoc(), false, Ty); Expr *TheCall = new (Context) CallExpr(CE, TheArg, /*Implicit=*/true); if (TC.typeCheckExpressionShallow(TheCall, Arg->getDeclContext())) return ; // Inject the call into the top level stream by wrapping it with a TLCD. auto *BS = BraceStmt::create(Context, Loc, ASTNode(TheCall), EndLoc); newTopLevel->setBody(BS); TC.checkTopLevelErrorHandling(newTopLevel); SF.Decls.push_back(newTopLevel); }
bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, ObjCMethodDecl *Method, bool isClassMessage, SourceLocation lbrac, SourceLocation rbrac, QualType &ReturnType, ExprValueKind &VK) { if (!Method) { // Apply default argument promotion as for (C99 6.5.2.2p6). for (unsigned i = 0; i != NumArgs; i++) { if (Args[i]->isTypeDependent()) continue; DefaultArgumentPromotion(Args[i]); } unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : diag::warn_inst_method_not_found; Diag(lbrac, DiagID) << Sel << isClassMessage << SourceRange(lbrac, rbrac); ReturnType = Context.getObjCIdType(); VK = VK_RValue; return false; } ReturnType = Method->getSendResultType(); VK = Expr::getValueKindForType(Method->getResultType()); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due // to addition of c-style arguments in method. if (Method->param_size() > Sel.getNumArgs()) NumNamedArgs = Method->param_size(); // FIXME. This need be cleaned up. if (NumArgs < NumNamedArgs) { Diag(lbrac, diag::err_typecheck_call_too_few_args) << 2 << NumNamedArgs << NumArgs; return false; } bool IsError = false; for (unsigned i = 0; i < NumNamedArgs; i++) { // We can't do any type-checking on a type-dependent argument. if (Args[i]->isTypeDependent()) continue; Expr *argExpr = Args[i]; ParmVarDecl *Param = Method->param_begin()[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); if (RequireCompleteType(argExpr->getSourceRange().getBegin(), Param->getType(), PDiag(diag::err_call_incomplete_argument) << argExpr->getSourceRange())) return true; InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, Param); ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr)); if (ArgE.isInvalid()) IsError = true; else Args[i] = ArgE.takeAs<Expr>(); } // Promote additional arguments to variadic methods. if (Method->isVariadic()) { for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { if (Args[i]->isTypeDependent()) continue; IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); } } else { // Check for extra arguments to non-variadic methods. if (NumArgs != NumNamedArgs) { Diag(Args[NumNamedArgs]->getLocStart(), diag::err_typecheck_call_too_many_args) << 2 /*method*/ << NumNamedArgs << NumArgs << Method->getSourceRange() << SourceRange(Args[NumNamedArgs]->getLocStart(), Args[NumArgs-1]->getLocEnd()); } } DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); return IsError; }
void IRMutator::visit(const Not *op) { Expr a = mutate(op->a); if (a.same_as(op->a)) expr = op; else expr = Not::make(a); }
void IRMutator::visit(const Broadcast *op) { Expr value = mutate(op->value); if (value.same_as(op->value)) expr = op; else expr = Broadcast::make(value, op->width); }
int main(int argc, char** argv) { try { const double pi = 4.0*atan(1.0); double lambda = 1.25*pi*pi; int nx = 32; int nt = 10; double tFinal = 1.0/lambda; Sundance::setOption("nx", nx, "Number of elements"); Sundance::setOption("nt", nt, "Number of timesteps"); Sundance::setOption("tFinal", tFinal, "Final time"); Sundance::init(&argc, &argv); /* Creation of vector type */ VectorType<double> vecType = new EpetraVectorType(); /* Set up mesh */ MeshType meshType = new BasicSimplicialMeshType(); MeshSource meshSrc = new PartitionedRectangleMesher( 0.0, 1.0, nx, 0.0, 1.0, nx, meshType); Mesh mesh = meshSrc.getMesh(); /* * Specification of cell filters */ CellFilter interior = new MaximalCellFilter(); CellFilter edges = new DimensionalCellFilter(1); CellFilter west = edges.coordSubset(0, 0.0); CellFilter east = edges.coordSubset(0, 1.0); CellFilter south = edges.coordSubset(1, 0.0); CellFilter north = edges.coordSubset(1, 1.0); /* set up test and unknown functions */ BasisFamily basis = new Lagrange(1); Expr u = new UnknownFunction(basis, "u"); Expr v = new TestFunction(basis, "v"); /* set up differential operators */ Expr grad = gradient(2); Expr x = new CoordExpr(0); Expr y = new CoordExpr(1); Expr t = new Sundance::Parameter(0.0); Expr tPrev = new Sundance::Parameter(0.0); DiscreteSpace discSpace(mesh, basis, vecType); Expr uExact = cos(0.5*pi*y)*sin(pi*x)*exp(-lambda*t); L2Projector proj(discSpace, uExact); Expr uPrev = proj.project(); /* * We need a quadrature rule for doing the integrations */ QuadratureFamily quad = new GaussianQuadrature(2); double deltaT = tFinal/nt; Expr gWest = -pi*exp(-lambda*t)*cos(0.5*pi*y); Expr gWestPrev = -pi*exp(-lambda*tPrev)*cos(0.5*pi*y); /* Create the weak form */ Expr eqn = Integral(interior, v*(u-uPrev)/deltaT + 0.5*(grad*v)*(grad*u + grad*uPrev), quad) + Integral(west, -0.5*v*(gWest+gWestPrev), quad); Expr bc = EssentialBC(east + north, v*u, quad); LinearProblem prob(mesh, eqn, bc, v, u, vecType); LinearSolver<double> solver = LinearSolverBuilder::createSolver("amesos.xml"); FieldWriter w0 = new VTKWriter("TransientHeat2D-0"); w0.addMesh(mesh); w0.addField("T", new ExprFieldWrapper(uPrev[0])); w0.write(); for (int i=0; i<nt; i++) { t.setParameterValue((i+1)*deltaT); tPrev.setParameterValue(i*deltaT); Out::root() << "t=" << (i+1)*deltaT << endl; Expr uNext = prob.solve(solver); ostringstream oss; oss << "TransientHeat2D-" << i+1; FieldWriter w = new VTKWriter(oss.str()); w.addMesh(mesh); w.addField("T", new ExprFieldWrapper(uNext[0])); w.write(); updateDiscreteFunction(uNext, uPrev); } double err = L2Norm(mesh, interior, uExact-uPrev, quad); Out::root() << "error norm=" << err << endl; double h = 1.0/(nx-1.0); double tol = 0.1*(pow(h,2.0) + pow(lambda*deltaT, 2.0)); Out::root() << "tol=" << tol << endl; Sundance::passFailTest(err, tol); } catch(std::exception& e) { Sundance::handleException(e); } Sundance::finalize(); return Sundance::testStatus(); }
/// \brief Figure out if an expression could be turned into a call. /// /// Use this when trying to recover from an error where the programmer may have /// written just the name of a function instead of actually calling it. /// /// \param E - The expression to examine. /// \param ZeroArgCallReturnTy - If the expression can be turned into a call /// with no arguments, this parameter is set to the type returned by such a /// call; otherwise, it is set to an empty QualType. /// \param OverloadSet - If the expression is an overloaded function /// name, this parameter is populated with the decls of the various overloads. bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, UnresolvedSetImpl &OverloadSet) { ZeroArgCallReturnTy = QualType(); OverloadSet.clear(); if (E.getType() == Context.OverloadTy) { OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E)); const OverloadExpr *Overloads = FR.Expression; for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { OverloadSet.addDecl(*it); // Check whether the function is a non-template which takes no // arguments. if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) { if (OverloadDecl->getMinRequiredArguments() == 0) ZeroArgCallReturnTy = OverloadDecl->getResultType(); } } // Ignore overloads that are pointer-to-member constants. if (FR.HasFormOfMemberPointer) return false; return true; } if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) { if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { if (Fun->getMinRequiredArguments() == 0) ZeroArgCallReturnTy = Fun->getResultType(); return true; } } // We don't have an expression that's convenient to get a FunctionDecl from, // but we can at least check if the type is "function of 0 arguments". QualType ExprTy = E.getType(); const FunctionType *FunTy = NULL; QualType PointeeTy = ExprTy->getPointeeType(); if (!PointeeTy.isNull()) FunTy = PointeeTy->getAs<FunctionType>(); if (!FunTy) FunTy = ExprTy->getAs<FunctionType>(); if (!FunTy && ExprTy == Context.BoundMemberTy) { // Look for the bound-member type. If it's still overloaded, give up, // although we probably should have fallen into the OverloadExpr case above // if we actually have an overloaded bound member. QualType BoundMemberTy = Expr::findBoundMemberType(&E); if (!BoundMemberTy.isNull()) FunTy = BoundMemberTy->castAs<FunctionType>(); } if (const FunctionProtoType *FPT = dyn_cast_or_null<FunctionProtoType>(FunTy)) { if (FPT->getNumArgs() == 0) ZeroArgCallReturnTy = FunTy->getResultType(); return true; } return false; }
void match_types(Expr &a, Expr &b) { user_assert(!a.type().is_handle() && !b.type().is_handle()) << "Can't do arithmetic on opaque pointer types\n"; if (a.type() == b.type()) return; // First widen to match if (a.type().is_scalar() && b.type().is_vector()) { a = Broadcast::make(a, b.type().lanes()); } else if (a.type().is_vector() && b.type().is_scalar()) { b = Broadcast::make(b, a.type().lanes()); } else { internal_assert(a.type().lanes() == b.type().lanes()) << "Can't match types of differing widths"; } Type ta = a.type(), tb = b.type(); // If type widening has made the types match no additional casts are needed if (ta == tb) return; if (!ta.is_float() && tb.is_float()) { // int(a) * float(b) -> float(b) // uint(a) * float(b) -> float(b) a = cast(tb, a); } else if (ta.is_float() && !tb.is_float()) { b = cast(ta, b); } else if (ta.is_float() && tb.is_float()) { // float(a) * float(b) -> float(max(a, b)) if (ta.bits() > tb.bits()) b = cast(ta, b); else a = cast(tb, a); } else if (ta.is_uint() && tb.is_uint()) { // uint(a) * uint(b) -> uint(max(a, b)) if (ta.bits() > tb.bits()) b = cast(ta, b); else a = cast(tb, a); } else if (!ta.is_float() && !tb.is_float()) { // int(a) * (u)int(b) -> int(max(a, b)) int bits = std::max(ta.bits(), tb.bits()); int lanes = a.type().lanes(); a = cast(Int(bits, lanes), a); b = cast(Int(bits, lanes), b); } else { internal_error << "Could not match types: " << ta << ", " << tb << "\n"; } }
inline Sacado::ELRFad::GeneralFad<T,Storage>::GeneralFad(const Expr<S>& x) : Storage(T(0.)), update_val_(x.updateValue()) { int sz = x.size(); if (sz != this->size()) this->resize(sz); if (sz) { if (Expr<S>::is_linear) { if (x.hasFastAccess()) for(int i=0; i<sz; ++i) this->fastAccessDx(i) = x.fastAccessDx(i); else for(int i=0; i<sz; ++i) this->fastAccessDx(i) = x.dx(i); } else { // Number of arguments const int N = Expr<S>::num_args; if (x.hasFastAccess()) { // Compute partials FastLocalAccumOp< Expr<S> > op(x); // Compute each tangent direction for(op.i=0; op.i<sz; ++op.i) { op.t = T(0.); // Automatically unrolled loop that computes // for (int j=0; j<N; j++) // op.t += op.partials[j] * x.getTangent<j>(i); Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op); this->fastAccessDx(op.i) = op.t; } } else { // Compute partials SlowLocalAccumOp< Expr<S> > op(x); // Compute each tangent direction for(op.i=0; op.i<sz; ++op.i) { op.t = T(0.); // Automatically unrolled loop that computes // for (int j=0; j<N; j++) // op.t += op.partials[j] * x.getTangent<j>(i); Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op); this->fastAccessDx(op.i) = op.t; } } } } // Compute value if (update_val_) this->val() = x.val(); }
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (!D->getDescribedFunctionTemplate() && !D->isFunctionTemplateSpecialization()) prettyPrintPragmas(D); if (D->isFunctionTemplateSpecialization()) Out << "template<> "; CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D); CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D); if (!Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; case SC_Extern: Out << "extern "; break; case SC_Static: Out << "static "; break; case SC_PrivateExtern: Out << "__private_extern__ "; break; case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions"); } if (D->isInlineSpecified()) Out << "inline "; if (D->isVirtualAsWritten()) Out << "virtual "; if (D->isModulePrivate()) Out << "__module_private__ "; if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr "; if ((CDecl && CDecl->isExplicitSpecified()) || (ConversionDecl && ConversionDecl->isExplicit())) Out << "explicit "; } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { llvm::raw_string_ostream POut(Proto); DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); TArgPrinter.printTemplateArguments(*TArgs); } QualType Ty = D->getType(); while (const ParenType *PT = dyn_cast<ParenType>(Ty)) { Proto = '(' + Proto + ')'; Ty = PT->getInnerType(); } prettyPrintAttributes(D); if (const FunctionType *AFT = Ty->getAs<FunctionType>()) { const FunctionProtoType *FT = nullptr; if (D->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(AFT); Proto += "("; if (FT) { llvm::raw_string_ostream POut(Proto); DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) POut << ", "; ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); } if (FT->isVariadic()) { if (D->getNumParams()) POut << ", "; POut << "..."; } } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) Proto += ", "; Proto += D->getParamDecl(i)->getNameAsString(); } } Proto += ")"; if (FT) { if (FT->isConst()) Proto += " const"; if (FT->isVolatile()) Proto += " volatile"; if (FT->isRestrict()) Proto += " restrict"; switch (FT->getRefQualifier()) { case RQ_None: break; case RQ_LValue: Proto += " &"; break; case RQ_RValue: Proto += " &&"; break; } } if (FT && FT->hasDynamicExceptionSpec()) { Proto += " throw("; if (FT->getExceptionSpecType() == EST_MSAny) Proto += "..."; else for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { if (I) Proto += ", "; Proto += FT->getExceptionType(I).getAsString(SubPolicy); } Proto += ")"; } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { Proto += " noexcept"; if (FT->getExceptionSpecType() == EST_ComputedNoexcept) { Proto += "("; llvm::raw_string_ostream EOut(Proto); FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy, Indentation); EOut.flush(); Proto += EOut.str(); Proto += ")"; } } if (CDecl) { bool HasInitializerList = false; for (const auto *BMInitializer : CDecl->inits()) { if (BMInitializer->isInClassMemberInitializer()) continue; if (!HasInitializerList) { Proto += " : "; Out << Proto; Proto.clear(); HasInitializerList = true; } else Out << ", "; if (BMInitializer->isAnyMemberInitializer()) { FieldDecl *FD = BMInitializer->getAnyMember(); Out << *FD; } else { Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy); } Out << "("; if (!BMInitializer->getInit()) { // Nothing to print } else { Expr *Init = BMInitializer->getInit(); if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init)) Init = Tmp->getSubExpr(); Init = Init->IgnoreParens(); Expr *SimpleInit = nullptr; Expr **Args = nullptr; unsigned NumArgs = 0; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); } else if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { Args = Construct->getArgs(); NumArgs = Construct->getNumArgs(); } else SimpleInit = Init; if (SimpleInit) SimpleInit->printPretty(Out, nullptr, Policy, Indentation); else { for (unsigned I = 0; I != NumArgs; ++I) { assert(Args[I] != nullptr && "Expected non-null Expr"); if (isa<CXXDefaultArgExpr>(Args[I])) break; if (I) Out << ", "; Args[I]->printPretty(Out, nullptr, Policy, Indentation); } } } Out << ")"; if (BMInitializer->isPackExpansion()) Out << "..."; } } else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) { if (FT && FT->hasTrailingReturn()) { Out << "auto " << Proto << " -> "; Proto.clear(); } AFT->getReturnType().print(Out, Policy, Proto); Proto.clear(); } Out << Proto; } else { Ty.print(Out, Policy, Proto); } if (D->isPure()) Out << " = 0"; else if (D->isDeletedAsWritten()) Out << " = delete"; else if (D->isExplicitlyDefaulted()) Out << " = default"; else if (D->doesThisDeclarationHaveABody()) { if (!Policy.TerseOutput) { if (!D->hasPrototype() && D->getNumParams()) { // This is a K&R function definition, so we need to print the // parameters. Out << '\n'; DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); Indentation += Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); Out << ";\n"; } Indentation -= Policy.Indentation; } else Out << ' '; if (D->getBody()) D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation); } else { if (isa<CXXConstructorDecl>(*D)) Out << " {}"; } } }
pair<int, int> ModulusRemainder::analyze(Expr e) { e.accept(this); return make_pair(modulus, remainder); }
void DeclPrinter::VisitVarDecl(VarDecl *D) { prettyPrintPragmas(D); QualType T = D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() : D->getASTContext().getUnqualifiedObjCPointerType(D->getType()); if (!Policy.SuppressSpecifiers) { StorageClass SC = D->getStorageClass(); if (SC != SC_None) Out << VarDecl::getStorageClassSpecifierString(SC) << " "; switch (D->getTSCSpec()) { case TSCS_unspecified: break; case TSCS___thread: Out << "__thread "; break; case TSCS__Thread_local: Out << "_Thread_local "; break; case TSCS_thread_local: Out << "thread_local "; break; } if (D->isModulePrivate()) Out << "__module_private__ "; if (D->isConstexpr()) { Out << "constexpr "; T.removeLocalConst(); } } printDeclType(T, D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) { if (D->getInitStyle() == VarDecl::CallInit && !Construct->isListInitialization()) { ImplicitInit = Construct->getNumArgs() == 0 || Construct->getArg(0)->isDefaultArgument(); } } if (!ImplicitInit) { if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) Out << "("; else if (D->getInitStyle() == VarDecl::CInit) { Out << " = "; } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; SubPolicy.IncludeTagDefinition = false; Init->printPretty(Out, nullptr, SubPolicy, Indentation); if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init)) Out << ")"; } } prettyPrintAttributes(D); }
bool X86General::Finalize(Bytecode& bc, DiagnosticsEngine& diags) { if (m_ea) { if (!m_ea->Finalize(diags)) return false; } if (m_imm.get() != 0) { if (!m_imm->Finalize(diags, diag::err_imm_too_complex)) return false; } if (m_postop == X86_POSTOP_ADDRESS16 && m_common.m_addrsize != 0) { diags.Report(bc.getSource(), diag::warn_address_size_ignored); m_common.m_addrsize = 0; } // Handle non-span-dependent post-ops here switch (m_postop) { case X86_POSTOP_SHORT_MOV: { // Long (modrm+sib) mov instructions in amd64 can be optimized into // short mov instructions if a 32-bit address override is applied in // 64-bit mode to an EA of just an offset (no registers) and the // target register is al/ax/eax/rax. // // We don't want to do this if we're in default rel mode. Expr* abs; if (!m_default_rel && m_common.m_mode_bits == 64 && m_common.m_addrsize == 32 && (!(abs = m_ea->m_disp.getAbs()) || !abs->Contains(ExprTerm::REG))) { m_ea->setDispOnly(); // Make the short form permanent. m_opcode.MakeAlt1(); } m_postop = X86_POSTOP_NONE; break; } case X86_POSTOP_SIMM32_AVAIL: { // Used for 64-bit mov immediate, which can take a sign-extended // imm32 as well as imm64 values. The imm32 form is put in the // second byte of the opcode and its ModRM byte is put in the third // byte of the opcode. Expr* abs; if (!(abs = m_imm->getAbs()) || (m_imm->getAbs()->isIntNum() && m_imm->getAbs()->getIntNum().isOkSize(32, 0, 1))) { // Throwaway REX byte unsigned char rex_temp = 0; // Build ModRM EA - CAUTION: this depends on // opcode 0 being a mov instruction! m_ea.reset(new X86EffAddr()); if (!m_ea->setReg(X86RegTmod::Instance(). getReg(X86Register::REG64, m_opcode.get(0)-0xB8), &rex_temp, 64)) { diags.Report(m_ea->m_disp.getSource().getBegin(), diag::err_high8_rex_conflict); return false; } // Make the imm32s form permanent. m_opcode.MakeAlt1(); m_imm->setSize(32); m_imm->setSigned(); } m_postop = X86_POSTOP_NONE; break; } default: break; } return true; }
size_t count(Expr expr) { indexVars.clear(); expr.accept(this); return indexVars.size(); }
bool constant_expr_equals(Expr expr, T expected) { return (expr.type() == type_of<T>() && is_one(simplify(expr == Expr(expected)))); }
void updateBlocked(Expr expr) { Type type = expr.type(); if (type.isTensor() && !isScalar(type.toTensor()->getBlockType())) { isBlocked = true; } }
Expr *TransformVector::ConvertAssignExpr(DeclVector &DeclVec, ExtVectorElementExpr *LHS, BinaryOperator::Opcode Op, Expr *BRHS) { QualType BRHSTy = BRHS->getType(); Expr *RHS = BRHS->IgnoreParenCasts(); if (!(isa<CompoundLiteralExpr>(RHS) || isa<ExtVectorElementExpr>(RHS))) { RHS = ConvertVecLiteralInExpr(DeclVec, RHS); QualType RHSTy = RHS->getType(); if (RHSTy->isVectorType() && !isa<DeclRefExpr>(RHS)) { // Make a VarDecl with RHS VarDecl *VD = NewVecLiteralVarDecl(BRHSTy); VD->setInit(RHS); DeclVec.push_back(VD); // Make a DeclRefExpr SourceLocation loc; RHS = new (ASTCtx) DeclRefExpr(VD, BRHSTy, VK_RValue, loc); } } ExprVector LHSVec; MakeElementExprs(DeclVec, LHSVec, LHS); assert((LHSVec.size() > 0) && "Wrong element exprs"); bool IsScalarRHS = RHS->getType()->isScalarType(); if (LHSVec.size() == 1 && IsScalarRHS) { return NewBinaryOperator(LHSVec[0], Op, RHS); } Expr *NewExpr = 0; if (IsScalarRHS) { // scalar RHS for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, RHS); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else if (CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(RHS)) { unsigned NumElems = LHSVec.size(); Expr **Args = new (ASTCtx) Expr*[NumElems]; TransformVectorLiteralExpr(CLE, Args, 0); for (unsigned i = 0; i < NumElems; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, Args[i]); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else if (ExtVectorElementExpr *EE = dyn_cast<ExtVectorElementExpr>(RHS)) { ExprVector RHSVec; MakeElementExprs(DeclVec, RHSVec, EE); assert((LHSVec.size() == RHSVec.size()) && "Different LHS and RHS?"); for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, RHSVec[i]); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } else { // vector RHS for (unsigned i = 0, e = LHSVec.size(); i < e; i++) { QualType Ty = LHSVec[i]->getType(); // RHS[i] ArraySubscriptExpr *ElemRHS = new (ASTCtx) ArraySubscriptExpr( RHS, CLExprs.getExpr((CLExpressions::ExprKind)(CLExpressions::ZERO + i)), Ty, VK_RValue, OK_Ordinary, SourceLocation()); Expr *OneExpr = NewBinaryOperator(LHSVec[i], Op, ElemRHS); if (NewExpr) { NewExpr = NewBinaryOperator(NewExpr, BO_Comma, OneExpr); } else { NewExpr = OneExpr; } } } return NewExpr; }
std::vector<IndexVar> get(Expr expr) { expr.accept(this); return indexVars; }
void translate_to_redlog(const map<Expr, unsigned>& variables, const Expr& assertion) { bool first; unsigned n = assertion.getNumChildren(); if (n == 0) { if (assertion.isConst()) { if (assertion.getConst<bool>()) { cout << "(1 > 0)"; } else { cout << "(1 < 0)"; } } else { assert(false); } } else { std::string op; bool binary = false; bool theory = false; switch (assertion.getKind()) { case kind::NOT: cout << "(not "; translate_to_redlog(variables, assertion[0]); cout << ")"; break; case kind::OR: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " or "; } first = false; translate_to_redlog(variables, assertion[i]); } cout << ")"; break; case kind::AND: first = true; cout << "("; for (unsigned i = 0; i < n; ++ i) { if (!first) { cout << " and "; } first = false; translate_to_redlog(variables, assertion[i]); } cout << ")"; break; case kind::IMPLIES: cout << "("; translate_to_redlog(variables, assertion[0]); cout << " impl "; translate_to_redlog(variables, assertion[1]); cout << ")"; break; case kind::IFF: cout << "("; translate_to_redlog(variables, assertion[0]); cout << " equiv "; translate_to_redlog(variables, assertion[1]); cout << ")"; break; case kind::EQUAL: op = "="; theory = true; break; case kind::LT: op = "<"; theory = true; break; case kind::LEQ: op = "<="; theory = true; break; case kind::GT: op = ">"; theory = true; break; case kind::GEQ: op = ">="; theory = true; break; default: assert(false); break; } if (binary) { cout << "("; translate_to_redlog(variables, assertion[0]); cout << " " << op << " "; translate_to_redlog(variables, assertion[1]); cout << ")"; } if (theory) { cout << "("; translate_to_redlog_term(variables, assertion[0]); cout << " " << op << " "; translate_to_redlog_term(variables, assertion[1]); cout << ")"; } } }
void CheckAllocationsInFunctionVisitor::VisitAllocate( const A0& getArg0, const A1& getArg1, const T& getAllocType) { const Expr* firstArgNode = getArg0(); // Check if the first argument (to new or AllocateArray) is a static cast // AllocatorNew/AllocateArray in Chakra always does a static_cast to the AllocatorType const CXXStaticCastExpr* castNode = nullptr; if (firstArgNode != nullptr && (castNode = dyn_cast<CXXStaticCastExpr>(firstArgNode))) { QualType allocatedType = getAllocType(); string allocatedTypeStr = allocatedType.getAsString(); auto allocationType = CheckAllocationType(castNode); if (allocationType == AllocationTypes::Recycler) // Recycler allocation { const Expr* secondArgNode = getArg1(); // Chakra has two types of allocating functions- throwing and non-throwing // However, recycler allocations are always throwing, so the second parameter // should be the address of the allocator function auto unaryNode = cast<UnaryOperator>(secondArgNode); if (unaryNode != nullptr && unaryNode->getOpcode() == UnaryOperatorKind::UO_AddrOf) { Expr* subExpr = unaryNode->getSubExpr(); if (DeclRefExpr* declRef = cast<DeclRefExpr>(subExpr)) { auto declNameInfo = declRef->getNameInfo(); auto allocationFunctionStr = declNameInfo.getName().getAsString(); _mainVisitor->RecordRecyclerAllocation(allocationFunctionStr, allocatedTypeStr); if (!Contains(allocationFunctionStr, "Leaf")) { // Recycler write barrier allocation -- unless "Leaf" in allocFunc allocationType = AllocationTypes::RecyclerWriteBarrier; } } else { Log::errs() << "ERROR: (internal) Expected DeclRefExpr:\n"; subExpr->dump(); } } else if (auto mExpr = cast<MaterializeTemporaryExpr>(secondArgNode)) { auto name = mExpr->GetTemporaryExpr()->IgnoreImpCasts()->getType().getAsString(); if (StartsWith(name, "InfoBitsWrapper<")) // && Contains(name, "WithBarrierBit")) { // RecyclerNewEnumClass, RecyclerNewWithInfoBits -- always have WithBarrier varients allocationType = AllocationTypes::RecyclerWriteBarrier; } } else { Log::errs() << "ERROR: (internal) Expected unary node or MaterializeTemporaryExpr:\n"; secondArgNode->dump(); } } if (allocationType & AllocationTypes::WriteBarrier) { Log::outs() << "In \"" << _functionDecl->getQualifiedNameAsString() << "\"\n"; Log::outs() << " Allocating \"" << allocatedTypeStr << "\" in write barriered memory\n"; } _mainVisitor->RecordAllocation(allocatedType, allocationType); } }
DerivSet SymbPreprocessor::setupVariations(const Expr& expr, const Expr& vars, const Expr& varEvalPts, const Expr& unks, const Expr& unkEvalPts, const Expr& unkParams, const Expr& unkParamEvalPts, const Expr& fixedFields, const Expr& fixedFieldEvalPts, const Expr& fixedParams, const Expr& fixedParamEvalPts, const EvalContext& context, const ComputationType& compType) { TimeMonitor t(preprocTimer()); Tabs tab; const EvaluatableExpr* e = dynamic_cast<const EvaluatableExpr*>(expr.ptr().get()); Array<Set<MultiSet<int> > > funcDerivs(3); Array<Set<MultiIndex> > spatialDerivs(3); int verb=context.setupVerbosity(); SUNDANCE_BANNER1(verb, tab, "in setupVariations()"); verbosity<EvaluatableExpr>() = verb; SUNDANCE_MSG1(verb, tab << "************ setting up variations of expr: " << expr << std::endl << tab << "context is " << context << std::endl << tab << "conp type is " << compType << std::endl << tab << "vars are " << vars << std::endl << tab << "unks are " << unks << std::endl << tab << "unk parameters " << unkParams << std::endl << tab << "fixed parameters " << fixedParams << std::endl << tab << "the eval points for the vars are " << varEvalPts << std::endl << tab << "the eval points for the unks are " << unkEvalPts << std::endl << tab << "the eval points for the unknown parameters are " << unkParamEvalPts << std::endl << tab << "the eval points for the fixed parameters are " << fixedParamEvalPts << tab << std::endl); TEUCHOS_TEST_FOR_EXCEPTION(e==0, std::logic_error, "Non-evaluatable expr " << expr.toString() << " given to SymbPreprocessor::setupExpr()"); /* make flat lists of variations, unknowns, parameters, and fixed fields */ Expr v = vars.flatten(); Expr v0 = varEvalPts.flatten(); Expr u = unks.flatten(); Expr u0 = unkEvalPts.flatten(); Expr alpha = unkParams.flatten(); Expr alpha0 = unkParamEvalPts.flatten(); Expr beta = fixedParams.flatten(); Expr beta0 = fixedParamEvalPts.flatten(); Expr f = fixedFields.flatten(); Expr f0 = fixedFieldEvalPts.flatten(); Set<int> varID = processInputFuncs<SymbolicFuncElement>(v, v0); Set<int> unkID = processInputFuncs<UnknownFuncElement>(u, u0); Set<int> fixedID = processInputFuncs<UnknownFuncElement>(f, f0); Set<int> unkParamID = processInputParams<UnknownParameterElement>(alpha, alpha0); Set<int> fixedParamID = processInputParams<UnknownParameterElement>(beta, beta0); /* put together the set of functions that are active differentiation * variables */ SUNDANCE_MSG2(verb, tab << "forming active set"); Array<Sundance::Set<MultiSet<int> > > activeFuncIDs(3); if (context.needsDerivOrder(0)) activeFuncIDs[0].put(MultiSet<int>()); if (context.topLevelDiffOrder() >= 1) { for (Set<int>::const_iterator i=varID.begin(); i != varID.end(); i++) { if (context.needsDerivOrder(1)) activeFuncIDs[1].put(makeMultiSet<int>(*i)); if (context.topLevelDiffOrder()==2) { for (Set<int>::const_iterator j=unkID.begin(); j != unkID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } if (compType==MatrixAndVector) { for (Set<int>::const_iterator j=unkParamID.begin(); j != unkParamID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } } else if (compType==Sensitivities) { for (Set<int>::const_iterator j=fixedParamID.begin(); j != fixedParamID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } } } } } SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Finding nonzeros for expr " << std::endl << tab); for (int i=0; i<=context.topLevelDiffOrder(); i++) { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "diff order=" << i << ", active funcs=" << activeFuncIDs[i]); } Set<MultiIndex> miSet; miSet.put(MultiIndex()); e->registerSpatialDerivs(context, miSet); SUNDANCE_MSG2(verb, tab << std::endl << tab << " ************* finding required functions" << std::endl << tab); SUNDANCE_MSG2(verb, tab << "activeFuncIDs are = " << activeFuncIDs); SUNDANCE_MSG2(verb, tab << "spatial derivs are = " << spatialDerivs); Array<Set<MultipleDeriv> > RInput = e->computeInputR(context, activeFuncIDs, spatialDerivs); SUNDANCE_MSG3(verb, tab << std::endl << tab << " ************* Top-level required funcs are " << RInput << std::endl << tab); SUNDANCE_MSG2(verb, tab << std::endl << tab << " ************* Calling determineR()" << std::endl << tab); e->determineR(context, RInput); SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Finding sparsity structure " << std::endl << tab); DerivSet derivs = e->sparsitySuperset(context)->derivSet(); SUNDANCE_MSG1(verb, tab << std::endl << tab << "Nonzero deriv set = " << derivs); SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Setting up evaluators for expr " << std::endl << tab); int saveVerb = context.setupVerbosity(); context.setSetupVerbosity(0); e->setupEval(context); if (verb>1) { SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Nonzeros are:"); e->displayNonzeros(Out::os(), context); } context.setSetupVerbosity(saveVerb); return derivs; }
void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred, ExplodedNodeSet &Dst) { Expr *LHS = B->getLHS()->IgnoreParens(); Expr *RHS = B->getRHS()->IgnoreParens(); // FIXME: Prechecks eventually go in ::Visit(). ExplodedNodeSet CheckedSet; ExplodedNodeSet Tmp2; getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); // With both the LHS and RHS evaluated, process the operation itself. for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end(); it != ei; ++it) { ProgramStateRef state = (*it)->getState(); const LocationContext *LCtx = (*it)->getLocationContext(); SVal LeftV = state->getSVal(LHS, LCtx); SVal RightV = state->getSVal(RHS, LCtx); BinaryOperator::Opcode Op = B->getOpcode(); if (Op == BO_Assign) { // EXPERIMENTAL: "Conjured" symbols. // FIXME: Handle structs. if (RightV.isUnknown()) { unsigned Count = currBldrCtx->blockCount(); RightV = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, Count); } // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. SVal ExprVal = B->isGLValue() ? LeftV : RightV; evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), LeftV, RightV); continue; } if (!B->isAssignmentOp()) { StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); if (B->isAdditiveOp()) { // If one of the operands is a location, conjure a symbol for the other // one (offset) if it's unknown so that memory arithmetic always // results in an ElementRegion. // TODO: This can be removed after we enable history tracking with // SymSymExpr. unsigned Count = currBldrCtx->blockCount(); if (LeftV.getAs<Loc>() && RHS->getType()->isIntegralOrEnumerationType() && RightV.isUnknown()) { RightV = svalBuilder.conjureSymbolVal(RHS, LCtx, RHS->getType(), Count); } if (RightV.getAs<Loc>() && LHS->getType()->isIntegralOrEnumerationType() && LeftV.isUnknown()) { LeftV = svalBuilder.conjureSymbolVal(LHS, LCtx, LHS->getType(), Count); } } // Process non-assignments except commas or short-circuited // logical expressions (LAnd and LOr). SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); if (Result.isUnknown()) { Bldr.generateNode(B, *it, state); continue; } state = state->BindExpr(B, LCtx, Result); Bldr.generateNode(B, *it, state); continue; } assert (B->isCompoundAssignmentOp()); switch (Op) { default: llvm_unreachable("Invalid opcode for compound assignment."); case BO_MulAssign: Op = BO_Mul; break; case BO_DivAssign: Op = BO_Div; break; case BO_RemAssign: Op = BO_Rem; break; case BO_AddAssign: Op = BO_Add; break; case BO_SubAssign: Op = BO_Sub; break; case BO_ShlAssign: Op = BO_Shl; break; case BO_ShrAssign: Op = BO_Shr; break; case BO_AndAssign: Op = BO_And; break; case BO_XorAssign: Op = BO_Xor; break; case BO_OrAssign: Op = BO_Or; break; } // Perform a load (the LHS). This performs the checks for // null dereferences, and so on. ExplodedNodeSet Tmp; SVal location = LeftV; evalLoad(Tmp, B, LHS, *it, state, location); for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { state = (*I)->getState(); const LocationContext *LCtx = (*I)->getLocationContext(); SVal V = state->getSVal(LHS, LCtx); // Get the computation type. QualType CTy = cast<CompoundAssignOperator>(B)->getComputationResultType(); CTy = getContext().getCanonicalType(CTy); QualType CLHSTy = cast<CompoundAssignOperator>(B)->getComputationLHSType(); CLHSTy = getContext().getCanonicalType(CLHSTy); QualType LTy = getContext().getCanonicalType(LHS->getType()); // Promote LHS. V = svalBuilder.evalCast(V, CLHSTy, LTy); // Compute the result of the operation. SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy), B->getType(), CTy); // EXPERIMENTAL: "Conjured" symbols. // FIXME: Handle structs. SVal LHSVal; if (Result.isUnknown()) { // The symbolic value is actually for the type of the left-hand side // expression, not the computation type, as this is the value the // LValue on the LHS will bind to. LHSVal = svalBuilder.conjureSymbolVal(0, B->getRHS(), LCtx, LTy, currBldrCtx->blockCount()); // However, we need to convert the symbol to the computation type. Result = svalBuilder.evalCast(LHSVal, CTy, LTy); } else { // The left-hand side may bind to a different value then the // computation type. LHSVal = svalBuilder.evalCast(Result, LTy, CTy); } // In C++, assignment and compound assignment operators return an // lvalue. if (B->isGLValue()) state = state->BindExpr(B, LCtx, location); else state = state->BindExpr(B, LCtx, Result); evalStore(Tmp2, B, LHS, *I, state, location, LHSVal); } } // FIXME: postvisits eventually go in ::Visit() getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); }