llvm-project/clang/lib/Sema/SemaX86.cpp
keinflue 182d9a3cf0
[Clang] Use valid source loc for empty target_clones diagnostic (#173747)
For X86 and RISCV checking of target_clones attribute arguments
attempted to use the location of the first argument for diagnosing a
missing default argument.

However, if the argument list is empty, then this location doesn't exist
and causes an assertion.

This commit passes the location of the attribute itself to the
target-specific validation function in the case of X86 and RISCV in
order to provide a usable location for this diagnostic.

Fixes #173684

---

I am not sure whether this is intentional, but for AArch64 the
validation does not emit a diagnostic for missing `"default"` argument.
Therefore the issue did not appear there and I did not make any changes
to it. This is the only other target besides X86 and RISCV that supports
`target_clones`.
2026-01-01 19:28:53 +00:00

1115 lines
43 KiB
C++

//===------ SemaX86.cpp ---------- X86 target-specific routines -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis functions specific to X86.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaX86.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/TargetParser/Triple.h"
#include <bitset>
namespace clang {
SemaX86::SemaX86(Sema &S) : SemaBase(S) {}
// Check if the rounding mode is legal.
bool SemaX86::CheckBuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
// Indicates if this instruction has rounding control or just SAE.
bool HasRC = false;
unsigned ArgNum = 0;
switch (BuiltinID) {
default:
return false;
case X86::BI__builtin_ia32_vcvttsd2si32:
case X86::BI__builtin_ia32_vcvttsd2si64:
case X86::BI__builtin_ia32_vcvttsd2usi32:
case X86::BI__builtin_ia32_vcvttsd2usi64:
case X86::BI__builtin_ia32_vcvttss2si32:
case X86::BI__builtin_ia32_vcvttss2si64:
case X86::BI__builtin_ia32_vcvttss2usi32:
case X86::BI__builtin_ia32_vcvttss2usi64:
case X86::BI__builtin_ia32_vcvttsh2si32:
case X86::BI__builtin_ia32_vcvttsh2si64:
case X86::BI__builtin_ia32_vcvttsh2usi32:
case X86::BI__builtin_ia32_vcvttsh2usi64:
case X86::BI__builtin_ia32_vcvttsd2sis32:
case X86::BI__builtin_ia32_vcvttsd2usis32:
case X86::BI__builtin_ia32_vcvttss2sis32:
case X86::BI__builtin_ia32_vcvttss2usis32:
case X86::BI__builtin_ia32_vcvttsd2sis64:
case X86::BI__builtin_ia32_vcvttsd2usis64:
case X86::BI__builtin_ia32_vcvttss2sis64:
case X86::BI__builtin_ia32_vcvttss2usis64:
ArgNum = 1;
break;
case X86::BI__builtin_ia32_maxpd512:
case X86::BI__builtin_ia32_maxps512:
case X86::BI__builtin_ia32_minpd512:
case X86::BI__builtin_ia32_minps512:
case X86::BI__builtin_ia32_maxph512:
case X86::BI__builtin_ia32_minph512:
ArgNum = 2;
break;
case X86::BI__builtin_ia32_vcvtph2pd512_mask:
case X86::BI__builtin_ia32_vcvtph2psx512_mask:
case X86::BI__builtin_ia32_cvtps2pd512_mask:
case X86::BI__builtin_ia32_cvttpd2dq512_mask:
case X86::BI__builtin_ia32_cvttpd2qq512_mask:
case X86::BI__builtin_ia32_cvttpd2udq512_mask:
case X86::BI__builtin_ia32_cvttpd2uqq512_mask:
case X86::BI__builtin_ia32_cvttps2dq512_mask:
case X86::BI__builtin_ia32_cvttps2qq512_mask:
case X86::BI__builtin_ia32_cvttps2udq512_mask:
case X86::BI__builtin_ia32_cvttps2uqq512_mask:
case X86::BI__builtin_ia32_vcvttph2w512_mask:
case X86::BI__builtin_ia32_vcvttph2uw512_mask:
case X86::BI__builtin_ia32_vcvttph2dq512_mask:
case X86::BI__builtin_ia32_vcvttph2udq512_mask:
case X86::BI__builtin_ia32_vcvttph2qq512_mask:
case X86::BI__builtin_ia32_vcvttph2uqq512_mask:
case X86::BI__builtin_ia32_getexppd512_mask:
case X86::BI__builtin_ia32_getexpps512_mask:
case X86::BI__builtin_ia32_getexpph512_mask:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
case X86::BI__builtin_ia32_vcomish:
case X86::BI__builtin_ia32_vcvtph2ps512_mask:
case X86::BI__builtin_ia32_vcvttph2ibs512_mask:
case X86::BI__builtin_ia32_vcvttph2iubs512_mask:
case X86::BI__builtin_ia32_vcvttps2ibs512_mask:
case X86::BI__builtin_ia32_vcvttps2iubs512_mask:
ArgNum = 3;
break;
case X86::BI__builtin_ia32_cmppd512_mask:
case X86::BI__builtin_ia32_cmpps512_mask:
case X86::BI__builtin_ia32_cmpsd_mask:
case X86::BI__builtin_ia32_cmpss_mask:
case X86::BI__builtin_ia32_cmpsh_mask:
case X86::BI__builtin_ia32_vcvtsh2sd_round_mask:
case X86::BI__builtin_ia32_vcvtsh2ss_round_mask:
case X86::BI__builtin_ia32_cvtss2sd_round_mask:
case X86::BI__builtin_ia32_getexpsd128_round_mask:
case X86::BI__builtin_ia32_getexpss128_round_mask:
case X86::BI__builtin_ia32_getexpsh128_round_mask:
case X86::BI__builtin_ia32_getmantpd512_mask:
case X86::BI__builtin_ia32_getmantps512_mask:
case X86::BI__builtin_ia32_getmantph512_mask:
case X86::BI__builtin_ia32_maxsd_round_mask:
case X86::BI__builtin_ia32_maxss_round_mask:
case X86::BI__builtin_ia32_maxsh_round_mask:
case X86::BI__builtin_ia32_minsd_round_mask:
case X86::BI__builtin_ia32_minss_round_mask:
case X86::BI__builtin_ia32_minsh_round_mask:
case X86::BI__builtin_ia32_reducepd512_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
case X86::BI__builtin_ia32_reduceph512_mask:
case X86::BI__builtin_ia32_rndscalepd_mask:
case X86::BI__builtin_ia32_rndscaleps_mask:
case X86::BI__builtin_ia32_rndscaleph_mask:
ArgNum = 4;
break;
case X86::BI__builtin_ia32_fixupimmpd512_mask:
case X86::BI__builtin_ia32_fixupimmpd512_maskz:
case X86::BI__builtin_ia32_fixupimmps512_mask:
case X86::BI__builtin_ia32_fixupimmps512_maskz:
case X86::BI__builtin_ia32_fixupimmsd_mask:
case X86::BI__builtin_ia32_fixupimmsd_maskz:
case X86::BI__builtin_ia32_fixupimmss_mask:
case X86::BI__builtin_ia32_fixupimmss_maskz:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
case X86::BI__builtin_ia32_getmantsh_round_mask:
case X86::BI__builtin_ia32_rangepd512_mask:
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_rangesd128_round_mask:
case X86::BI__builtin_ia32_rangess128_round_mask:
case X86::BI__builtin_ia32_reducesd_mask:
case X86::BI__builtin_ia32_reducess_mask:
case X86::BI__builtin_ia32_reducesh_mask:
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
case X86::BI__builtin_ia32_rndscalesh_round_mask:
case X86::BI__builtin_ia32_vminmaxpd512_round_mask:
case X86::BI__builtin_ia32_vminmaxps512_round_mask:
case X86::BI__builtin_ia32_vminmaxph512_round_mask:
case X86::BI__builtin_ia32_vminmaxsd_round_mask:
case X86::BI__builtin_ia32_vminmaxsh_round_mask:
case X86::BI__builtin_ia32_vminmaxss_round_mask:
ArgNum = 5;
break;
case X86::BI__builtin_ia32_vcvtsd2si64:
case X86::BI__builtin_ia32_vcvtsd2si32:
case X86::BI__builtin_ia32_vcvtsd2usi32:
case X86::BI__builtin_ia32_vcvtsd2usi64:
case X86::BI__builtin_ia32_vcvtss2si32:
case X86::BI__builtin_ia32_vcvtss2si64:
case X86::BI__builtin_ia32_vcvtss2usi32:
case X86::BI__builtin_ia32_vcvtss2usi64:
case X86::BI__builtin_ia32_vcvtsh2si32:
case X86::BI__builtin_ia32_vcvtsh2si64:
case X86::BI__builtin_ia32_vcvtsh2usi32:
case X86::BI__builtin_ia32_vcvtsh2usi64:
case X86::BI__builtin_ia32_sqrtpd512:
case X86::BI__builtin_ia32_sqrtps512:
case X86::BI__builtin_ia32_sqrtph512:
ArgNum = 1;
HasRC = true;
break;
case X86::BI__builtin_ia32_addph512:
case X86::BI__builtin_ia32_divph512:
case X86::BI__builtin_ia32_mulph512:
case X86::BI__builtin_ia32_subph512:
case X86::BI__builtin_ia32_addpd512:
case X86::BI__builtin_ia32_addps512:
case X86::BI__builtin_ia32_divpd512:
case X86::BI__builtin_ia32_divps512:
case X86::BI__builtin_ia32_mulpd512:
case X86::BI__builtin_ia32_mulps512:
case X86::BI__builtin_ia32_subpd512:
case X86::BI__builtin_ia32_subps512:
case X86::BI__builtin_ia32_cvtsi2sd64:
case X86::BI__builtin_ia32_cvtsi2ss32:
case X86::BI__builtin_ia32_cvtsi2ss64:
case X86::BI__builtin_ia32_cvtusi2sd64:
case X86::BI__builtin_ia32_cvtusi2ss32:
case X86::BI__builtin_ia32_cvtusi2ss64:
case X86::BI__builtin_ia32_vcvtusi2sh:
case X86::BI__builtin_ia32_vcvtusi642sh:
case X86::BI__builtin_ia32_vcvtsi2sh:
case X86::BI__builtin_ia32_vcvtsi642sh:
ArgNum = 2;
HasRC = true;
break;
case X86::BI__builtin_ia32_cvtdq2ps512_mask:
case X86::BI__builtin_ia32_cvtudq2ps512_mask:
case X86::BI__builtin_ia32_vcvtpd2ph512_mask:
case X86::BI__builtin_ia32_vcvtps2phx512_mask:
case X86::BI__builtin_ia32_cvtpd2ps512_mask:
case X86::BI__builtin_ia32_cvtpd2dq512_mask:
case X86::BI__builtin_ia32_cvtpd2qq512_mask:
case X86::BI__builtin_ia32_cvtpd2udq512_mask:
case X86::BI__builtin_ia32_cvtpd2uqq512_mask:
case X86::BI__builtin_ia32_cvtps2dq512_mask:
case X86::BI__builtin_ia32_cvtps2qq512_mask:
case X86::BI__builtin_ia32_cvtps2udq512_mask:
case X86::BI__builtin_ia32_cvtps2uqq512_mask:
case X86::BI__builtin_ia32_cvtqq2pd512_mask:
case X86::BI__builtin_ia32_cvtqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
case X86::BI__builtin_ia32_vcvtdq2ph512_mask:
case X86::BI__builtin_ia32_vcvtudq2ph512_mask:
case X86::BI__builtin_ia32_vcvtw2ph512_mask:
case X86::BI__builtin_ia32_vcvtuw2ph512_mask:
case X86::BI__builtin_ia32_vcvtph2w512_mask:
case X86::BI__builtin_ia32_vcvtph2uw512_mask:
case X86::BI__builtin_ia32_vcvtph2dq512_mask:
case X86::BI__builtin_ia32_vcvtph2udq512_mask:
case X86::BI__builtin_ia32_vcvtph2qq512_mask:
case X86::BI__builtin_ia32_vcvtph2uqq512_mask:
case X86::BI__builtin_ia32_vcvtqq2ph512_mask:
case X86::BI__builtin_ia32_vcvtuqq2ph512_mask:
case X86::BI__builtin_ia32_vcvtph2ibs512_mask:
case X86::BI__builtin_ia32_vcvtph2iubs512_mask:
case X86::BI__builtin_ia32_vcvtps2ibs512_mask:
case X86::BI__builtin_ia32_vcvtps2iubs512_mask:
ArgNum = 3;
HasRC = true;
break;
case X86::BI__builtin_ia32_addsh_round_mask:
case X86::BI__builtin_ia32_addss_round_mask:
case X86::BI__builtin_ia32_addsd_round_mask:
case X86::BI__builtin_ia32_divsh_round_mask:
case X86::BI__builtin_ia32_divss_round_mask:
case X86::BI__builtin_ia32_divsd_round_mask:
case X86::BI__builtin_ia32_mulsh_round_mask:
case X86::BI__builtin_ia32_mulss_round_mask:
case X86::BI__builtin_ia32_mulsd_round_mask:
case X86::BI__builtin_ia32_subsh_round_mask:
case X86::BI__builtin_ia32_subss_round_mask:
case X86::BI__builtin_ia32_subsd_round_mask:
case X86::BI__builtin_ia32_scalefph512_mask:
case X86::BI__builtin_ia32_scalefpd512_mask:
case X86::BI__builtin_ia32_scalefps512_mask:
case X86::BI__builtin_ia32_scalefsd_round_mask:
case X86::BI__builtin_ia32_scalefss_round_mask:
case X86::BI__builtin_ia32_scalefsh_round_mask:
case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
case X86::BI__builtin_ia32_vcvtss2sh_round_mask:
case X86::BI__builtin_ia32_vcvtsd2sh_round_mask:
case X86::BI__builtin_ia32_sqrtsd_round_mask:
case X86::BI__builtin_ia32_sqrtss_round_mask:
case X86::BI__builtin_ia32_sqrtsh_round_mask:
case X86::BI__builtin_ia32_vfmaddsd3_mask:
case X86::BI__builtin_ia32_vfmaddsd3_maskz:
case X86::BI__builtin_ia32_vfmaddsd3_mask3:
case X86::BI__builtin_ia32_vfmaddss3_mask:
case X86::BI__builtin_ia32_vfmaddss3_maskz:
case X86::BI__builtin_ia32_vfmaddss3_mask3:
case X86::BI__builtin_ia32_vfmaddsh3_mask:
case X86::BI__builtin_ia32_vfmaddsh3_maskz:
case X86::BI__builtin_ia32_vfmaddsh3_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_mask:
case X86::BI__builtin_ia32_vfmaddpd512_maskz:
case X86::BI__builtin_ia32_vfmaddpd512_mask3:
case X86::BI__builtin_ia32_vfmsubpd512_mask3:
case X86::BI__builtin_ia32_vfmaddps512_mask:
case X86::BI__builtin_ia32_vfmaddps512_maskz:
case X86::BI__builtin_ia32_vfmaddps512_mask3:
case X86::BI__builtin_ia32_vfmsubps512_mask3:
case X86::BI__builtin_ia32_vfmaddph512_mask:
case X86::BI__builtin_ia32_vfmaddph512_maskz:
case X86::BI__builtin_ia32_vfmaddph512_mask3:
case X86::BI__builtin_ia32_vfmsubph512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubps512_mask:
case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
case X86::BI__builtin_ia32_vfmaddsubph512_mask:
case X86::BI__builtin_ia32_vfmaddsubph512_maskz:
case X86::BI__builtin_ia32_vfmaddsubph512_mask3:
case X86::BI__builtin_ia32_vfmsubaddph512_mask3:
case X86::BI__builtin_ia32_vfmaddcsh_mask:
case X86::BI__builtin_ia32_vfmaddcsh_round_mask:
case X86::BI__builtin_ia32_vfmaddcsh_round_mask3:
case X86::BI__builtin_ia32_vfmaddcph512_mask:
case X86::BI__builtin_ia32_vfmaddcph512_maskz:
case X86::BI__builtin_ia32_vfmaddcph512_mask3:
case X86::BI__builtin_ia32_vfcmaddcsh_mask:
case X86::BI__builtin_ia32_vfcmaddcsh_round_mask:
case X86::BI__builtin_ia32_vfcmaddcsh_round_mask3:
case X86::BI__builtin_ia32_vfcmaddcph512_mask:
case X86::BI__builtin_ia32_vfcmaddcph512_maskz:
case X86::BI__builtin_ia32_vfcmaddcph512_mask3:
case X86::BI__builtin_ia32_vfmulcsh_mask:
case X86::BI__builtin_ia32_vfmulcph512_mask:
case X86::BI__builtin_ia32_vfcmulcsh_mask:
case X86::BI__builtin_ia32_vfcmulcph512_mask:
case X86::BI__builtin_ia32_vcvt2ps2phx512_mask:
ArgNum = 4;
HasRC = true;
break;
case X86::BI__builtin_ia32_vcvttpd2dqs512_round_mask:
case X86::BI__builtin_ia32_vcvttpd2udqs512_round_mask:
case X86::BI__builtin_ia32_vcvttpd2qqs512_round_mask:
case X86::BI__builtin_ia32_vcvttpd2uqqs512_round_mask:
case X86::BI__builtin_ia32_vcvttps2dqs512_round_mask:
case X86::BI__builtin_ia32_vcvttps2udqs512_round_mask:
case X86::BI__builtin_ia32_vcvttps2qqs512_round_mask:
case X86::BI__builtin_ia32_vcvttps2uqqs512_round_mask:
ArgNum = 3;
break;
}
llvm::APSInt Result;
// We can't check the value of a dependent argument.
Expr *Arg = TheCall->getArg(ArgNum);
if (Arg->isTypeDependent() || Arg->isValueDependent())
return false;
// Check constant-ness first.
if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Result))
return true;
// Make sure rounding mode is either ROUND_CUR_DIRECTION or ROUND_NO_EXC bit
// is set. If the intrinsic has rounding control(bits 1:0), make sure its only
// combined with ROUND_NO_EXC. If the intrinsic does not have rounding
// control, allow ROUND_NO_EXC and ROUND_CUR_DIRECTION together.
if (Result == 4 /*ROUND_CUR_DIRECTION*/ || Result == 8 /*ROUND_NO_EXC*/ ||
(!HasRC && Result == 12 /*ROUND_CUR_DIRECTION|ROUND_NO_EXC*/) ||
(HasRC && Result.getZExtValue() >= 8 && Result.getZExtValue() <= 11))
return false;
return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_rounding)
<< Arg->getSourceRange();
}
// Check if the gather/scatter scale is legal.
bool SemaX86::CheckBuiltinGatherScatterScale(unsigned BuiltinID,
CallExpr *TheCall) {
unsigned ArgNum = 0;
switch (BuiltinID) {
default:
return false;
case X86::BI__builtin_ia32_gatherd_pd:
case X86::BI__builtin_ia32_gatherd_pd256:
case X86::BI__builtin_ia32_gatherq_pd:
case X86::BI__builtin_ia32_gatherq_pd256:
case X86::BI__builtin_ia32_gatherd_ps:
case X86::BI__builtin_ia32_gatherd_ps256:
case X86::BI__builtin_ia32_gatherq_ps:
case X86::BI__builtin_ia32_gatherq_ps256:
case X86::BI__builtin_ia32_gatherd_q:
case X86::BI__builtin_ia32_gatherd_q256:
case X86::BI__builtin_ia32_gatherq_q:
case X86::BI__builtin_ia32_gatherq_q256:
case X86::BI__builtin_ia32_gatherd_d:
case X86::BI__builtin_ia32_gatherd_d256:
case X86::BI__builtin_ia32_gatherq_d:
case X86::BI__builtin_ia32_gatherq_d256:
case X86::BI__builtin_ia32_gather3div2df:
case X86::BI__builtin_ia32_gather3div2di:
case X86::BI__builtin_ia32_gather3div4df:
case X86::BI__builtin_ia32_gather3div4di:
case X86::BI__builtin_ia32_gather3div4sf:
case X86::BI__builtin_ia32_gather3div4si:
case X86::BI__builtin_ia32_gather3div8sf:
case X86::BI__builtin_ia32_gather3div8si:
case X86::BI__builtin_ia32_gather3siv2df:
case X86::BI__builtin_ia32_gather3siv2di:
case X86::BI__builtin_ia32_gather3siv4df:
case X86::BI__builtin_ia32_gather3siv4di:
case X86::BI__builtin_ia32_gather3siv4sf:
case X86::BI__builtin_ia32_gather3siv4si:
case X86::BI__builtin_ia32_gather3siv8sf:
case X86::BI__builtin_ia32_gather3siv8si:
case X86::BI__builtin_ia32_gathersiv8df:
case X86::BI__builtin_ia32_gathersiv16sf:
case X86::BI__builtin_ia32_gatherdiv8df:
case X86::BI__builtin_ia32_gatherdiv16sf:
case X86::BI__builtin_ia32_gathersiv8di:
case X86::BI__builtin_ia32_gathersiv16si:
case X86::BI__builtin_ia32_gatherdiv8di:
case X86::BI__builtin_ia32_gatherdiv16si:
case X86::BI__builtin_ia32_scatterdiv2df:
case X86::BI__builtin_ia32_scatterdiv2di:
case X86::BI__builtin_ia32_scatterdiv4df:
case X86::BI__builtin_ia32_scatterdiv4di:
case X86::BI__builtin_ia32_scatterdiv4sf:
case X86::BI__builtin_ia32_scatterdiv4si:
case X86::BI__builtin_ia32_scatterdiv8sf:
case X86::BI__builtin_ia32_scatterdiv8si:
case X86::BI__builtin_ia32_scattersiv2df:
case X86::BI__builtin_ia32_scattersiv2di:
case X86::BI__builtin_ia32_scattersiv4df:
case X86::BI__builtin_ia32_scattersiv4di:
case X86::BI__builtin_ia32_scattersiv4sf:
case X86::BI__builtin_ia32_scattersiv4si:
case X86::BI__builtin_ia32_scattersiv8sf:
case X86::BI__builtin_ia32_scattersiv8si:
case X86::BI__builtin_ia32_scattersiv8df:
case X86::BI__builtin_ia32_scattersiv16sf:
case X86::BI__builtin_ia32_scatterdiv8df:
case X86::BI__builtin_ia32_scatterdiv16sf:
case X86::BI__builtin_ia32_scattersiv8di:
case X86::BI__builtin_ia32_scattersiv16si:
case X86::BI__builtin_ia32_scatterdiv8di:
case X86::BI__builtin_ia32_scatterdiv16si:
ArgNum = 4;
break;
}
llvm::APSInt Result;
// We can't check the value of a dependent argument.
Expr *Arg = TheCall->getArg(ArgNum);
if (Arg->isTypeDependent() || Arg->isValueDependent())
return false;
// Check constant-ness first.
if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Result))
return true;
if (Result == 1 || Result == 2 || Result == 4 || Result == 8)
return false;
return Diag(TheCall->getBeginLoc(), diag::err_x86_builtin_invalid_scale)
<< Arg->getSourceRange();
}
enum { TileRegLow = 0, TileRegHigh = 7 };
bool SemaX86::CheckBuiltinTileArgumentsRange(CallExpr *TheCall,
ArrayRef<int> ArgNums) {
for (int ArgNum : ArgNums) {
if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, TileRegLow,
TileRegHigh))
return true;
}
return false;
}
bool SemaX86::CheckBuiltinTileDuplicate(CallExpr *TheCall,
ArrayRef<int> ArgNums) {
// Because the max number of tile register is TileRegHigh + 1, so here we use
// each bit to represent the usage of them in bitset.
std::bitset<TileRegHigh + 1> ArgValues;
for (int ArgNum : ArgNums) {
Expr *Arg = TheCall->getArg(ArgNum);
if (Arg->isTypeDependent() || Arg->isValueDependent())
continue;
llvm::APSInt Result;
if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Result))
return true;
int ArgExtValue = Result.getExtValue();
assert((ArgExtValue >= TileRegLow && ArgExtValue <= TileRegHigh) &&
"Incorrect tile register num.");
if (ArgValues.test(ArgExtValue))
return Diag(TheCall->getBeginLoc(),
diag::err_x86_builtin_tile_arg_duplicate)
<< TheCall->getArg(ArgNum)->getSourceRange();
ArgValues.set(ArgExtValue);
}
return false;
}
bool SemaX86::CheckBuiltinTileRangeAndDuplicate(CallExpr *TheCall,
ArrayRef<int> ArgNums) {
return CheckBuiltinTileArgumentsRange(TheCall, ArgNums) ||
CheckBuiltinTileDuplicate(TheCall, ArgNums);
}
bool SemaX86::CheckBuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall) {
switch (BuiltinID) {
default:
return false;
case X86::BI__builtin_ia32_tileloadd64:
case X86::BI__builtin_ia32_tileloaddt164:
case X86::BI__builtin_ia32_tileloaddrs64:
case X86::BI__builtin_ia32_tileloaddrst164:
case X86::BI__builtin_ia32_tilestored64:
case X86::BI__builtin_ia32_tilezero:
case X86::BI__builtin_ia32_tcvtrowps2bf16h:
case X86::BI__builtin_ia32_tcvtrowps2bf16l:
case X86::BI__builtin_ia32_tcvtrowps2phh:
case X86::BI__builtin_ia32_tcvtrowps2phl:
case X86::BI__builtin_ia32_tcvtrowd2ps:
case X86::BI__builtin_ia32_tilemovrow:
return CheckBuiltinTileArgumentsRange(TheCall, 0);
case X86::BI__builtin_ia32_tdpbssd:
case X86::BI__builtin_ia32_tdpbsud:
case X86::BI__builtin_ia32_tdpbusd:
case X86::BI__builtin_ia32_tdpbuud:
case X86::BI__builtin_ia32_tdpbf16ps:
case X86::BI__builtin_ia32_tdpfp16ps:
case X86::BI__builtin_ia32_tcmmimfp16ps:
case X86::BI__builtin_ia32_tcmmrlfp16ps:
case X86::BI__builtin_ia32_tdpbf8ps:
case X86::BI__builtin_ia32_tdpbhf8ps:
case X86::BI__builtin_ia32_tdphbf8ps:
case X86::BI__builtin_ia32_tdphf8ps:
case X86::BI__builtin_ia32_tmmultf32ps:
return CheckBuiltinTileRangeAndDuplicate(TheCall, {0, 1, 2});
case X86::BI__builtin_ia32_tcvtrowps2bf16hi:
case X86::BI__builtin_ia32_tcvtrowps2bf16li:
case X86::BI__builtin_ia32_tcvtrowps2phhi:
case X86::BI__builtin_ia32_tcvtrowps2phli:
case X86::BI__builtin_ia32_tcvtrowd2psi:
case X86::BI__builtin_ia32_tilemovrowi:
return CheckBuiltinTileArgumentsRange(TheCall, 0) ||
SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 255,
/*RangeIsError=*/false);
}
}
static bool isX86_32Builtin(unsigned BuiltinID) {
// These builtins only work on x86-32 targets.
switch (BuiltinID) {
case X86::BI__builtin_ia32_readeflags_u32:
case X86::BI__builtin_ia32_writeeflags_u32:
return true;
}
return false;
}
bool SemaX86::CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall) {
// Check for 32-bit only builtins on a 64-bit target.
const llvm::Triple &TT = TI.getTriple();
if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID))
return Diag(TheCall->getCallee()->getBeginLoc(),
diag::err_32_bit_builtin_64_bit_tgt);
// If the intrinsic has rounding or SAE make sure its valid.
if (CheckBuiltinRoundingOrSAE(BuiltinID, TheCall))
return true;
// If the intrinsic has a gather/scatter scale immediate make sure its valid.
if (CheckBuiltinGatherScatterScale(BuiltinID, TheCall))
return true;
// If the intrinsic has a tile arguments, make sure they are valid.
if (CheckBuiltinTileArguments(BuiltinID, TheCall))
return true;
// For intrinsics which take an immediate value as part of the instruction,
// range check them here.
int i = 0, l = 0, u = 0;
switch (BuiltinID) {
default:
return false;
case X86::BI__builtin_ia32_vec_ext_v2di:
case X86::BI__builtin_ia32_vextractf128_pd256:
case X86::BI__builtin_ia32_vextractf128_ps256:
case X86::BI__builtin_ia32_vextractf128_si256:
case X86::BI__builtin_ia32_extract128i256:
case X86::BI__builtin_ia32_extractf64x4_mask:
case X86::BI__builtin_ia32_extracti64x4_mask:
case X86::BI__builtin_ia32_extractf32x8_mask:
case X86::BI__builtin_ia32_extracti32x8_mask:
case X86::BI__builtin_ia32_extractf64x2_256_mask:
case X86::BI__builtin_ia32_extracti64x2_256_mask:
case X86::BI__builtin_ia32_extractf32x4_256_mask:
case X86::BI__builtin_ia32_extracti32x4_256_mask:
i = 1;
l = 0;
u = 1;
break;
case X86::BI__builtin_ia32_vec_set_v2di:
case X86::BI__builtin_ia32_vinsertf128_pd256:
case X86::BI__builtin_ia32_vinsertf128_ps256:
case X86::BI__builtin_ia32_vinsertf128_si256:
case X86::BI__builtin_ia32_insert128i256:
case X86::BI__builtin_ia32_insertf32x8:
case X86::BI__builtin_ia32_inserti32x8:
case X86::BI__builtin_ia32_insertf64x4:
case X86::BI__builtin_ia32_inserti64x4:
case X86::BI__builtin_ia32_insertf64x2_256:
case X86::BI__builtin_ia32_inserti64x2_256:
case X86::BI__builtin_ia32_insertf32x4_256:
case X86::BI__builtin_ia32_inserti32x4_256:
i = 2;
l = 0;
u = 1;
break;
case X86::BI__builtin_ia32_vpermilpd:
case X86::BI__builtin_ia32_vec_ext_v4hi:
case X86::BI__builtin_ia32_vec_ext_v4si:
case X86::BI__builtin_ia32_vec_ext_v4sf:
case X86::BI__builtin_ia32_vec_ext_v4di:
case X86::BI__builtin_ia32_extractf32x4_mask:
case X86::BI__builtin_ia32_extracti32x4_mask:
case X86::BI__builtin_ia32_extractf64x2_512_mask:
case X86::BI__builtin_ia32_extracti64x2_512_mask:
i = 1;
l = 0;
u = 3;
break;
case X86::BI_mm_prefetch:
case X86::BI__builtin_ia32_vec_ext_v8hi:
case X86::BI__builtin_ia32_vec_ext_v8si:
i = 1;
l = 0;
u = 7;
break;
case X86::BI__builtin_ia32_sha1rnds4:
case X86::BI__builtin_ia32_blendpd:
case X86::BI__builtin_ia32_shufpd:
case X86::BI__builtin_ia32_vec_set_v4hi:
case X86::BI__builtin_ia32_vec_set_v4si:
case X86::BI__builtin_ia32_vec_set_v4di:
case X86::BI__builtin_ia32_shuf_f32x4_256:
case X86::BI__builtin_ia32_shuf_f64x2_256:
case X86::BI__builtin_ia32_shuf_i32x4_256:
case X86::BI__builtin_ia32_shuf_i64x2_256:
case X86::BI__builtin_ia32_insertf64x2_512:
case X86::BI__builtin_ia32_inserti64x2_512:
case X86::BI__builtin_ia32_insertf32x4:
case X86::BI__builtin_ia32_inserti32x4:
i = 2;
l = 0;
u = 3;
break;
case X86::BI__builtin_ia32_vpermil2pd:
case X86::BI__builtin_ia32_vpermil2pd256:
case X86::BI__builtin_ia32_vpermil2ps:
case X86::BI__builtin_ia32_vpermil2ps256:
i = 3;
l = 0;
u = 3;
break;
case X86::BI__builtin_ia32_cmpb128_mask:
case X86::BI__builtin_ia32_cmpw128_mask:
case X86::BI__builtin_ia32_cmpd128_mask:
case X86::BI__builtin_ia32_cmpq128_mask:
case X86::BI__builtin_ia32_cmpb256_mask:
case X86::BI__builtin_ia32_cmpw256_mask:
case X86::BI__builtin_ia32_cmpd256_mask:
case X86::BI__builtin_ia32_cmpq256_mask:
case X86::BI__builtin_ia32_cmpb512_mask:
case X86::BI__builtin_ia32_cmpw512_mask:
case X86::BI__builtin_ia32_cmpd512_mask:
case X86::BI__builtin_ia32_cmpq512_mask:
case X86::BI__builtin_ia32_ucmpb128_mask:
case X86::BI__builtin_ia32_ucmpw128_mask:
case X86::BI__builtin_ia32_ucmpd128_mask:
case X86::BI__builtin_ia32_ucmpq128_mask:
case X86::BI__builtin_ia32_ucmpb256_mask:
case X86::BI__builtin_ia32_ucmpw256_mask:
case X86::BI__builtin_ia32_ucmpd256_mask:
case X86::BI__builtin_ia32_ucmpq256_mask:
case X86::BI__builtin_ia32_ucmpb512_mask:
case X86::BI__builtin_ia32_ucmpw512_mask:
case X86::BI__builtin_ia32_ucmpd512_mask:
case X86::BI__builtin_ia32_ucmpq512_mask:
case X86::BI__builtin_ia32_vpcomub:
case X86::BI__builtin_ia32_vpcomuw:
case X86::BI__builtin_ia32_vpcomud:
case X86::BI__builtin_ia32_vpcomuq:
case X86::BI__builtin_ia32_vpcomb:
case X86::BI__builtin_ia32_vpcomw:
case X86::BI__builtin_ia32_vpcomd:
case X86::BI__builtin_ia32_vpcomq:
case X86::BI__builtin_ia32_vec_set_v8hi:
case X86::BI__builtin_ia32_vec_set_v8si:
i = 2;
l = 0;
u = 7;
break;
case X86::BI__builtin_ia32_vpermilpd256:
case X86::BI__builtin_ia32_roundps:
case X86::BI__builtin_ia32_roundpd:
case X86::BI__builtin_ia32_roundps256:
case X86::BI__builtin_ia32_roundpd256:
case X86::BI__builtin_ia32_getmantpd128_mask:
case X86::BI__builtin_ia32_getmantpd256_mask:
case X86::BI__builtin_ia32_getmantps128_mask:
case X86::BI__builtin_ia32_getmantps256_mask:
case X86::BI__builtin_ia32_getmantpd512_mask:
case X86::BI__builtin_ia32_getmantps512_mask:
case X86::BI__builtin_ia32_getmantph128_mask:
case X86::BI__builtin_ia32_getmantph256_mask:
case X86::BI__builtin_ia32_getmantph512_mask:
case X86::BI__builtin_ia32_vec_ext_v16qi:
case X86::BI__builtin_ia32_vec_ext_v16hi:
i = 1;
l = 0;
u = 15;
break;
case X86::BI__builtin_ia32_pblendd128:
case X86::BI__builtin_ia32_blendps:
case X86::BI__builtin_ia32_blendpd256:
case X86::BI__builtin_ia32_shufpd256:
case X86::BI__builtin_ia32_roundss:
case X86::BI__builtin_ia32_roundsd:
case X86::BI__builtin_ia32_rangepd128_mask:
case X86::BI__builtin_ia32_rangepd256_mask:
case X86::BI__builtin_ia32_rangepd512_mask:
case X86::BI__builtin_ia32_rangeps128_mask:
case X86::BI__builtin_ia32_rangeps256_mask:
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
case X86::BI__builtin_ia32_getmantsh_round_mask:
case X86::BI__builtin_ia32_vec_set_v16qi:
case X86::BI__builtin_ia32_vec_set_v16hi:
i = 2;
l = 0;
u = 15;
break;
case X86::BI__builtin_ia32_vec_ext_v32qi:
i = 1;
l = 0;
u = 31;
break;
case X86::BI__builtin_ia32_cmpps:
case X86::BI__builtin_ia32_cmpss:
case X86::BI__builtin_ia32_cmppd:
case X86::BI__builtin_ia32_cmpsd:
case X86::BI__builtin_ia32_cmpps256:
case X86::BI__builtin_ia32_cmppd256:
case X86::BI__builtin_ia32_cmpps128_mask:
case X86::BI__builtin_ia32_cmppd128_mask:
case X86::BI__builtin_ia32_cmpps256_mask:
case X86::BI__builtin_ia32_cmppd256_mask:
case X86::BI__builtin_ia32_cmpps512_mask:
case X86::BI__builtin_ia32_cmppd512_mask:
case X86::BI__builtin_ia32_cmpsd_mask:
case X86::BI__builtin_ia32_cmpss_mask:
case X86::BI__builtin_ia32_vec_set_v32qi:
i = 2;
l = 0;
u = 31;
break;
case X86::BI__builtin_ia32_permdf256:
case X86::BI__builtin_ia32_permdi256:
case X86::BI__builtin_ia32_permdf512:
case X86::BI__builtin_ia32_permdi512:
case X86::BI__builtin_ia32_vpermilps:
case X86::BI__builtin_ia32_vpermilps256:
case X86::BI__builtin_ia32_vpermilpd512:
case X86::BI__builtin_ia32_vpermilps512:
case X86::BI__builtin_ia32_pshufd:
case X86::BI__builtin_ia32_pshufd256:
case X86::BI__builtin_ia32_pshufd512:
case X86::BI__builtin_ia32_pshufhw:
case X86::BI__builtin_ia32_pshufhw256:
case X86::BI__builtin_ia32_pshufhw512:
case X86::BI__builtin_ia32_pshuflw:
case X86::BI__builtin_ia32_pshuflw256:
case X86::BI__builtin_ia32_pshuflw512:
case X86::BI__builtin_ia32_vcvtps2ph:
case X86::BI__builtin_ia32_vcvtps2ph_mask:
case X86::BI__builtin_ia32_vcvtps2ph256:
case X86::BI__builtin_ia32_vcvtps2ph256_mask:
case X86::BI__builtin_ia32_vcvtps2ph512_mask:
case X86::BI__builtin_ia32_rndscaleps_128_mask:
case X86::BI__builtin_ia32_rndscalepd_128_mask:
case X86::BI__builtin_ia32_rndscaleps_256_mask:
case X86::BI__builtin_ia32_rndscalepd_256_mask:
case X86::BI__builtin_ia32_rndscaleps_mask:
case X86::BI__builtin_ia32_rndscalepd_mask:
case X86::BI__builtin_ia32_rndscaleph_mask:
case X86::BI__builtin_ia32_vrndscalebf16_128_mask:
case X86::BI__builtin_ia32_vrndscalebf16_256_mask:
case X86::BI__builtin_ia32_vrndscalebf16_mask:
case X86::BI__builtin_ia32_reducepd128_mask:
case X86::BI__builtin_ia32_reducepd256_mask:
case X86::BI__builtin_ia32_reducepd512_mask:
case X86::BI__builtin_ia32_reduceps128_mask:
case X86::BI__builtin_ia32_reduceps256_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
case X86::BI__builtin_ia32_reduceph128_mask:
case X86::BI__builtin_ia32_reduceph256_mask:
case X86::BI__builtin_ia32_reduceph512_mask:
case X86::BI__builtin_ia32_vreducebf16128_mask:
case X86::BI__builtin_ia32_vreducebf16256_mask:
case X86::BI__builtin_ia32_vreducebf16512_mask:
case X86::BI__builtin_ia32_prold512:
case X86::BI__builtin_ia32_prolq512:
case X86::BI__builtin_ia32_prold128:
case X86::BI__builtin_ia32_prold256:
case X86::BI__builtin_ia32_prolq128:
case X86::BI__builtin_ia32_prolq256:
case X86::BI__builtin_ia32_prord512:
case X86::BI__builtin_ia32_prorq512:
case X86::BI__builtin_ia32_prord128:
case X86::BI__builtin_ia32_prord256:
case X86::BI__builtin_ia32_prorq128:
case X86::BI__builtin_ia32_prorq256:
case X86::BI__builtin_ia32_fpclasspd128_mask:
case X86::BI__builtin_ia32_fpclasspd256_mask:
case X86::BI__builtin_ia32_fpclassps128_mask:
case X86::BI__builtin_ia32_fpclassps256_mask:
case X86::BI__builtin_ia32_fpclassps512_mask:
case X86::BI__builtin_ia32_fpclasspd512_mask:
case X86::BI__builtin_ia32_fpclassph128_mask:
case X86::BI__builtin_ia32_fpclassph256_mask:
case X86::BI__builtin_ia32_fpclassph512_mask:
case X86::BI__builtin_ia32_vfpclassbf16128_mask:
case X86::BI__builtin_ia32_vfpclassbf16256_mask:
case X86::BI__builtin_ia32_vfpclassbf16512_mask:
case X86::BI__builtin_ia32_fpclasssd_mask:
case X86::BI__builtin_ia32_fpclassss_mask:
case X86::BI__builtin_ia32_fpclasssh_mask:
case X86::BI__builtin_ia32_pslldqi128_byteshift:
case X86::BI__builtin_ia32_pslldqi256_byteshift:
case X86::BI__builtin_ia32_pslldqi512_byteshift:
case X86::BI__builtin_ia32_psrldqi128_byteshift:
case X86::BI__builtin_ia32_psrldqi256_byteshift:
case X86::BI__builtin_ia32_psrldqi512_byteshift:
case X86::BI__builtin_ia32_kshiftliqi:
case X86::BI__builtin_ia32_kshiftlihi:
case X86::BI__builtin_ia32_kshiftlisi:
case X86::BI__builtin_ia32_kshiftlidi:
case X86::BI__builtin_ia32_kshiftriqi:
case X86::BI__builtin_ia32_kshiftrihi:
case X86::BI__builtin_ia32_kshiftrisi:
case X86::BI__builtin_ia32_kshiftridi:
i = 1;
l = 0;
u = 255;
break;
case X86::BI__builtin_ia32_vperm2f128_pd256:
case X86::BI__builtin_ia32_vperm2f128_ps256:
case X86::BI__builtin_ia32_vperm2f128_si256:
case X86::BI__builtin_ia32_permti256:
case X86::BI__builtin_ia32_pblendw128:
case X86::BI__builtin_ia32_pblendw256:
case X86::BI__builtin_ia32_blendps256:
case X86::BI__builtin_ia32_pblendd256:
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
case X86::BI__builtin_ia32_palignr512:
case X86::BI__builtin_ia32_alignq512:
case X86::BI__builtin_ia32_alignd512:
case X86::BI__builtin_ia32_alignd128:
case X86::BI__builtin_ia32_alignd256:
case X86::BI__builtin_ia32_alignq128:
case X86::BI__builtin_ia32_alignq256:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
case X86::BI__builtin_ia32_shuf_f32x4:
case X86::BI__builtin_ia32_shuf_f64x2:
case X86::BI__builtin_ia32_shuf_i32x4:
case X86::BI__builtin_ia32_shuf_i64x2:
case X86::BI__builtin_ia32_shufpd512:
case X86::BI__builtin_ia32_shufps:
case X86::BI__builtin_ia32_shufps256:
case X86::BI__builtin_ia32_shufps512:
case X86::BI__builtin_ia32_dbpsadbw128:
case X86::BI__builtin_ia32_dbpsadbw256:
case X86::BI__builtin_ia32_dbpsadbw512:
case X86::BI__builtin_ia32_vpshldd128:
case X86::BI__builtin_ia32_vpshldd256:
case X86::BI__builtin_ia32_vpshldd512:
case X86::BI__builtin_ia32_vpshldq128:
case X86::BI__builtin_ia32_vpshldq256:
case X86::BI__builtin_ia32_vpshldq512:
case X86::BI__builtin_ia32_vpshldw128:
case X86::BI__builtin_ia32_vpshldw256:
case X86::BI__builtin_ia32_vpshldw512:
case X86::BI__builtin_ia32_vpshrdd128:
case X86::BI__builtin_ia32_vpshrdd256:
case X86::BI__builtin_ia32_vpshrdd512:
case X86::BI__builtin_ia32_vpshrdq128:
case X86::BI__builtin_ia32_vpshrdq256:
case X86::BI__builtin_ia32_vpshrdq512:
case X86::BI__builtin_ia32_vpshrdw128:
case X86::BI__builtin_ia32_vpshrdw256:
case X86::BI__builtin_ia32_vpshrdw512:
case X86::BI__builtin_ia32_vminmaxbf16128:
case X86::BI__builtin_ia32_vminmaxbf16256:
case X86::BI__builtin_ia32_vminmaxbf16512:
case X86::BI__builtin_ia32_vminmaxpd128_mask:
case X86::BI__builtin_ia32_vminmaxpd256_mask:
case X86::BI__builtin_ia32_vminmaxph128_mask:
case X86::BI__builtin_ia32_vminmaxph256_mask:
case X86::BI__builtin_ia32_vminmaxps128_mask:
case X86::BI__builtin_ia32_vminmaxps256_mask:
case X86::BI__builtin_ia32_vminmaxpd512_round_mask:
case X86::BI__builtin_ia32_vminmaxps512_round_mask:
case X86::BI__builtin_ia32_vminmaxph512_round_mask:
case X86::BI__builtin_ia32_vminmaxsd_round_mask:
case X86::BI__builtin_ia32_vminmaxsh_round_mask:
case X86::BI__builtin_ia32_vminmaxss_round_mask:
i = 2;
l = 0;
u = 255;
break;
case X86::BI__builtin_ia32_fixupimmpd512_mask:
case X86::BI__builtin_ia32_fixupimmpd512_maskz:
case X86::BI__builtin_ia32_fixupimmps512_mask:
case X86::BI__builtin_ia32_fixupimmps512_maskz:
case X86::BI__builtin_ia32_fixupimmsd_mask:
case X86::BI__builtin_ia32_fixupimmsd_maskz:
case X86::BI__builtin_ia32_fixupimmss_mask:
case X86::BI__builtin_ia32_fixupimmss_maskz:
case X86::BI__builtin_ia32_fixupimmpd128_mask:
case X86::BI__builtin_ia32_fixupimmpd128_maskz:
case X86::BI__builtin_ia32_fixupimmpd256_mask:
case X86::BI__builtin_ia32_fixupimmpd256_maskz:
case X86::BI__builtin_ia32_fixupimmps128_mask:
case X86::BI__builtin_ia32_fixupimmps128_maskz:
case X86::BI__builtin_ia32_fixupimmps256_mask:
case X86::BI__builtin_ia32_fixupimmps256_maskz:
case X86::BI__builtin_ia32_pternlogd512_mask:
case X86::BI__builtin_ia32_pternlogd512_maskz:
case X86::BI__builtin_ia32_pternlogq512_mask:
case X86::BI__builtin_ia32_pternlogq512_maskz:
case X86::BI__builtin_ia32_pternlogd128_mask:
case X86::BI__builtin_ia32_pternlogd128_maskz:
case X86::BI__builtin_ia32_pternlogd256_mask:
case X86::BI__builtin_ia32_pternlogd256_maskz:
case X86::BI__builtin_ia32_pternlogq128_mask:
case X86::BI__builtin_ia32_pternlogq128_maskz:
case X86::BI__builtin_ia32_pternlogq256_mask:
case X86::BI__builtin_ia32_pternlogq256_maskz:
case X86::BI__builtin_ia32_vsm3rnds2:
i = 3;
l = 0;
u = 255;
break;
case X86::BI__builtin_ia32_reducesd_mask:
case X86::BI__builtin_ia32_reducess_mask:
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
case X86::BI__builtin_ia32_rndscalesh_round_mask:
case X86::BI__builtin_ia32_reducesh_mask:
i = 4;
l = 0;
u = 255;
break;
case X86::BI__builtin_ia32_cmpccxadd32:
case X86::BI__builtin_ia32_cmpccxadd64:
i = 3;
l = 0;
u = 15;
break;
case X86::BI__builtin_ia32_prefetchi:
i = 1;
l = 2; // _MM_HINT_T1
u = 3; // _MM_HINT_T0
break;
}
// Note that we don't force a hard error on the range check here, allowing
// template-generated or macro-generated dead code to potentially have out-of-
// range values. These need to code generate, but don't need to necessarily
// make any sense. We use a warning that defaults to an error.
return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u,
/*RangeIsError*/ false);
}
void SemaX86::handleAnyInterruptAttr(Decl *D, const ParsedAttr &AL) {
// Semantic checks for a function with the 'interrupt' attribute.
// a) Must be a function.
// b) Must have the 'void' return type.
// c) Must take 1 or 2 arguments.
// d) The 1st argument must be a pointer.
// e) The 2nd argument (if any) must be an unsigned integer.
ASTContext &Context = getASTContext();
if (!isFuncOrMethodForAttrSubject(D) || !hasFunctionProto(D) ||
isInstanceMethod(D) ||
CXXMethodDecl::isStaticOverloadedOperator(
cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
<< AL << AL.isRegularKeywordAttribute()
<< ExpectedFunctionWithProtoType;
return;
}
// Interrupt handler must have void return type.
if (!getFunctionOrMethodResultType(D)->isVoidType()) {
Diag(getFunctionOrMethodResultSourceRange(D).getBegin(),
diag::err_anyx86_interrupt_attribute)
<< (SemaRef.Context.getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86
? 0
: 1)
<< 0;
return;
}
// Interrupt handler must have 1 or 2 parameters.
unsigned NumParams = getFunctionOrMethodNumParams(D);
if (NumParams < 1 || NumParams > 2) {
Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute)
<< (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
? 0
: 1)
<< 1;
return;
}
// The first argument must be a pointer.
if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) {
Diag(getFunctionOrMethodParamRange(D, 0).getBegin(),
diag::err_anyx86_interrupt_attribute)
<< (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
? 0
: 1)
<< 2;
return;
}
// The second argument, if present, must be an unsigned integer.
unsigned TypeSize =
Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64
? 64
: 32;
if (NumParams == 2 &&
(!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() ||
Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) {
Diag(getFunctionOrMethodParamRange(D, 1).getBegin(),
diag::err_anyx86_interrupt_attribute)
<< (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
? 0
: 1)
<< 3 << Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false);
return;
}
D->addAttr(::new (Context) AnyX86InterruptAttr(Context, AL));
D->addAttr(UsedAttr::CreateImplicit(Context));
}
void SemaX86::handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL) {
// If we try to apply it to a function pointer, don't warn, but don't
// do anything, either. It doesn't matter anyway, because there's nothing
// special about calling a force_align_arg_pointer function.
const auto *VD = dyn_cast<ValueDecl>(D);
if (VD && VD->getType()->isFunctionPointerType())
return;
// Also don't warn on function pointer typedefs.
const auto *TD = dyn_cast<TypedefNameDecl>(D);
if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
TD->getUnderlyingType()->isFunctionType()))
return;
// Attribute can only be applied to function types.
if (!isa<FunctionDecl>(D)) {
Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
<< AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
return;
}
D->addAttr(::new (getASTContext())
X86ForceAlignArgPointerAttr(getASTContext(), AL));
}
bool SemaX86::checkTargetClonesAttr(const SmallVectorImpl<StringRef> &Params,
const SmallVectorImpl<SourceLocation> &Locs,
SmallVectorImpl<SmallString<64>> &NewParams,
SourceLocation AttrLoc) {
using namespace DiagAttrParams;
assert(Params.size() == Locs.size() &&
"Mismatch between number of string parameters and locations");
bool HasDefault = false;
bool HasComma = false;
for (unsigned I = 0, E = Params.size(); I < E; ++I) {
const StringRef Param = Params[I].trim();
const SourceLocation &Loc = Locs[I];
if (Param.empty() || Param.ends_with(','))
return Diag(Loc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "" << TargetClones;
if (Param.contains(','))
HasComma = true;
StringRef LHS;
StringRef RHS = Param;
do {
std::tie(LHS, RHS) = RHS.split(',');
LHS = LHS.trim();
const SourceLocation &CurLoc =
Loc.getLocWithOffset(LHS.data() - Param.data());
if (LHS.starts_with("arch=")) {
if (!getASTContext().getTargetInfo().isValidCPUName(
LHS.drop_front(sizeof("arch=") - 1)))
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << CPU << LHS.drop_front(sizeof("arch=") - 1)
<< TargetClones;
} else if (LHS == "default")
HasDefault = true;
else if (!getASTContext().getTargetInfo().isValidFeatureName(LHS) ||
getASTContext().getTargetInfo().getFMVPriority(LHS) == 0)
return Diag(CurLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << LHS << TargetClones;
if (llvm::is_contained(NewParams, LHS))
Diag(CurLoc, diag::warn_target_clone_duplicate_options);
// Note: Add even if there are duplicates, since it changes name mangling.
NewParams.push_back(LHS);
} while (!RHS.empty());
}
if (HasComma && Params.size() > 1)
Diag(Locs[0], diag::warn_target_clone_mixed_values);
if (!HasDefault)
return Diag(AttrLoc, diag::err_target_clone_must_have_default);
return false;
}
} // namespace clang