Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaBPF.cpp
35234 views
//===------ SemaBPF.cpp ---------- BPF target-specific routines -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements semantic analysis functions specific to BPF.9//10//===----------------------------------------------------------------------===//1112#include "clang/Sema/SemaBPF.h"13#include "clang/AST/Decl.h"14#include "clang/AST/Type.h"15#include "clang/Basic/DiagnosticSema.h"16#include "clang/Basic/TargetBuiltins.h"17#include "clang/Sema/ParsedAttr.h"18#include "clang/Sema/Sema.h"19#include "llvm/ADT/APSInt.h"20#include <optional>2122namespace clang {2324SemaBPF::SemaBPF(Sema &S) : SemaBase(S) {}2526static bool isValidPreserveFieldInfoArg(Expr *Arg) {27if (Arg->getType()->getAsPlaceholderType())28return false;2930// The first argument needs to be a record field access.31// If it is an array element access, we delay decision32// to BPF backend to check whether the access is a33// field access or not.34return (Arg->IgnoreParens()->getObjectKind() == OK_BitField ||35isa<MemberExpr>(Arg->IgnoreParens()) ||36isa<ArraySubscriptExpr>(Arg->IgnoreParens()));37}3839static bool isValidPreserveTypeInfoArg(Expr *Arg) {40QualType ArgType = Arg->getType();41if (ArgType->getAsPlaceholderType())42return false;4344// for TYPE_EXISTENCE/TYPE_MATCH/TYPE_SIZEOF reloc type45// format:46// 1. __builtin_preserve_type_info(*(<type> *)0, flag);47// 2. <type> var;48// __builtin_preserve_type_info(var, flag);49if (!isa<DeclRefExpr>(Arg->IgnoreParens()) &&50!isa<UnaryOperator>(Arg->IgnoreParens()))51return false;5253// Typedef type.54if (ArgType->getAs<TypedefType>())55return true;5657// Record type or Enum type.58const Type *Ty = ArgType->getUnqualifiedDesugaredType();59if (const auto *RT = Ty->getAs<RecordType>()) {60if (!RT->getDecl()->getDeclName().isEmpty())61return true;62} else if (const auto *ET = Ty->getAs<EnumType>()) {63if (!ET->getDecl()->getDeclName().isEmpty())64return true;65}6667return false;68}6970static bool isValidPreserveEnumValueArg(Expr *Arg) {71QualType ArgType = Arg->getType();72if (ArgType->getAsPlaceholderType())73return false;7475// for ENUM_VALUE_EXISTENCE/ENUM_VALUE reloc type76// format:77// __builtin_preserve_enum_value(*(<enum_type> *)<enum_value>,78// flag);79const auto *UO = dyn_cast<UnaryOperator>(Arg->IgnoreParens());80if (!UO)81return false;8283const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr());84if (!CE)85return false;86if (CE->getCastKind() != CK_IntegralToPointer &&87CE->getCastKind() != CK_NullToPointer)88return false;8990// The integer must be from an EnumConstantDecl.91const auto *DR = dyn_cast<DeclRefExpr>(CE->getSubExpr());92if (!DR)93return false;9495const EnumConstantDecl *Enumerator =96dyn_cast<EnumConstantDecl>(DR->getDecl());97if (!Enumerator)98return false;99100// The type must be EnumType.101const Type *Ty = ArgType->getUnqualifiedDesugaredType();102const auto *ET = Ty->getAs<EnumType>();103if (!ET)104return false;105106// The enum value must be supported.107return llvm::is_contained(ET->getDecl()->enumerators(), Enumerator);108}109110bool SemaBPF::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,111CallExpr *TheCall) {112assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||113BuiltinID == BPF::BI__builtin_btf_type_id ||114BuiltinID == BPF::BI__builtin_preserve_type_info ||115BuiltinID == BPF::BI__builtin_preserve_enum_value) &&116"unexpected BPF builtin");117ASTContext &Context = getASTContext();118if (SemaRef.checkArgCount(TheCall, 2))119return true;120121// The second argument needs to be a constant int122Expr *Arg = TheCall->getArg(1);123std::optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(Context);124diag::kind kind;125if (!Value) {126if (BuiltinID == BPF::BI__builtin_preserve_field_info)127kind = diag::err_preserve_field_info_not_const;128else if (BuiltinID == BPF::BI__builtin_btf_type_id)129kind = diag::err_btf_type_id_not_const;130else if (BuiltinID == BPF::BI__builtin_preserve_type_info)131kind = diag::err_preserve_type_info_not_const;132else133kind = diag::err_preserve_enum_value_not_const;134Diag(Arg->getBeginLoc(), kind) << 2 << Arg->getSourceRange();135return true;136}137138// The first argument139Arg = TheCall->getArg(0);140bool InvalidArg = false;141bool ReturnUnsignedInt = true;142if (BuiltinID == BPF::BI__builtin_preserve_field_info) {143if (!isValidPreserveFieldInfoArg(Arg)) {144InvalidArg = true;145kind = diag::err_preserve_field_info_not_field;146}147} else if (BuiltinID == BPF::BI__builtin_preserve_type_info) {148if (!isValidPreserveTypeInfoArg(Arg)) {149InvalidArg = true;150kind = diag::err_preserve_type_info_invalid;151}152} else if (BuiltinID == BPF::BI__builtin_preserve_enum_value) {153if (!isValidPreserveEnumValueArg(Arg)) {154InvalidArg = true;155kind = diag::err_preserve_enum_value_invalid;156}157ReturnUnsignedInt = false;158} else if (BuiltinID == BPF::BI__builtin_btf_type_id) {159ReturnUnsignedInt = false;160}161162if (InvalidArg) {163Diag(Arg->getBeginLoc(), kind) << 1 << Arg->getSourceRange();164return true;165}166167if (ReturnUnsignedInt)168TheCall->setType(Context.UnsignedIntTy);169else170TheCall->setType(Context.UnsignedLongTy);171return false;172}173174void SemaBPF::handlePreserveAIRecord(RecordDecl *RD) {175// Add preserve_access_index attribute to all fields and inner records.176for (auto *D : RD->decls()) {177if (D->hasAttr<BPFPreserveAccessIndexAttr>())178continue;179180D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(getASTContext()));181if (auto *Rec = dyn_cast<RecordDecl>(D))182handlePreserveAIRecord(Rec);183}184}185186void SemaBPF::handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL) {187auto *Rec = cast<RecordDecl>(D);188handlePreserveAIRecord(Rec);189Rec->addAttr(::new (getASTContext())190BPFPreserveAccessIndexAttr(getASTContext(), AL));191}192193} // namespace clang194195196