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