xref: /llvm-project/clang/lib/Sema/SemaPPC.cpp (revision 27d37ee4d067f42e9a46a0871d3cb961323e5c85)
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   llvm::APSInt Result;
102 
103   if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
104     return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
105            << TheCall->getSourceRange();
106 
107   switch (BuiltinID) {
108   default:
109     return false;
110   case PPC::BI__builtin_altivec_crypto_vshasigmaw:
111   case PPC::BI__builtin_altivec_crypto_vshasigmad:
112     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
113            SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);
114   case PPC::BI__builtin_altivec_dss:
115     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3);
116   case PPC::BI__builtin_tbegin:
117   case PPC::BI__builtin_tend:
118     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
119   case PPC::BI__builtin_tsr:
120     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7);
121   case PPC::BI__builtin_tabortwc:
122   case PPC::BI__builtin_tabortdc:
123     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
124   case PPC::BI__builtin_tabortwci:
125   case PPC::BI__builtin_tabortdci:
126     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31) ||
127            SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
128   // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
129   // __builtin_(un)pack_longdouble are available only if long double uses IBM
130   // extended double representation.
131   case PPC::BI__builtin_unpack_longdouble:
132     if (SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1))
133       return true;
134     [[fallthrough]];
135   case PPC::BI__builtin_pack_longdouble:
136     if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
137       return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)
138              << "ibmlongdouble";
139     return false;
140   case PPC::BI__builtin_altivec_dst:
141   case PPC::BI__builtin_altivec_dstt:
142   case PPC::BI__builtin_altivec_dstst:
143   case PPC::BI__builtin_altivec_dststt:
144     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
145   case PPC::BI__builtin_vsx_xxpermdi:
146   case PPC::BI__builtin_vsx_xxsldwi:
147     return BuiltinVSX(TheCall);
148   case PPC::BI__builtin_unpack_vector_int128:
149     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
150   case PPC::BI__builtin_altivec_vgnb:
151     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 2, 7);
152   case PPC::BI__builtin_vsx_xxeval:
153     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 255);
154   case PPC::BI__builtin_altivec_vsldbi:
155     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
156   case PPC::BI__builtin_altivec_vsrdbi:
157     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
158   case PPC::BI__builtin_vsx_xxpermx:
159     return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 7);
160   case PPC::BI__builtin_ppc_tw:
161   case PPC::BI__builtin_ppc_tdw:
162     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 31);
163   case PPC::BI__builtin_ppc_cmprb:
164     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
165   // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
166   // be a constant that represents a contiguous bit field.
167   case PPC::BI__builtin_ppc_rlwnm:
168     return SemaRef.ValueIsRunOfOnes(TheCall, 2);
169   case PPC::BI__builtin_ppc_rlwimi:
170     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) ||
171            SemaRef.ValueIsRunOfOnes(TheCall, 3);
172   case PPC::BI__builtin_ppc_rldimi:
173     return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 63) ||
174            SemaRef.ValueIsRunOfOnes(TheCall, 3);
175   case PPC::BI__builtin_ppc_addex: {
176     if (SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3))
177       return true;
178     // Output warning for reserved values 1 to 3.
179     int ArgValue =
180         TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();
181     if (ArgValue != 0)
182       Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)
183           << ArgValue;
184     return false;
185   }
186   case PPC::BI__builtin_ppc_mtfsb0:
187   case PPC::BI__builtin_ppc_mtfsb1:
188     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
189   case PPC::BI__builtin_ppc_mtfsf:
190     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 255);
191   case PPC::BI__builtin_ppc_mtfsfi:
192     return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7) ||
193            SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
194   case PPC::BI__builtin_ppc_alignx:
195     return SemaRef.BuiltinConstantArgPower2(TheCall, 0);
196   case PPC::BI__builtin_ppc_rdlam:
197     return SemaRef.ValueIsRunOfOnes(TheCall, 2);
198   case PPC::BI__builtin_vsx_ldrmb:
199   case PPC::BI__builtin_vsx_strmb:
200     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
201   case PPC::BI__builtin_altivec_vcntmbb:
202   case PPC::BI__builtin_altivec_vcntmbh:
203   case PPC::BI__builtin_altivec_vcntmbw:
204   case PPC::BI__builtin_altivec_vcntmbd:
205     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
206   case PPC::BI__builtin_vsx_xxgenpcvbm:
207   case PPC::BI__builtin_vsx_xxgenpcvhm:
208   case PPC::BI__builtin_vsx_xxgenpcvwm:
209   case PPC::BI__builtin_vsx_xxgenpcvdm:
210     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
211   case PPC::BI__builtin_ppc_test_data_class: {
212     // Check if the first argument of the __builtin_ppc_test_data_class call is
213     // valid. The argument must be 'float' or 'double' or '__float128'.
214     QualType ArgType = TheCall->getArg(0)->getType();
215     if (ArgType != QualType(Context.FloatTy) &&
216         ArgType != QualType(Context.DoubleTy) &&
217         ArgType != QualType(Context.Float128Ty))
218       return Diag(TheCall->getBeginLoc(),
219                   diag::err_ppc_invalid_test_data_class_type);
220     return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 127);
221   }
222   case PPC::BI__builtin_ppc_maxfe:
223   case PPC::BI__builtin_ppc_minfe:
224   case PPC::BI__builtin_ppc_maxfl:
225   case PPC::BI__builtin_ppc_minfl:
226   case PPC::BI__builtin_ppc_maxfs:
227   case PPC::BI__builtin_ppc_minfs: {
228     if (Context.getTargetInfo().getTriple().isOSAIX() &&
229         (BuiltinID == PPC::BI__builtin_ppc_maxfe ||
230          BuiltinID == PPC::BI__builtin_ppc_minfe))
231       return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type)
232              << "builtin" << true << 128 << QualType(Context.LongDoubleTy)
233              << false << Context.getTargetInfo().getTriple().str();
234     // Argument type should be exact.
235     QualType ArgType = QualType(Context.LongDoubleTy);
236     if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||
237         BuiltinID == PPC::BI__builtin_ppc_minfl)
238       ArgType = QualType(Context.DoubleTy);
239     else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||
240              BuiltinID == PPC::BI__builtin_ppc_minfs)
241       ArgType = QualType(Context.FloatTy);
242     for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)
243       if (TheCall->getArg(I)->getType() != ArgType)
244         return Diag(TheCall->getBeginLoc(),
245                     diag::err_typecheck_convert_incompatible)
246                << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0;
247     return false;
248   }
249 #define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature)                        \
250   case PPC::BI__builtin_##Name:                                                \
251     return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
252 #include "clang/Basic/BuiltinsPPC.def"
253   }
254   llvm_unreachable("must return from switch");
255 }
256 
257 // Check if the given type is a non-pointer PPC MMA type. This function is used
258 // in Sema to prevent invalid uses of restricted PPC MMA types.
259 bool SemaPPC::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
260   ASTContext &Context = getASTContext();
261   if (Type->isPointerType() || Type->isArrayType())
262     return false;
263 
264   QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
265 #define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
266   if (false
267 #include "clang/Basic/PPCTypes.def"
268   ) {
269     Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
270     return true;
271   }
272   return false;
273 }
274 
275 /// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
276 /// advancing the pointer over the consumed characters. The decoded type is
277 /// returned. If the decoded type represents a constant integer with a
278 /// constraint on its value then Mask is set to that value. The type descriptors
279 /// used in Str are specific to PPC MMA builtins and are documented in the file
280 /// defining the PPC builtins.
281 static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
282                                         unsigned &Mask) {
283   bool RequireICE = false;
284   ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
285   switch (*Str++) {
286   case 'V':
287     return Context.getVectorType(Context.UnsignedCharTy, 16,
288                                  VectorKind::AltiVecVector);
289   case 'i': {
290     char *End;
291     unsigned size = strtoul(Str, &End, 10);
292     assert(End != Str && "Missing constant parameter constraint");
293     Str = End;
294     Mask = size;
295     return Context.IntTy;
296   }
297   case 'W': {
298     char *End;
299     unsigned size = strtoul(Str, &End, 10);
300     assert(End != Str && "Missing PowerPC MMA type size");
301     Str = End;
302     QualType Type;
303     switch (size) {
304 #define PPC_VECTOR_TYPE(typeName, Id, size)                                    \
305   case size:                                                                   \
306     Type = Context.Id##Ty;                                                     \
307     break;
308 #include "clang/Basic/PPCTypes.def"
309     default:
310       llvm_unreachable("Invalid PowerPC MMA vector type");
311     }
312     bool CheckVectorArgs = false;
313     while (!CheckVectorArgs) {
314       switch (*Str++) {
315       case '*':
316         Type = Context.getPointerType(Type);
317         break;
318       case 'C':
319         Type = Type.withConst();
320         break;
321       default:
322         CheckVectorArgs = true;
323         --Str;
324         break;
325       }
326     }
327     return Type;
328   }
329   default:
330     return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);
331   }
332 }
333 
334 bool SemaPPC::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
335                                 const char *TypeStr) {
336 
337   assert((TypeStr[0] != '\0') &&
338          "Invalid types in PPC MMA builtin declaration");
339 
340   ASTContext &Context = getASTContext();
341   unsigned Mask = 0;
342   unsigned ArgNum = 0;
343 
344   // The first type in TypeStr is the type of the value returned by the
345   // builtin. So we first read that type and change the type of TheCall.
346   QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
347   TheCall->setType(type);
348 
349   while (*TypeStr != '\0') {
350     Mask = 0;
351     QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
352     if (ArgNum >= TheCall->getNumArgs()) {
353       ArgNum++;
354       break;
355     }
356 
357     Expr *Arg = TheCall->getArg(ArgNum);
358     QualType PassedType = Arg->getType();
359     QualType StrippedRVType = PassedType.getCanonicalType();
360 
361     // Strip Restrict/Volatile qualifiers.
362     if (StrippedRVType.isRestrictQualified() ||
363         StrippedRVType.isVolatileQualified())
364       StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
365 
366     // The only case where the argument type and expected type are allowed to
367     // mismatch is if the argument type is a non-void pointer (or array) and
368     // expected type is a void pointer.
369     if (StrippedRVType != ExpectedType)
370       if (!(ExpectedType->isVoidPointerType() &&
371             (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
372         return Diag(Arg->getBeginLoc(),
373                     diag::err_typecheck_convert_incompatible)
374                << PassedType << ExpectedType << 1 << 0 << 0;
375 
376     // If the value of the Mask is not 0, we have a constraint in the size of
377     // the integer argument so here we ensure the argument is a constant that
378     // is in the valid range.
379     if (Mask != 0 &&
380         SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))
381       return true;
382 
383     ArgNum++;
384   }
385 
386   // In case we exited early from the previous loop, there are other types to
387   // read from TypeStr. So we need to read them all to ensure we have the right
388   // number of arguments in TheCall and if it is not the case, to display a
389   // better error message.
390   while (*TypeStr != '\0') {
391     (void)DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
392     ArgNum++;
393   }
394   if (SemaRef.checkArgCount(TheCall, ArgNum))
395     return true;
396 
397   return false;
398 }
399 
400 bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {
401   unsigned ExpectedNumArgs = 3;
402   if (SemaRef.checkArgCount(TheCall, ExpectedNumArgs))
403     return true;
404 
405   // Check the third argument is a compile time constant
406   if (!TheCall->getArg(2)->isIntegerConstantExpr(getASTContext()))
407     return Diag(TheCall->getBeginLoc(),
408                 diag::err_vsx_builtin_nonconstant_argument)
409            << 3 /* argument index */ << TheCall->getDirectCallee()
410            << SourceRange(TheCall->getArg(2)->getBeginLoc(),
411                           TheCall->getArg(2)->getEndLoc());
412 
413   QualType Arg1Ty = TheCall->getArg(0)->getType();
414   QualType Arg2Ty = TheCall->getArg(1)->getType();
415 
416   // Check the type of argument 1 and argument 2 are vectors.
417   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
418   if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
419       (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
420     return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
421            << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
422            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
423                           TheCall->getArg(1)->getEndLoc());
424   }
425 
426   // Check the first two arguments are the same type.
427   if (!getASTContext().hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
428     return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
429            << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
430            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
431                           TheCall->getArg(1)->getEndLoc());
432   }
433 
434   // When default clang type checking is turned off and the customized type
435   // checking is used, the returning type of the function must be explicitly
436   // set. Otherwise it is _Bool by default.
437   TheCall->setType(Arg1Ty);
438 
439   return false;
440 }
441 
442 } // namespace clang
443