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