clang 22.0.0git
SemaBPF.cpp
Go to the documentation of this file.
1//===------ SemaBPF.cpp ---------- BPF 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 BPF.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Sema/SemaBPF.h"
14#include "clang/AST/Decl.h"
15#include "clang/AST/Type.h"
19#include "clang/Sema/Sema.h"
20#include "llvm/ADT/APSInt.h"
21#include <optional>
22
23namespace clang {
24
26
28 if (Arg->getType()->getAsPlaceholderType())
29 return false;
30
31 // The first argument needs to be a record field access.
32 // If it is an array element access, we delay decision
33 // to BPF backend to check whether the access is a
34 // field access or not.
35 return (Arg->IgnoreParens()->getObjectKind() == OK_BitField ||
36 isa<MemberExpr>(Arg->IgnoreParens()) ||
37 isa<ArraySubscriptExpr>(Arg->IgnoreParens()));
38}
39
41 QualType ArgType = Arg->getType();
42 if (ArgType->getAsPlaceholderType())
43 return false;
44
45 // for TYPE_EXISTENCE/TYPE_MATCH/TYPE_SIZEOF reloc type
46 // format:
47 // 1. __builtin_preserve_type_info(*(<type> *)0, flag);
48 // 2. <type> var;
49 // __builtin_preserve_type_info(var, flag);
50 if (!isa<DeclRefExpr>(Arg->IgnoreParens()) &&
51 !isa<UnaryOperator>(Arg->IgnoreParens()))
52 return false;
53
54 // Typedef type.
55 if (ArgType->getAs<TypedefType>())
56 return true;
57
58 // Record type or Enum type.
59 if (const auto *RT = ArgType->getAsCanonical<TagType>())
60 if (!RT->getOriginalDecl()->getDeclName().isEmpty())
61 return true;
62
63 return false;
64}
65
67 QualType ArgType = Arg->getType();
68 if (ArgType->getAsPlaceholderType())
69 return false;
70
71 // for ENUM_VALUE_EXISTENCE/ENUM_VALUE reloc type
72 // format:
73 // __builtin_preserve_enum_value(*(<enum_type> *)<enum_value>,
74 // flag);
75 const auto *UO = dyn_cast<UnaryOperator>(Arg->IgnoreParens());
76 if (!UO)
77 return false;
78
79 const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr());
80 if (!CE)
81 return false;
82 if (CE->getCastKind() != CK_IntegralToPointer &&
83 CE->getCastKind() != CK_NullToPointer)
84 return false;
85
86 // The integer must be from an EnumConstantDecl.
87 const auto *DR = dyn_cast<DeclRefExpr>(CE->getSubExpr());
88 if (!DR)
89 return false;
90
92 dyn_cast<EnumConstantDecl>(DR->getDecl());
93 if (!Enumerator)
94 return false;
95
96 // The type must be EnumType.
97 const auto *ED = ArgType->getAsEnumDecl();
98 if (!ED)
99 return false;
100
101 // The enum value must be supported.
102 return llvm::is_contained(ED->enumerators(), Enumerator);
103}
104
106 CallExpr *TheCall) {
107 assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
108 BuiltinID == BPF::BI__builtin_btf_type_id ||
109 BuiltinID == BPF::BI__builtin_preserve_type_info ||
110 BuiltinID == BPF::BI__builtin_preserve_enum_value) &&
111 "unexpected BPF builtin");
112 ASTContext &Context = getASTContext();
113 if (SemaRef.checkArgCount(TheCall, 2))
114 return true;
115
116 // The second argument needs to be a constant int
117 Expr *Arg = TheCall->getArg(1);
118 std::optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(Context);
119 diag::kind kind;
120 if (!Value) {
121 if (BuiltinID == BPF::BI__builtin_preserve_field_info)
122 kind = diag::err_preserve_field_info_not_const;
123 else if (BuiltinID == BPF::BI__builtin_btf_type_id)
124 kind = diag::err_btf_type_id_not_const;
125 else if (BuiltinID == BPF::BI__builtin_preserve_type_info)
126 kind = diag::err_preserve_type_info_not_const;
127 else
128 kind = diag::err_preserve_enum_value_not_const;
129 Diag(Arg->getBeginLoc(), kind) << 2 << Arg->getSourceRange();
130 return true;
131 }
132
133 // The first argument
134 Arg = TheCall->getArg(0);
135 bool InvalidArg = false;
136 bool ReturnUnsignedInt = true;
137 if (BuiltinID == BPF::BI__builtin_preserve_field_info) {
138 if (!isValidPreserveFieldInfoArg(Arg)) {
139 InvalidArg = true;
140 kind = diag::err_preserve_field_info_not_field;
141 }
142 } else if (BuiltinID == BPF::BI__builtin_preserve_type_info) {
143 if (!isValidPreserveTypeInfoArg(Arg)) {
144 InvalidArg = true;
145 kind = diag::err_preserve_type_info_invalid;
146 }
147 } else if (BuiltinID == BPF::BI__builtin_preserve_enum_value) {
148 if (!isValidPreserveEnumValueArg(Arg)) {
149 InvalidArg = true;
150 kind = diag::err_preserve_enum_value_invalid;
151 }
152 ReturnUnsignedInt = false;
153 } else if (BuiltinID == BPF::BI__builtin_btf_type_id) {
154 ReturnUnsignedInt = false;
155 }
156
157 if (InvalidArg) {
158 Diag(Arg->getBeginLoc(), kind) << 1 << Arg->getSourceRange();
159 return true;
160 }
161
162 if (ReturnUnsignedInt)
163 TheCall->setType(Context.UnsignedIntTy);
164 else
165 TheCall->setType(Context.UnsignedLongTy);
166 return false;
167}
168
170 // Add preserve_access_index attribute to all fields and inner records.
171 for (auto *D : RD->decls()) {
172 if (D->hasAttr<BPFPreserveAccessIndexAttr>())
173 continue;
174
175 D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(getASTContext()));
176 if (auto *Rec = dyn_cast<RecordDecl>(D))
178 }
179}
180
182 auto *Rec = cast<RecordDecl>(D);
184 Rec->addAttr(::new (getASTContext())
185 BPFPreserveAccessIndexAttr(getASTContext(), AL));
186}
187
188} // namespace clang
const Decl * D
This file declares semantic analysis functions specific to BPF.
Enumerates target-specific builtins in their own namespaces within namespace clang.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3083
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2373
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
An instance of this object exists for each enum constant that is defined.
Definition: Decl.h:3420
This represents one expression.
Definition: Expr.h:112
void setType(QualType t)
Definition: Expr.h:145
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3069
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:451
QualType getType() const
Definition: Expr.h:144
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:119
A (possibly-)qualified type.
Definition: TypeBase.h:937
Represents a struct/union/class.
Definition: Decl.h:4309
void handlePreserveAIRecord(RecordDecl *RD)
Definition: SemaBPF.cpp:169
SemaBPF(Sema &S)
Definition: SemaBPF.cpp:25
void handlePreserveAccessIndexAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaBPF.cpp:181
bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaBPF.cpp:105
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
const BuiltinType * getAsPlaceholderType() const
Definition: TypeBase.h:8918
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition: Type.h:53
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition: TypeBase.h:2939
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
The JSON file list parser is used to communicate input to InstallAPI.
static bool isValidPreserveFieldInfoArg(Expr *Arg)
Definition: SemaBPF.cpp:27
@ OK_BitField
A bitfield object is a bitfield on a C or C++ record.
Definition: Specifiers.h:154
static bool isValidPreserveEnumValueArg(Expr *Arg)
Definition: SemaBPF.cpp:66
static bool isValidPreserveTypeInfoArg(Expr *Arg)
Definition: SemaBPF.cpp:40
@ Enumerator
Enumerator value with fixed underlying type.