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