Stmt *TransformVector::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
  unsigned NumElems = Node->getNumElements();
  if (NumElems == 0) {
    // array subscripting syntax
    Expr *ExprBase = TransformExpr(Node->getBase());
    ASTCtx.Deallocate(Node);
    return ExprBase;
  } else {
    DeclVector DeclVec;
    ExprVector ExprVec;
    MakeElementExprs(DeclVec, ExprVec, Node);
    assert((ExprVec.size() == NumElems) && "Wrong accessor?");
    if (DeclVec.size() > 0) {
      PushBackDeclStmts(*CurStmtVec, DeclVec);
    }

    if (NumElems == 1) {
      return ExprVec[0];
    } else {
      QualType NodeTy = Node->getType();
      CallExpr *NewExpr = new (ASTCtx) CallExpr(ASTCtx,
          CLExprs.getVectorLiteralExpr(NodeTy), ExprVec.data(), NumElems,
          NodeTy, VK_RValue, SourceLocation());
      return NewExpr;
    }
  }
}
Example #2
0
void ReduceArrayDim::handleOneArraySubscriptExpr(
       const ArraySubscriptExpr *ASE)
{
  const Type *ASETy = ASE->getType().getTypePtr();
  if (!ASETy->isScalarType() && !ASETy->isStructureType() && 
      !ASETy->isUnionType())
    return;

  ExprVector IdxExprs;
  const Expr *BaseE = getBaseExprAndIdxExprs(ASE, IdxExprs);
  TransAssert(BaseE && "Empty Base expression!");

  if (IdxExprs.size() <= 1)
    return;

  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseE);
  if (!DRE)
    return;

  const ValueDecl *OrigDecl = DRE->getDecl();
  const VarDecl *VD = dyn_cast<VarDecl>(OrigDecl);
  if (!VD)
    return;

  const VarDecl *CanonicalVD = VD->getCanonicalDecl();
  if (CanonicalVD != TheVarDecl)
    return;

  rewriteSubscriptExpr(IdxExprs); 
}
Example #3
0
void ReduceArraySize::handleOneASE(const ArraySubscriptExpr *ASE)
{
  const Type *ASETy = ASE->getType().getTypePtr();
  if (!ASETy->isScalarType() && !ASETy->isStructureType() && 
      !ASETy->isUnionType())
    return;
  
  ExprVector IdxExprs;
  const Expr *BaseE = getBaseExprAndIdxExprs(ASE, IdxExprs);
  TransAssert(BaseE && "Empty Base expression!");

  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseE);
  if (!DRE)
    return;

  const ValueDecl *OrigDecl = DRE->getDecl();
  const VarDecl *VD = dyn_cast<VarDecl>(OrigDecl);
  if (!VD)
    return;

  const VarDecl *CanonicalVD = VD->getCanonicalDecl();
  DimValueVector *DimVec = VarDeclToDim[CanonicalVD];
  // It's possible DimVec is NULL, e.g.,
  // int main(..., char *argv[]) {
  //  ... argv[1] ...
  // }
  if (!DimVec)
    return;

  TransAssert((DimVec->size() >= IdxExprs.size()) &&
              "More indices than it should be!");

  unsigned int DimIdx = 0;
  for (ExprVector::reverse_iterator I = IdxExprs.rbegin(), 
       E = IdxExprs.rend(); I != E; ++I) {

    int OldIdx = (*DimVec)[DimIdx];
    if (OldIdx == -1) {
      DimIdx++;
      continue;
    }

    const Expr *IdxE = (*I);
    if (isIntegerExpr(IdxE)) {
      int Idx = getIndexAsInteger(IdxE);
      if (Idx > OldIdx)
        (*DimVec)[DimIdx] = Idx;
    }
    else {
      (*DimVec)[DimIdx] = -1;
    }
    DimIdx++;
  }
}
Example #4
0
void Expression::SubstituteSlots(const ExprVector &slots)
{
	string functionName = FunctionName();
	if(functionName == "Slot")
	{
		IntegerType index;
		if(leaves.empty())
			index = 1;
		else
		{
			//MachineInteger *indexInt = leaves.at(0)->MachineIntegerHead();
			Integer *indexInt(dynamic_cast<Integer*>(leaves.at(0)->NumberHead()));
			if(indexInt)
				index = indexInt->IntValue();
			else
				throw EvaluateException("Slot expected to have an Integer argument.");
		}
		Expression *slot;
		if(index > 0 && index-1 < slots.size())
			slot = slots.at(static_cast<ExprVector::size_type>(index-1));
		else
			throw EvaluateException("Slot not given.");
		AssignCloned(slot);
	}
	else if(functionName == "SlotSequence")
	{
		delete head;
		head = new Expression("Sequence");
		DeleteLeaves();
		leaves.reserve(slots.size());
		for(ExprVector::const_iterator leaf = slots.begin(); leaf != slots.end(); ++leaf)
			AppendLeaf((*leaf)->Clone());
	}
	else if(functionName != "Function")
	{
		if(head)
			head->SubstituteSlots(slots);
		for(ExprVector::const_iterator leaf = leaves.begin(); leaf != leaves.end(); ++leaf)
			(*leaf)->SubstituteSlots(slots);
	}
}
Stmt *TransformVector::VisitInitListExpr(InitListExpr *Node) {
  // For conventional vector literals such as '{1, 2, 3, 4}'
  QualType ETy = Node->getType();
  if (ETy->isExtVectorType()) {
    CompoundLiteralExpr *CLE = new (ASTCtx) CompoundLiteralExpr(
        SourceLocation(), ASTCtx.getTrivialTypeSourceInfo(ETy),
        ETy, Node->getValueKind(), Node, false);
    return VisitCompoundLiteralExpr(CLE);
  }

  if (NeedFlattening) {
    ExprVector InitExprs;
    ExprVector *PrvInitExprs = CurInitExprs;
    CurInitExprs = &InitExprs;

    for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
      assert(Node->getInit(i) && "NULL InitExpr?");
      Expr *InitExpr = TransformExpr(Node->getInit(i));
      InitExprs.push_back(InitExpr);
    }

    for (unsigned i =0, e = InitExprs.size(); i < e; ++i) {
      Node->updateInit(ASTCtx, i, InitExprs[i]);
    }

    CurInitExprs = PrvInitExprs;

  } else {
    for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
      if (Node->getInit(i)) {
        Node->setInit(i, TransformExpr(Node->getInit(i)));
      }
    }
  }
  
  return Node;
}
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 #7
0
/// ParseAsmStatement - Parse a GNU extended asm statement.
///       asm-statement:
///         gnu-asm-statement
///         ms-asm-statement
///
/// [GNU] gnu-asm-statement:
///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
///
/// [GNU] asm-argument:
///         asm-string-literal
///         asm-string-literal ':' asm-operands[opt]
///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
///                 ':' asm-clobbers
///
/// [GNU] asm-clobbers:
///         asm-string-literal
///         asm-clobbers ',' asm-string-literal
///
StmtResult Parser::ParseAsmStatement(bool &msAsm) {
  assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
  SourceLocation AsmLoc = ConsumeToken();

  if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
      !isTypeQualifier()) {
    msAsm = true;
    return ParseMicrosoftAsmStatement(AsmLoc);
  }

  DeclSpec DS(AttrFactory);
  SourceLocation Loc = Tok.getLocation();
  ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);

  // GNU asms accept, but warn, about type-qualifiers other than volatile.
  if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
    Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
  if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
    Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
  // FIXME: Once GCC supports _Atomic, check whether it permits it here.
  if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
    Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";

  // Remember if this was a volatile asm.
  bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
  if (Tok.isNot(tok::l_paren)) {
    Diag(Tok, diag::err_expected_lparen_after) << "asm";
    SkipUntil(tok::r_paren, StopAtSemi);
    return StmtError();
  }
  BalancedDelimiterTracker T(*this, tok::l_paren);
  T.consumeOpen();

  ExprResult AsmString(ParseAsmStringLiteral());

  // Check if GNU-style InlineAsm is disabled.
  // Error on anything other than empty string.
  if (!(getLangOpts().GNUAsm || AsmString.isInvalid())) {
    const auto *SL = cast<StringLiteral>(AsmString.get());
    if (!SL->getString().trim().empty())
      Diag(Loc, diag::err_gnu_inline_asm_disabled);
  }

  if (AsmString.isInvalid()) {
    // Consume up to and including the closing paren.
    T.skipToEnd();
    return StmtError();
  }

  SmallVector<IdentifierInfo *, 4> Names;
  ExprVector Constraints;
  ExprVector Exprs;
  ExprVector Clobbers;

  if (Tok.is(tok::r_paren)) {
    // We have a simple asm expression like 'asm("foo")'.
    T.consumeClose();
    return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
                                   /*NumOutputs*/ 0, /*NumInputs*/ 0, nullptr,
                                   Constraints, Exprs, AsmString.get(),
                                   Clobbers, T.getCloseLocation());
  }

  // Parse Outputs, if present.
  bool AteExtraColon = false;
  if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    // In C++ mode, parse "::" like ": :".
    AteExtraColon = Tok.is(tok::coloncolon);
    ConsumeToken();

    if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
      return StmtError();
  }

  unsigned NumOutputs = Names.size();

  // Parse Inputs, if present.
  if (AteExtraColon || Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    // In C++ mode, parse "::" like ": :".
    if (AteExtraColon)
      AteExtraColon = false;
    else {
      AteExtraColon = Tok.is(tok::coloncolon);
      ConsumeToken();
    }

    if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
      return StmtError();
  }

  assert(Names.size() == Constraints.size() &&
         Constraints.size() == Exprs.size() && "Input operand size mismatch!");

  unsigned NumInputs = Names.size() - NumOutputs;

  // Parse the clobbers, if present.
  if (AteExtraColon || Tok.is(tok::colon)) {
    if (!AteExtraColon)
      ConsumeToken();

    // Parse the asm-string list for clobbers if present.
    if (Tok.isNot(tok::r_paren)) {
      while (1) {
        ExprResult Clobber(ParseAsmStringLiteral());

        if (Clobber.isInvalid())
          break;

        Clobbers.push_back(Clobber.get());

        if (!TryConsumeToken(tok::comma))
          break;
      }
    }
  }

  T.consumeClose();
  return Actions.ActOnGCCAsmStmt(
      AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(),
      Constraints, Exprs, AsmString.get(), Clobbers, T.getCloseLocation());
}