コード例 #1
0
ファイル: Parser.cpp プロジェクト: Eelis/klee
/// version-specifier = <identifier>
/// version-specifier = [<identifier>:] [ version ]
VersionResult ParserImpl::ParseVersionSpecifier() {
  const Identifier *Label = 0;
  if (Tok.kind == Token::Identifier) {
    Token LTok = Tok;
    Label = GetOrCreateIdentifier(Tok);
    ConsumeToken();

    if (Tok.kind != Token::Colon) {
      VersionSymTabTy::iterator it = VersionSymTab.find(Label);
      
      if (it == VersionSymTab.end()) {
        Error("invalid version reference.", LTok);
        return VersionResult(false, UpdateList(0, NULL));
      }

      return it->second;
    }

    ConsumeToken();
    if (VersionSymTab.count(Label)) {
      Error("duplicate update list label definition.", LTok);
      Label = 0;
    }
  }

  VersionResult Res = ParseVersion();
  // Define update list to avoid use-of-undef errors.
  if (!Res.isValid()) {
    Res = VersionResult(true, UpdateList(Array::CreateArray("", 0), NULL));
  }
  
  if (Label)
    VersionSymTab.insert(std::make_pair(Label, Res.get()));
  return Res;
}
コード例 #2
0
ファイル: Parser.cpp プロジェクト: Himeshi/klee
/// version - '[' update-list? ']' '@' version-specifier
/// update-list - empty
/// update-list - lhs '=' rhs [',' update-list]
VersionResult ParserImpl::ParseVersion() {
  if (Tok.kind != Token::LSquare)
    return VersionResult(false, UpdateList(0, NULL));
  
  std::vector<WriteInfo> Writes;
  ConsumeLSquare();
  for (;;) {
    Token LHSTok = Tok;
    NumberOrExprResult LHS = ParseNumberOrExpr();
    
    if (Tok.kind != Token::Equals) {
      Error("expected '='.", Tok);
      break;
    }
    
    ConsumeToken();
    Token RHSTok = Tok;
    NumberOrExprResult RHS = ParseNumberOrExpr();

    Writes.push_back(WriteInfo(LHS, RHS, LHSTok, RHSTok));
    
    if (Tok.kind == Token::Comma)
      ConsumeToken();
    else
      break;
  }
  ExpectRSquare("expected close of update list");

  VersionHandle Base(0, NULL);

  if (Tok.kind != Token::At) {
    Error("expected '@'.", Tok);
    return VersionResult(false, UpdateList(0, NULL));
  } 

  ConsumeExpectedToken(Token::At);

  VersionResult BaseRes = ParseVersionSpecifier();
  if (!BaseRes.isValid())
    return BaseRes;

  Base = BaseRes.get();

  Expr::Width ArrayDomainType = Expr::Int32;
  Expr::Width ArrayRangeType = Expr::Int8;

  for (std::vector<WriteInfo>::reverse_iterator it = Writes.rbegin(), 
         ie = Writes.rend(); it != ie; ++it) {
    const WriteInfo &WI = *it;
    ExprResult LHS, RHS;
    // FIXME: This can be factored into common helper for coercing a
    // NumberOrExpr into an Expr.
    if (WI.LHS.isNumber()) {
      LHS = ParseNumberToken(ArrayDomainType, WI.LHS.getNumber());
    } else {
      LHS = WI.LHS.getExpr();
      if (LHS.isValid() && LHS.get()->getWidth() != ArrayDomainType) {
        Error("invalid write index (doesn't match array domain).", WI.LHSTok);
        LHS = ExprResult();
      }
    }

    if (WI.RHS.isNumber()) {
      RHS = ParseNumberToken(ArrayRangeType, WI.RHS.getNumber());
    } else {
      RHS = WI.RHS.getExpr();
      if (RHS.isValid() && RHS.get()->getWidth() != ArrayRangeType) {
        Error("invalid write value (doesn't match array range).", WI.RHSTok);
        RHS = ExprResult();
      }
    }
    
    if (LHS.isValid() && RHS.isValid())
      Base.extend(LHS.get(), RHS.get());
  }

  return Base;
}
コード例 #3
0
ファイル: Parser.cpp プロジェクト: Himeshi/klee
ExprResult ParserImpl::ParseAnyReadParenExpr(const Token &Name,
                                             unsigned Kind,
                                             Expr::Width ResTy) {
  NumberOrExprResult Index = ParseNumberOrExpr();
  VersionResult Array = ParseVersionSpecifier();
  ExpectRParen("unexpected argument in read expression.");
  
  if (!Array.isValid())
    return Builder->Constant(0, ResTy);

  // FIXME: Need generic way to get array width. Needs to work with
  // anonymous arrays.
  Expr::Width ArrayDomainType = Expr::Int32;
  Expr::Width ArrayRangeType = Expr::Int8;

  // Coerce number to correct type.
  ExprResult IndexExpr;
  if (Index.isNumber())
    IndexExpr = ParseNumberToken(ArrayDomainType, Index.getNumber());
  else
    IndexExpr = Index.getExpr();
  
  if (!IndexExpr.isValid())
    return Builder->Constant(0, ResTy);
  else if (IndexExpr.get()->getWidth() != ArrayDomainType) {
    Error("index width does not match array domain.");
    return Builder->Constant(0, ResTy);
  }

  // FIXME: Check range width.

  switch (Kind) {
  default:
    assert(0 && "Invalid kind.");
    return Builder->Constant(0, ResTy);
  case eMacroKind_ReadLSB:
  case eMacroKind_ReadMSB: {
    unsigned NumReads = ResTy / ArrayRangeType;
    if (ResTy != NumReads*ArrayRangeType) {
      Error("invalid ordered read (not multiple of range type).", Name);
      return Builder->Constant(0, ResTy);
    }
    std::vector<ExprHandle> Kids(NumReads);
    ExprHandle Index = IndexExpr.get();
    for (unsigned i=0; i != NumReads; ++i) {
      // FIXME: We rely on folding here to not complicate things to where the
      // Read macro pattern fails to match.
      ExprHandle OffsetIndex = Index;
      if (i)
        OffsetIndex = AddExpr::create(OffsetIndex,
                                      Builder->Constant(i, ArrayDomainType));
      Kids[i] = Builder->Read(Array.get(), OffsetIndex);
    }
    if (Kind == eMacroKind_ReadLSB)
      std::reverse(Kids.begin(), Kids.end());
    // FIXME: Use builder!
    return ConcatExpr::createN(NumReads, &Kids[0]);
  }
  case Expr::Read:
    return Builder->Read(Array.get(), IndexExpr.get());
  }
}