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);
}
Example #2
0
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;
    }
  }  
}
Example #3
0
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;
}
Example #6
0
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;
}
Example #7
0
bool expr_depends_on_var(Expr e, string v) {
    ExprDependsOnVar depends(v);
    e.accept(&depends);
    return depends.result;
}
Example #8
0
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);
}
Example #11
0
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;
}
Example #12
0
void IRMutator::visit(const Not *op) {
    Expr a = mutate(op->a);
    if (a.same_as(op->a)) expr = op;
    else expr = Not::make(a);
}
Example #13
0
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();
}
Example #15
0
/// \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;
}
Example #16
0
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();
}
Example #18
0
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 << " {}";
    }
  }
}
Example #19
0
pair<int, int> ModulusRemainder::analyze(Expr e) {
    e.accept(this);
    return make_pair(modulus, remainder);
}
Example #20
0
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);
}
Example #21
0
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;
}
Example #22
0
 size_t count(Expr expr) {
   indexVars.clear();
   expr.accept(this);
   return indexVars.size();
 }
Example #23
0
bool constant_expr_equals(Expr expr, T expected) {
    return (expr.type() == type_of<T>() &&
            is_one(simplify(expr == Expr(expected))));
}
Example #24
0
 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;
}
Example #26
0
 std::vector<IndexVar> get(Expr expr) {
   expr.accept(this);
   return indexVars;
 }
Example #27
0
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 << ")";
    }      
  }  
}
Example #28
0
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);
}