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
25namespace clang {
26
27SemaPPC::SemaPPC(Sema &S) : SemaBase(S) {}
28
29void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {
30 const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: Arg->IgnoreParens());
31 if (!ICE)
32 return;
33
34 const auto *DR = dyn_cast<DeclRefExpr>(Val: ICE->getSubExpr());
35 if (!DR)
36 return;
37
38 const auto *PD = dyn_cast<ParmVarDecl>(Val: 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 BitSize: AA->getAlignment(Ctx&: getASTContext()));
48 if (Alignment.getQuantity() == 16) {
49 Diag(Loc: FD->getLocation(), DiagID: diag::warn_not_xl_compatible) << FD;
50 Diag(Loc, DiagID: diag::note_misaligned_member_used_here) << PD;
51 }
52 }
53 }
54}
55
56static 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
92bool 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(T: TI.getIntPtrType()) == 64;
98 llvm::APSInt Result;
99
100 if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
101 return Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 1, Low: 0, High: 1) ||
110 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 15);
111 case PPC::BI__builtin_altivec_dss:
112 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 3);
113 case PPC::BI__builtin_tbegin:
114 case PPC::BI__builtin_tend:
115 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 1);
116 case PPC::BI__builtin_tsr:
117 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7);
118 case PPC::BI__builtin_tabortwc:
119 case PPC::BI__builtin_tabortdc:
120 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31);
121 case PPC::BI__builtin_tabortwci:
122 case PPC::BI__builtin_tabortdci:
123 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31) ||
124 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 1))
130 return true;
131 [[fallthrough]];
132 case PPC::BI__builtin_pack_longdouble:
133 if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
134 return Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 2, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 1);
147 case PPC::BI__builtin_altivec_vgnb:
148 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 2, High: 7);
149 case PPC::BI__builtin_vsx_xxeval:
150 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 255);
151 case PPC::BI__builtin_altivec_vsldbi:
152 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
153 case PPC::BI__builtin_altivec_vsrdbi:
154 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
155 case PPC::BI__builtin_vsx_xxpermx:
156 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 7);
157 case PPC::BI__builtin_ppc_tw:
158 case PPC::BI__builtin_ppc_tdw:
159 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 1, High: 31);
160 case PPC::BI__builtin_ppc_cmprb:
161 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 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, ArgNum: 2);
166 case PPC::BI__builtin_ppc_rlwimi:
167 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 31) ||
168 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
169 case PPC::BI__builtin_ppc_rldimi:
170 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 63) ||
171 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
172 case PPC::BI__builtin_ppc_addex: {
173 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 3))
174 return true;
175 // Output warning for reserved values 1 to 3.
176 int ArgValue =
177 TheCall->getArg(Arg: 2)->getIntegerConstantExpr(Ctx: Context)->getSExtValue();
178 if (ArgValue != 0)
179 Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 0, Low: 0, High: 31);
186 case PPC::BI__builtin_ppc_mtfsf:
187 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 255);
188 case PPC::BI__builtin_ppc_mtfsfi:
189 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7) ||
190 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 15);
191 case PPC::BI__builtin_ppc_alignx:
192 return SemaRef.BuiltinConstantArgPower2(TheCall, ArgNum: 0);
193 case PPC::BI__builtin_ppc_rdlam:
194 return SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 2);
195 case PPC::BI__builtin_vsx_ldrmb:
196 case PPC::BI__builtin_vsx_strmb:
197 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 1, High: 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, ArgNum: 1, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 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(Arg: 0)->getType();
212 if (ArgType != QualType(Context.FloatTy) &&
213 ArgType != QualType(Context.DoubleTy) &&
214 ArgType != QualType(Context.Float128Ty))
215 return Diag(Loc: TheCall->getBeginLoc(),
216 DiagID: diag::err_ppc_invalid_test_data_class_type);
217 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 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(Loc: TheCall->getBeginLoc(), DiagID: 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(Arg: I)->getType() != ArgType)
241 return Diag(Loc: TheCall->getBeginLoc(),
242 DiagID: diag::err_typecheck_convert_incompatible)
243 << TheCall->getArg(Arg: 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, ArgNum: i, Low: l, High: 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.
256bool 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(Loc: TypeLoc, DiagID: 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.
278static 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(VectorType: Context.UnsignedCharTy, NumElts: 16,
285 VecKind: VectorKind::AltiVecVector);
286 case 'i': {
287 char *End;
288 unsigned size = strtoul(nptr: Str, endptr: &End, base: 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(nptr: Str, endptr: &End, base: 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(T: 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&: --Str, Context, Error, RequireICE, AllowTypeModifiers: true);
328 }
329}
330
331bool 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, Str&: TypeStr, Mask);
344 TheCall->setType(type);
345
346 while (*TypeStr != '\0') {
347 Mask = 0;
348 QualType ExpectedType = DecodePPCMMATypeFromStr(Context, Str&: TypeStr, Mask);
349 if (ArgNum >= TheCall->getNumArgs()) {
350 ArgNum++;
351 break;
352 }
353
354 Expr *Arg = TheCall->getArg(Arg: 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(Loc: Arg->getBeginLoc(),
370 DiagID: 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, Low: 0, High: Mask, RangeIsError: 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, Str&: TypeStr, Mask);
389 ArgNum++;
390 }
391 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ArgNum))
392 return true;
393
394 return false;
395}
396
397bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {
398 unsigned ExpectedNumArgs = 3;
399 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ExpectedNumArgs))
400 return true;
401
402 // Check the third argument is a compile time constant
403 if (!TheCall->getArg(Arg: 2)->isIntegerConstantExpr(Ctx: getASTContext()))
404 return Diag(Loc: TheCall->getBeginLoc(),
405 DiagID: diag::err_vsx_builtin_nonconstant_argument)
406 << 3 /* argument index */ << TheCall->getDirectCallee()
407 << SourceRange(TheCall->getArg(Arg: 2)->getBeginLoc(),
408 TheCall->getArg(Arg: 2)->getEndLoc());
409
410 QualType Arg1Ty = TheCall->getArg(Arg: 0)->getType();
411 QualType Arg2Ty = TheCall->getArg(Arg: 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(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_non_vector)
418 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
419 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
420 TheCall->getArg(Arg: 1)->getEndLoc());
421 }
422
423 // Check the first two arguments are the same type.
424 if (!getASTContext().hasSameUnqualifiedType(T1: Arg1Ty, T2: Arg2Ty)) {
425 return Diag(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_incompatible_vector)
426 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
427 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
428 TheCall->getArg(Arg: 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