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