xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaPPC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===------ SemaPPC.cpp ------ PowerPC target-specific routines -----------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric //  This file implements semantic analysis functions specific to PowerPC.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric #include "clang/Sema/SemaPPC.h"
14*0fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h"
15*0fca6ea1SDimitry Andric #include "clang/AST/Attr.h"
16*0fca6ea1SDimitry Andric #include "clang/AST/CharUnits.h"
17*0fca6ea1SDimitry Andric #include "clang/AST/Decl.h"
18*0fca6ea1SDimitry Andric #include "clang/AST/Type.h"
19*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
20*0fca6ea1SDimitry Andric #include "clang/Basic/SourceLocation.h"
21*0fca6ea1SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
22*0fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
23*0fca6ea1SDimitry Andric #include "llvm/ADT/APSInt.h"
24*0fca6ea1SDimitry Andric 
25*0fca6ea1SDimitry Andric namespace clang {
26*0fca6ea1SDimitry Andric 
27*0fca6ea1SDimitry Andric SemaPPC::SemaPPC(Sema &S) : SemaBase(S) {}
28*0fca6ea1SDimitry Andric 
29*0fca6ea1SDimitry Andric void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {
30*0fca6ea1SDimitry Andric   const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens());
31*0fca6ea1SDimitry Andric   if (!ICE)
32*0fca6ea1SDimitry Andric     return;
33*0fca6ea1SDimitry Andric 
34*0fca6ea1SDimitry Andric   const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
35*0fca6ea1SDimitry Andric   if (!DR)
36*0fca6ea1SDimitry Andric     return;
37*0fca6ea1SDimitry Andric 
38*0fca6ea1SDimitry Andric   const auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl());
39*0fca6ea1SDimitry Andric   if (!PD || !PD->getType()->isRecordType())
40*0fca6ea1SDimitry Andric     return;
41*0fca6ea1SDimitry Andric 
42*0fca6ea1SDimitry Andric   QualType ArgType = Arg->getType();
43*0fca6ea1SDimitry Andric   for (const FieldDecl *FD :
44*0fca6ea1SDimitry Andric        ArgType->castAs<RecordType>()->getDecl()->fields()) {
45*0fca6ea1SDimitry Andric     if (const auto *AA = FD->getAttr<AlignedAttr>()) {
46*0fca6ea1SDimitry Andric       CharUnits Alignment = getASTContext().toCharUnitsFromBits(
47*0fca6ea1SDimitry Andric           AA->getAlignment(getASTContext()));
48*0fca6ea1SDimitry Andric       if (Alignment.getQuantity() == 16) {
49*0fca6ea1SDimitry Andric         Diag(FD->getLocation(), diag::warn_not_xl_compatible) << FD;
50*0fca6ea1SDimitry Andric         Diag(Loc, diag::note_misaligned_member_used_here) << PD;
51*0fca6ea1SDimitry Andric       }
52*0fca6ea1SDimitry Andric     }
53*0fca6ea1SDimitry Andric   }
54*0fca6ea1SDimitry Andric }
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric static bool isPPC_64Builtin(unsigned BuiltinID) {
57*0fca6ea1SDimitry Andric   // These builtins only work on PPC 64bit targets.
58*0fca6ea1SDimitry Andric   switch (BuiltinID) {
59*0fca6ea1SDimitry Andric   case PPC::BI__builtin_divde:
60*0fca6ea1SDimitry Andric   case PPC::BI__builtin_divdeu:
61*0fca6ea1SDimitry Andric   case PPC::BI__builtin_bpermd:
62*0fca6ea1SDimitry Andric   case PPC::BI__builtin_pdepd:
63*0fca6ea1SDimitry Andric   case PPC::BI__builtin_pextd:
64*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_ldarx:
65*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_stdcx:
66*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_tdw:
67*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_trapd:
68*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_cmpeqb:
69*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_setb:
70*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mulhd:
71*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mulhdu:
72*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maddhd:
73*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maddhdu:
74*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maddld:
75*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_load8r:
76*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_store8r:
77*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_insert_exp:
78*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_extract_sig:
79*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_addex:
80*0fca6ea1SDimitry Andric   case PPC::BI__builtin_darn:
81*0fca6ea1SDimitry Andric   case PPC::BI__builtin_darn_raw:
82*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_compare_and_swaplp:
83*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_addlp:
84*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_andlp:
85*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_orlp:
86*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_fetch_and_swaplp:
87*0fca6ea1SDimitry Andric     return true;
88*0fca6ea1SDimitry Andric   }
89*0fca6ea1SDimitry Andric   return false;
90*0fca6ea1SDimitry Andric }
91*0fca6ea1SDimitry Andric 
92*0fca6ea1SDimitry Andric bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
93*0fca6ea1SDimitry Andric                                           unsigned BuiltinID,
94*0fca6ea1SDimitry Andric                                           CallExpr *TheCall) {
95*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
96*0fca6ea1SDimitry Andric   unsigned i = 0, l = 0, u = 0;
97*0fca6ea1SDimitry Andric   bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
98*0fca6ea1SDimitry Andric   llvm::APSInt Result;
99*0fca6ea1SDimitry Andric 
100*0fca6ea1SDimitry Andric   if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
101*0fca6ea1SDimitry Andric     return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
102*0fca6ea1SDimitry Andric            << TheCall->getSourceRange();
103*0fca6ea1SDimitry Andric 
104*0fca6ea1SDimitry Andric   switch (BuiltinID) {
105*0fca6ea1SDimitry Andric   default:
106*0fca6ea1SDimitry Andric     return false;
107*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_crypto_vshasigmaw:
108*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_crypto_vshasigmad:
109*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
110*0fca6ea1SDimitry Andric            SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);
111*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_dss:
112*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3);
113*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tbegin:
114*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tend:
115*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
116*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tsr:
117*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7);
118*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tabortwc:
119*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tabortdc:
120*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
121*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tabortwci:
122*0fca6ea1SDimitry Andric   case PPC::BI__builtin_tabortdci:
123*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31) ||
124*0fca6ea1SDimitry Andric            SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
125*0fca6ea1SDimitry Andric   // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
126*0fca6ea1SDimitry Andric   // __builtin_(un)pack_longdouble are available only if long double uses IBM
127*0fca6ea1SDimitry Andric   // extended double representation.
128*0fca6ea1SDimitry Andric   case PPC::BI__builtin_unpack_longdouble:
129*0fca6ea1SDimitry Andric     if (SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1))
130*0fca6ea1SDimitry Andric       return true;
131*0fca6ea1SDimitry Andric     [[fallthrough]];
132*0fca6ea1SDimitry Andric   case PPC::BI__builtin_pack_longdouble:
133*0fca6ea1SDimitry Andric     if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
134*0fca6ea1SDimitry Andric       return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)
135*0fca6ea1SDimitry Andric              << "ibmlongdouble";
136*0fca6ea1SDimitry Andric     return false;
137*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_dst:
138*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_dstt:
139*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_dstst:
140*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_dststt:
141*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
142*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxpermdi:
143*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxsldwi:
144*0fca6ea1SDimitry Andric     return BuiltinVSX(TheCall);
145*0fca6ea1SDimitry Andric   case PPC::BI__builtin_unpack_vector_int128:
146*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
147*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vgnb:
148*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 2, 7);
149*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxeval:
150*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 255);
151*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vsldbi:
152*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
153*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vsrdbi:
154*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
155*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxpermx:
156*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 7);
157*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_tw:
158*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_tdw:
159*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 31);
160*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_cmprb:
161*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
162*0fca6ea1SDimitry Andric   // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
163*0fca6ea1SDimitry Andric   // be a constant that represents a contiguous bit field.
164*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_rlwnm:
165*0fca6ea1SDimitry Andric     return SemaRef.ValueIsRunOfOnes(TheCall, 2);
166*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_rlwimi:
167*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) ||
168*0fca6ea1SDimitry Andric            SemaRef.ValueIsRunOfOnes(TheCall, 3);
169*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_rldimi:
170*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 63) ||
171*0fca6ea1SDimitry Andric            SemaRef.ValueIsRunOfOnes(TheCall, 3);
172*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_addex: {
173*0fca6ea1SDimitry Andric     if (SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3))
174*0fca6ea1SDimitry Andric       return true;
175*0fca6ea1SDimitry Andric     // Output warning for reserved values 1 to 3.
176*0fca6ea1SDimitry Andric     int ArgValue =
177*0fca6ea1SDimitry Andric         TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();
178*0fca6ea1SDimitry Andric     if (ArgValue != 0)
179*0fca6ea1SDimitry Andric       Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)
180*0fca6ea1SDimitry Andric           << ArgValue;
181*0fca6ea1SDimitry Andric     return false;
182*0fca6ea1SDimitry Andric   }
183*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mtfsb0:
184*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mtfsb1:
185*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
186*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mtfsf:
187*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 255);
188*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_mtfsfi:
189*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7) ||
190*0fca6ea1SDimitry Andric            SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
191*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_alignx:
192*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgPower2(TheCall, 0);
193*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_rdlam:
194*0fca6ea1SDimitry Andric     return SemaRef.ValueIsRunOfOnes(TheCall, 2);
195*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_ldrmb:
196*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_strmb:
197*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
198*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vcntmbb:
199*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vcntmbh:
200*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vcntmbw:
201*0fca6ea1SDimitry Andric   case PPC::BI__builtin_altivec_vcntmbd:
202*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
203*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxgenpcvbm:
204*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxgenpcvhm:
205*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxgenpcvwm:
206*0fca6ea1SDimitry Andric   case PPC::BI__builtin_vsx_xxgenpcvdm:
207*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
208*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_test_data_class: {
209*0fca6ea1SDimitry Andric     // Check if the first argument of the __builtin_ppc_test_data_class call is
210*0fca6ea1SDimitry Andric     // valid. The argument must be 'float' or 'double' or '__float128'.
211*0fca6ea1SDimitry Andric     QualType ArgType = TheCall->getArg(0)->getType();
212*0fca6ea1SDimitry Andric     if (ArgType != QualType(Context.FloatTy) &&
213*0fca6ea1SDimitry Andric         ArgType != QualType(Context.DoubleTy) &&
214*0fca6ea1SDimitry Andric         ArgType != QualType(Context.Float128Ty))
215*0fca6ea1SDimitry Andric       return Diag(TheCall->getBeginLoc(),
216*0fca6ea1SDimitry Andric                   diag::err_ppc_invalid_test_data_class_type);
217*0fca6ea1SDimitry Andric     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 127);
218*0fca6ea1SDimitry Andric   }
219*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maxfe:
220*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_minfe:
221*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maxfl:
222*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_minfl:
223*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_maxfs:
224*0fca6ea1SDimitry Andric   case PPC::BI__builtin_ppc_minfs: {
225*0fca6ea1SDimitry Andric     if (Context.getTargetInfo().getTriple().isOSAIX() &&
226*0fca6ea1SDimitry Andric         (BuiltinID == PPC::BI__builtin_ppc_maxfe ||
227*0fca6ea1SDimitry Andric          BuiltinID == PPC::BI__builtin_ppc_minfe))
228*0fca6ea1SDimitry Andric       return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type)
229*0fca6ea1SDimitry Andric              << "builtin" << true << 128 << QualType(Context.LongDoubleTy)
230*0fca6ea1SDimitry Andric              << false << Context.getTargetInfo().getTriple().str();
231*0fca6ea1SDimitry Andric     // Argument type should be exact.
232*0fca6ea1SDimitry Andric     QualType ArgType = QualType(Context.LongDoubleTy);
233*0fca6ea1SDimitry Andric     if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||
234*0fca6ea1SDimitry Andric         BuiltinID == PPC::BI__builtin_ppc_minfl)
235*0fca6ea1SDimitry Andric       ArgType = QualType(Context.DoubleTy);
236*0fca6ea1SDimitry Andric     else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||
237*0fca6ea1SDimitry Andric              BuiltinID == PPC::BI__builtin_ppc_minfs)
238*0fca6ea1SDimitry Andric       ArgType = QualType(Context.FloatTy);
239*0fca6ea1SDimitry Andric     for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)
240*0fca6ea1SDimitry Andric       if (TheCall->getArg(I)->getType() != ArgType)
241*0fca6ea1SDimitry Andric         return Diag(TheCall->getBeginLoc(),
242*0fca6ea1SDimitry Andric                     diag::err_typecheck_convert_incompatible)
243*0fca6ea1SDimitry Andric                << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0;
244*0fca6ea1SDimitry Andric     return false;
245*0fca6ea1SDimitry Andric   }
246*0fca6ea1SDimitry Andric #define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature)                        \
247*0fca6ea1SDimitry Andric   case PPC::BI__builtin_##Name:                                                \
248*0fca6ea1SDimitry Andric     return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
249*0fca6ea1SDimitry Andric #include "clang/Basic/BuiltinsPPC.def"
250*0fca6ea1SDimitry Andric   }
251*0fca6ea1SDimitry Andric   return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u);
252*0fca6ea1SDimitry Andric }
253*0fca6ea1SDimitry Andric 
254*0fca6ea1SDimitry Andric // Check if the given type is a non-pointer PPC MMA type. This function is used
255*0fca6ea1SDimitry Andric // in Sema to prevent invalid uses of restricted PPC MMA types.
256*0fca6ea1SDimitry Andric bool SemaPPC::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
257*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
258*0fca6ea1SDimitry Andric   if (Type->isPointerType() || Type->isArrayType())
259*0fca6ea1SDimitry Andric     return false;
260*0fca6ea1SDimitry Andric 
261*0fca6ea1SDimitry Andric   QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
262*0fca6ea1SDimitry Andric #define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
263*0fca6ea1SDimitry Andric   if (false
264*0fca6ea1SDimitry Andric #include "clang/Basic/PPCTypes.def"
265*0fca6ea1SDimitry Andric   ) {
266*0fca6ea1SDimitry Andric     Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
267*0fca6ea1SDimitry Andric     return true;
268*0fca6ea1SDimitry Andric   }
269*0fca6ea1SDimitry Andric   return false;
270*0fca6ea1SDimitry Andric }
271*0fca6ea1SDimitry Andric 
272*0fca6ea1SDimitry Andric /// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
273*0fca6ea1SDimitry Andric /// advancing the pointer over the consumed characters. The decoded type is
274*0fca6ea1SDimitry Andric /// returned. If the decoded type represents a constant integer with a
275*0fca6ea1SDimitry Andric /// constraint on its value then Mask is set to that value. The type descriptors
276*0fca6ea1SDimitry Andric /// used in Str are specific to PPC MMA builtins and are documented in the file
277*0fca6ea1SDimitry Andric /// defining the PPC builtins.
278*0fca6ea1SDimitry Andric static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
279*0fca6ea1SDimitry Andric                                         unsigned &Mask) {
280*0fca6ea1SDimitry Andric   bool RequireICE = false;
281*0fca6ea1SDimitry Andric   ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
282*0fca6ea1SDimitry Andric   switch (*Str++) {
283*0fca6ea1SDimitry Andric   case 'V':
284*0fca6ea1SDimitry Andric     return Context.getVectorType(Context.UnsignedCharTy, 16,
285*0fca6ea1SDimitry Andric                                  VectorKind::AltiVecVector);
286*0fca6ea1SDimitry Andric   case 'i': {
287*0fca6ea1SDimitry Andric     char *End;
288*0fca6ea1SDimitry Andric     unsigned size = strtoul(Str, &End, 10);
289*0fca6ea1SDimitry Andric     assert(End != Str && "Missing constant parameter constraint");
290*0fca6ea1SDimitry Andric     Str = End;
291*0fca6ea1SDimitry Andric     Mask = size;
292*0fca6ea1SDimitry Andric     return Context.IntTy;
293*0fca6ea1SDimitry Andric   }
294*0fca6ea1SDimitry Andric   case 'W': {
295*0fca6ea1SDimitry Andric     char *End;
296*0fca6ea1SDimitry Andric     unsigned size = strtoul(Str, &End, 10);
297*0fca6ea1SDimitry Andric     assert(End != Str && "Missing PowerPC MMA type size");
298*0fca6ea1SDimitry Andric     Str = End;
299*0fca6ea1SDimitry Andric     QualType Type;
300*0fca6ea1SDimitry Andric     switch (size) {
301*0fca6ea1SDimitry Andric #define PPC_VECTOR_TYPE(typeName, Id, size)                                    \
302*0fca6ea1SDimitry Andric   case size:                                                                   \
303*0fca6ea1SDimitry Andric     Type = Context.Id##Ty;                                                     \
304*0fca6ea1SDimitry Andric     break;
305*0fca6ea1SDimitry Andric #include "clang/Basic/PPCTypes.def"
306*0fca6ea1SDimitry Andric     default:
307*0fca6ea1SDimitry Andric       llvm_unreachable("Invalid PowerPC MMA vector type");
308*0fca6ea1SDimitry Andric     }
309*0fca6ea1SDimitry Andric     bool CheckVectorArgs = false;
310*0fca6ea1SDimitry Andric     while (!CheckVectorArgs) {
311*0fca6ea1SDimitry Andric       switch (*Str++) {
312*0fca6ea1SDimitry Andric       case '*':
313*0fca6ea1SDimitry Andric         Type = Context.getPointerType(Type);
314*0fca6ea1SDimitry Andric         break;
315*0fca6ea1SDimitry Andric       case 'C':
316*0fca6ea1SDimitry Andric         Type = Type.withConst();
317*0fca6ea1SDimitry Andric         break;
318*0fca6ea1SDimitry Andric       default:
319*0fca6ea1SDimitry Andric         CheckVectorArgs = true;
320*0fca6ea1SDimitry Andric         --Str;
321*0fca6ea1SDimitry Andric         break;
322*0fca6ea1SDimitry Andric       }
323*0fca6ea1SDimitry Andric     }
324*0fca6ea1SDimitry Andric     return Type;
325*0fca6ea1SDimitry Andric   }
326*0fca6ea1SDimitry Andric   default:
327*0fca6ea1SDimitry Andric     return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);
328*0fca6ea1SDimitry Andric   }
329*0fca6ea1SDimitry Andric }
330*0fca6ea1SDimitry Andric 
331*0fca6ea1SDimitry Andric bool SemaPPC::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
332*0fca6ea1SDimitry Andric                                 const char *TypeStr) {
333*0fca6ea1SDimitry Andric 
334*0fca6ea1SDimitry Andric   assert((TypeStr[0] != '\0') &&
335*0fca6ea1SDimitry Andric          "Invalid types in PPC MMA builtin declaration");
336*0fca6ea1SDimitry Andric 
337*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
338*0fca6ea1SDimitry Andric   unsigned Mask = 0;
339*0fca6ea1SDimitry Andric   unsigned ArgNum = 0;
340*0fca6ea1SDimitry Andric 
341*0fca6ea1SDimitry Andric   // The first type in TypeStr is the type of the value returned by the
342*0fca6ea1SDimitry Andric   // builtin. So we first read that type and change the type of TheCall.
343*0fca6ea1SDimitry Andric   QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
344*0fca6ea1SDimitry Andric   TheCall->setType(type);
345*0fca6ea1SDimitry Andric 
346*0fca6ea1SDimitry Andric   while (*TypeStr != '\0') {
347*0fca6ea1SDimitry Andric     Mask = 0;
348*0fca6ea1SDimitry Andric     QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
349*0fca6ea1SDimitry Andric     if (ArgNum >= TheCall->getNumArgs()) {
350*0fca6ea1SDimitry Andric       ArgNum++;
351*0fca6ea1SDimitry Andric       break;
352*0fca6ea1SDimitry Andric     }
353*0fca6ea1SDimitry Andric 
354*0fca6ea1SDimitry Andric     Expr *Arg = TheCall->getArg(ArgNum);
355*0fca6ea1SDimitry Andric     QualType PassedType = Arg->getType();
356*0fca6ea1SDimitry Andric     QualType StrippedRVType = PassedType.getCanonicalType();
357*0fca6ea1SDimitry Andric 
358*0fca6ea1SDimitry Andric     // Strip Restrict/Volatile qualifiers.
359*0fca6ea1SDimitry Andric     if (StrippedRVType.isRestrictQualified() ||
360*0fca6ea1SDimitry Andric         StrippedRVType.isVolatileQualified())
361*0fca6ea1SDimitry Andric       StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
362*0fca6ea1SDimitry Andric 
363*0fca6ea1SDimitry Andric     // The only case where the argument type and expected type are allowed to
364*0fca6ea1SDimitry Andric     // mismatch is if the argument type is a non-void pointer (or array) and
365*0fca6ea1SDimitry Andric     // expected type is a void pointer.
366*0fca6ea1SDimitry Andric     if (StrippedRVType != ExpectedType)
367*0fca6ea1SDimitry Andric       if (!(ExpectedType->isVoidPointerType() &&
368*0fca6ea1SDimitry Andric             (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
369*0fca6ea1SDimitry Andric         return Diag(Arg->getBeginLoc(),
370*0fca6ea1SDimitry Andric                     diag::err_typecheck_convert_incompatible)
371*0fca6ea1SDimitry Andric                << PassedType << ExpectedType << 1 << 0 << 0;
372*0fca6ea1SDimitry Andric 
373*0fca6ea1SDimitry Andric     // If the value of the Mask is not 0, we have a constraint in the size of
374*0fca6ea1SDimitry Andric     // the integer argument so here we ensure the argument is a constant that
375*0fca6ea1SDimitry Andric     // is in the valid range.
376*0fca6ea1SDimitry Andric     if (Mask != 0 &&
377*0fca6ea1SDimitry Andric         SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))
378*0fca6ea1SDimitry Andric       return true;
379*0fca6ea1SDimitry Andric 
380*0fca6ea1SDimitry Andric     ArgNum++;
381*0fca6ea1SDimitry Andric   }
382*0fca6ea1SDimitry Andric 
383*0fca6ea1SDimitry Andric   // In case we exited early from the previous loop, there are other types to
384*0fca6ea1SDimitry Andric   // read from TypeStr. So we need to read them all to ensure we have the right
385*0fca6ea1SDimitry Andric   // number of arguments in TheCall and if it is not the case, to display a
386*0fca6ea1SDimitry Andric   // better error message.
387*0fca6ea1SDimitry Andric   while (*TypeStr != '\0') {
388*0fca6ea1SDimitry Andric     (void)DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
389*0fca6ea1SDimitry Andric     ArgNum++;
390*0fca6ea1SDimitry Andric   }
391*0fca6ea1SDimitry Andric   if (SemaRef.checkArgCount(TheCall, ArgNum))
392*0fca6ea1SDimitry Andric     return true;
393*0fca6ea1SDimitry Andric 
394*0fca6ea1SDimitry Andric   return false;
395*0fca6ea1SDimitry Andric }
396*0fca6ea1SDimitry Andric 
397*0fca6ea1SDimitry Andric bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {
398*0fca6ea1SDimitry Andric   unsigned ExpectedNumArgs = 3;
399*0fca6ea1SDimitry Andric   if (SemaRef.checkArgCount(TheCall, ExpectedNumArgs))
400*0fca6ea1SDimitry Andric     return true;
401*0fca6ea1SDimitry Andric 
402*0fca6ea1SDimitry Andric   // Check the third argument is a compile time constant
403*0fca6ea1SDimitry Andric   if (!TheCall->getArg(2)->isIntegerConstantExpr(getASTContext()))
404*0fca6ea1SDimitry Andric     return Diag(TheCall->getBeginLoc(),
405*0fca6ea1SDimitry Andric                 diag::err_vsx_builtin_nonconstant_argument)
406*0fca6ea1SDimitry Andric            << 3 /* argument index */ << TheCall->getDirectCallee()
407*0fca6ea1SDimitry Andric            << SourceRange(TheCall->getArg(2)->getBeginLoc(),
408*0fca6ea1SDimitry Andric                           TheCall->getArg(2)->getEndLoc());
409*0fca6ea1SDimitry Andric 
410*0fca6ea1SDimitry Andric   QualType Arg1Ty = TheCall->getArg(0)->getType();
411*0fca6ea1SDimitry Andric   QualType Arg2Ty = TheCall->getArg(1)->getType();
412*0fca6ea1SDimitry Andric 
413*0fca6ea1SDimitry Andric   // Check the type of argument 1 and argument 2 are vectors.
414*0fca6ea1SDimitry Andric   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
415*0fca6ea1SDimitry Andric   if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
416*0fca6ea1SDimitry Andric       (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
417*0fca6ea1SDimitry Andric     return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
418*0fca6ea1SDimitry Andric            << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
419*0fca6ea1SDimitry Andric            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
420*0fca6ea1SDimitry Andric                           TheCall->getArg(1)->getEndLoc());
421*0fca6ea1SDimitry Andric   }
422*0fca6ea1SDimitry Andric 
423*0fca6ea1SDimitry Andric   // Check the first two arguments are the same type.
424*0fca6ea1SDimitry Andric   if (!getASTContext().hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
425*0fca6ea1SDimitry Andric     return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
426*0fca6ea1SDimitry Andric            << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
427*0fca6ea1SDimitry Andric            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
428*0fca6ea1SDimitry Andric                           TheCall->getArg(1)->getEndLoc());
429*0fca6ea1SDimitry Andric   }
430*0fca6ea1SDimitry Andric 
431*0fca6ea1SDimitry Andric   // When default clang type checking is turned off and the customized type
432*0fca6ea1SDimitry Andric   // checking is used, the returning type of the function must be explicitly
433*0fca6ea1SDimitry Andric   // set. Otherwise it is _Bool by default.
434*0fca6ea1SDimitry Andric   TheCall->setType(Arg1Ty);
435*0fca6ea1SDimitry Andric 
436*0fca6ea1SDimitry Andric   return false;
437*0fca6ea1SDimitry Andric }
438*0fca6ea1SDimitry Andric 
439*0fca6ea1SDimitry Andric } // namespace clang
440