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
26namespace clang {
27
28SemaPPC::SemaPPC(Sema &S) : SemaBase(S) {}
29
30void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {
31 const auto *ICE = dyn_cast<ImplicitCastExpr>(Val: Arg->IgnoreParens());
32 if (!ICE)
33 return;
34
35 const auto *DR = dyn_cast<DeclRefExpr>(Val: ICE->getSubExpr());
36 if (!DR)
37 return;
38
39 const auto *PD = dyn_cast<ParmVarDecl>(Val: 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 BitSize: AA->getAlignment(Ctx&: getASTContext()));
49 if (Alignment.getQuantity() == 16) {
50 Diag(Loc: FD->getLocation(), DiagID: diag::warn_not_xl_compatible) << FD;
51 Diag(Loc, DiagID: diag::note_misaligned_member_used_here) << PD;
52 }
53 }
54 }
55}
56
57static 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
96bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
97 unsigned BuiltinID,
98 CallExpr *TheCall) {
99 ASTContext &Context = getASTContext();
100 bool IsTarget64Bit = TI.getTypeWidth(T: TI.getIntPtrType()) == 64;
101
102 if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
103 return Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 1, Low: 0, High: 1);
113 case PPC::BI__builtin_altivec_crypto_vshasigmaw:
114 case PPC::BI__builtin_altivec_crypto_vshasigmad:
115 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1) ||
116 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 15);
117 case PPC::BI__builtin_altivec_dss:
118 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 3);
119 case PPC::BI__builtin_tbegin:
120 case PPC::BI__builtin_tend:
121 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 1);
122 case PPC::BI__builtin_tsr:
123 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7);
124 case PPC::BI__builtin_tabortwc:
125 case PPC::BI__builtin_tabortdc:
126 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31);
127 case PPC::BI__builtin_tabortwci:
128 case PPC::BI__builtin_tabortdci:
129 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31) ||
130 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 1))
136 return true;
137 [[fallthrough]];
138 case PPC::BI__builtin_pack_longdouble:
139 if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
140 return Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 2, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 1);
153 case PPC::BI__builtin_altivec_vgnb:
154 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 2, High: 7);
155 case PPC::BI__builtin_vsx_xxeval:
156 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 255);
157 case PPC::BI__builtin_altivec_vsldbi:
158 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
159 case PPC::BI__builtin_altivec_vsrdbi:
160 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
161 case PPC::BI__builtin_vsx_xxpermx:
162 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 7);
163 case PPC::BI__builtin_ppc_tw:
164 case PPC::BI__builtin_ppc_tdw:
165 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 1, High: 31);
166 case PPC::BI__builtin_ppc_cmprb:
167 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 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, ArgNum: 2);
172 case PPC::BI__builtin_ppc_rlwimi:
173 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 31) ||
174 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
175 case PPC::BI__builtin_ppc_rldimi:
176 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 63) ||
177 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
178 case PPC::BI__builtin_ppc_addex: {
179 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 3))
180 return true;
181 // Output warning for reserved values 1 to 3.
182 int ArgValue =
183 TheCall->getArg(Arg: 2)->getIntegerConstantExpr(Ctx: Context)->getSExtValue();
184 if (ArgValue != 0)
185 Diag(Loc: TheCall->getBeginLoc(), DiagID: 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, ArgNum: 0, Low: 0, High: 31);
192 case PPC::BI__builtin_ppc_mtfsf:
193 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 255);
194 case PPC::BI__builtin_ppc_mtfsfi:
195 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7) ||
196 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 15);
197 case PPC::BI__builtin_ppc_alignx:
198 return SemaRef.BuiltinConstantArgPower2(TheCall, ArgNum: 0);
199 case PPC::BI__builtin_ppc_rdlam:
200 return SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 2);
201 case PPC::BI__builtin_vsx_ldrmb:
202 case PPC::BI__builtin_vsx_strmb:
203 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 1, High: 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, ArgNum: 1, Low: 0, High: 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, ArgNum: 1, Low: 0, High: 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(Arg: 0)->getType();
218 if (ArgType != QualType(Context.FloatTy) &&
219 ArgType != QualType(Context.DoubleTy) &&
220 ArgType != QualType(Context.Float128Ty))
221 return Diag(Loc: TheCall->getBeginLoc(),
222 DiagID: diag::err_ppc_invalid_test_data_class_type);
223 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 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(Loc: TheCall->getBeginLoc(), DiagID: 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(Arg: I)->getType() != ArgType)
247 return Diag(Loc: TheCall->getBeginLoc(),
248 DiagID: diag::err_typecheck_convert_incompatible)
249 << TheCall->getArg(Arg: 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.
262bool 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(Loc: TypeLoc, DiagID: 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.
284static 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(VectorType: Context.UnsignedCharTy, NumElts: 16,
291 VecKind: VectorKind::AltiVecVector);
292 case 'i': {
293 char *End;
294 unsigned size = strtoul(nptr: Str, endptr: &End, base: 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(nptr: Str, endptr: &End, base: 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(T: 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&: --Str, Context, Error, RequireICE, AllowTypeModifiers: true);
334 }
335}
336
337bool 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, Str&: TypeStr, Mask);
350 TheCall->setType(type);
351
352 while (*TypeStr != '\0') {
353 Mask = 0;
354 QualType ExpectedType = DecodePPCMMATypeFromStr(Context, Str&: TypeStr, Mask);
355 if (ArgNum >= TheCall->getNumArgs()) {
356 ArgNum++;
357 break;
358 }
359
360 Expr *Arg = TheCall->getArg(Arg: 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(Loc: Arg->getBeginLoc(),
376 DiagID: 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, Low: 0, High: Mask, RangeIsError: 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, Str&: TypeStr, Mask);
395 ArgNum++;
396 }
397 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ArgNum))
398 return true;
399
400 return false;
401}
402
403bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {
404 unsigned ExpectedNumArgs = 3;
405 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ExpectedNumArgs))
406 return true;
407
408 // Check the third argument is a compile time constant
409 if (!TheCall->getArg(Arg: 2)->isIntegerConstantExpr(Ctx: getASTContext()))
410 return Diag(Loc: TheCall->getBeginLoc(),
411 DiagID: diag::err_vsx_builtin_nonconstant_argument)
412 << 3 /* argument index */ << TheCall->getDirectCallee()
413 << SourceRange(TheCall->getArg(Arg: 2)->getBeginLoc(),
414 TheCall->getArg(Arg: 2)->getEndLoc());
415
416 QualType Arg1Ty = TheCall->getArg(Arg: 0)->getType();
417 QualType Arg2Ty = TheCall->getArg(Arg: 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(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_non_vector)
424 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
425 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
426 TheCall->getArg(Arg: 1)->getEndLoc());
427 }
428
429 // Check the first two arguments are the same type.
430 if (!getASTContext().hasSameUnqualifiedType(T1: Arg1Ty, T2: Arg2Ty)) {
431 return Diag(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_incompatible_vector)
432 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
433 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
434 TheCall->getArg(Arg: 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