19#include "mlir/IR/BuiltinAttributes.h"
20#include "mlir/IR/Value.h"
21#include "mlir/Support/LLVM.h"
26#include "llvm/Support/ErrorHandling.h"
33 const CallExpr *e, mlir::Operation *calleeValue) {
40 bool poisonZero =
false) {
47 if constexpr (std::is_same_v<Op, cir::BitClzOp> ||
48 std::is_same_v<Op, cir::BitCtzOp>)
53 mlir::Value result = op.getResult();
55 if (exprTy != result.getType())
71 amount, isRotateLeft);
75template <
class Operation>
84 Operation::create(cgf.
getBuilder(), arg.getLoc(), arg.getType(), arg);
119 unsigned builtinIDIfNoAsmLabel = fd->
hasAttr<AsmLabelAttr>() ? 0 : builtinID;
124 switch (builtinIDIfNoAsmLabel) {
129 case Builtin::BI__builtin_stdarg_start:
130 case Builtin::BI__builtin_va_start:
131 case Builtin::BI__va_start: {
132 mlir::Value vaList = builtinID == Builtin::BI__va_start
140 case Builtin::BI__builtin_va_end:
144 case Builtin::BIfabs:
145 case Builtin::BIfabsf:
146 case Builtin::BIfabsl:
147 case Builtin::BI__builtin_fabs:
148 case Builtin::BI__builtin_fabsf:
149 case Builtin::BI__builtin_fabsf16:
150 case Builtin::BI__builtin_fabsl:
151 case Builtin::BI__builtin_fabsf128:
152 return emitUnaryMaybeConstrainedFPBuiltin<cir::FAbsOp>(*
this, *e);
154 case Builtin::BI__assume:
155 case Builtin::BI__builtin_assume: {
160 builder.create<cir::AssumeOp>(loc, argValue);
164 case Builtin::BI__builtin_assume_separate_storage: {
167 builder.create<cir::AssumeSepStorageOp>(loc, value0, value1);
171 case Builtin::BI__builtin_assume_aligned: {
174 mlir::Value offsetValue =
177 std::optional<llvm::APSInt> alignment =
179 assert(alignment.has_value() &&
180 "the second argument to __builtin_assume_aligned must be an "
181 "integral constant expression");
185 alignment->getSExtValue(), offsetValue);
189 case Builtin::BI__builtin_complex: {
196 case Builtin::BI__builtin_creal:
197 case Builtin::BI__builtin_crealf:
198 case Builtin::BI__builtin_creall:
199 case Builtin::BIcreal:
200 case Builtin::BIcrealf:
201 case Builtin::BIcreall: {
207 case Builtin::BI__builtin_cimag:
208 case Builtin::BI__builtin_cimagf:
209 case Builtin::BI__builtin_cimagl:
210 case Builtin::BIcimag:
211 case Builtin::BIcimagf:
212 case Builtin::BIcimagl: {
218 case Builtin::BI__builtin_conj:
219 case Builtin::BI__builtin_conjf:
220 case Builtin::BI__builtin_conjl:
221 case Builtin::BIconj:
222 case Builtin::BIconjf:
223 case Builtin::BIconjl: {
226 cir::UnaryOpKind::Not, complex);
230 case Builtin::BI__builtin_clrsb:
231 case Builtin::BI__builtin_clrsbl:
232 case Builtin::BI__builtin_clrsbll:
233 return emitBuiltinBitOp<cir::BitClrsbOp>(*
this, e);
235 case Builtin::BI__builtin_ctzs:
236 case Builtin::BI__builtin_ctz:
237 case Builtin::BI__builtin_ctzl:
238 case Builtin::BI__builtin_ctzll:
239 case Builtin::BI__builtin_ctzg:
241 return emitBuiltinBitOp<cir::BitCtzOp>(*
this, e,
true);
243 case Builtin::BI__builtin_clzs:
244 case Builtin::BI__builtin_clz:
245 case Builtin::BI__builtin_clzl:
246 case Builtin::BI__builtin_clzll:
247 case Builtin::BI__builtin_clzg:
249 return emitBuiltinBitOp<cir::BitClzOp>(*
this, e,
true);
251 case Builtin::BI__builtin_ffs:
252 case Builtin::BI__builtin_ffsl:
253 case Builtin::BI__builtin_ffsll:
254 return emitBuiltinBitOp<cir::BitFfsOp>(*
this, e);
256 case Builtin::BI__builtin_parity:
257 case Builtin::BI__builtin_parityl:
258 case Builtin::BI__builtin_parityll:
259 return emitBuiltinBitOp<cir::BitParityOp>(*
this, e);
261 case Builtin::BI__lzcnt16:
262 case Builtin::BI__lzcnt:
263 case Builtin::BI__lzcnt64:
265 return emitBuiltinBitOp<cir::BitClzOp>(*
this, e,
false);
267 case Builtin::BI__popcnt16:
268 case Builtin::BI__popcnt:
269 case Builtin::BI__popcnt64:
270 case Builtin::BI__builtin_popcount:
271 case Builtin::BI__builtin_popcountl:
272 case Builtin::BI__builtin_popcountll:
273 case Builtin::BI__builtin_popcountg:
274 return emitBuiltinBitOp<cir::BitPopcountOp>(*
this, e);
276 case Builtin::BI__builtin_expect:
277 case Builtin::BI__builtin_expect_with_probability: {
281 mlir::FloatAttr probAttr;
282 if (builtinIDIfNoAsmLabel == Builtin::BI__builtin_expect_with_probability) {
283 llvm::APFloat probability(0.0);
285 [[maybe_unused]]
bool evalSucceeded =
287 assert(evalSucceeded &&
288 "probability should be able to evaluate as float");
289 bool loseInfo =
false;
290 probability.convert(llvm::APFloat::IEEEdouble(),
291 llvm::RoundingMode::Dynamic, &loseInfo);
292 probAttr = mlir::FloatAttr::get(mlir::Float64Type::get(&
getMLIRContext()),
296 auto result = builder.create<cir::ExpectOp>(
297 loc, argValue.getType(), argValue, expectedValue, probAttr);
301 case Builtin::BI__builtin_bswap16:
302 case Builtin::BI__builtin_bswap32:
303 case Builtin::BI__builtin_bswap64:
304 case Builtin::BI_byteswap_ushort:
305 case Builtin::BI_byteswap_ulong:
306 case Builtin::BI_byteswap_uint64: {
308 return RValue::get(builder.create<cir::ByteSwapOp>(loc, arg));
311 case Builtin::BI__builtin_bitreverse8:
312 case Builtin::BI__builtin_bitreverse16:
313 case Builtin::BI__builtin_bitreverse32:
314 case Builtin::BI__builtin_bitreverse64: {
316 return RValue::get(builder.create<cir::BitReverseOp>(loc, arg));
319 case Builtin::BI__builtin_rotateleft8:
320 case Builtin::BI__builtin_rotateleft16:
321 case Builtin::BI__builtin_rotateleft32:
322 case Builtin::BI__builtin_rotateleft64:
325 case Builtin::BI__builtin_rotateright8:
326 case Builtin::BI__builtin_rotateright16:
327 case Builtin::BI__builtin_rotateright32:
328 case Builtin::BI__builtin_rotateright64:
331 case Builtin::BI__builtin_return_address:
332 case Builtin::BI__builtin_frame_address: {
335 if (builtinID == Builtin::BI__builtin_return_address) {
345 case Builtin::BI__builtin_trap:
349 case Builtin::BI__builtin_unreachable:
357 if (
getContext().BuiltinInfo.isLibFunction(builtinID))
368 unsigned builtinID) {
391 "emitCheckedArgForAssume: sanitizers are NYI");
398 cir::VAStartOp::create(builder, vaList.getLoc(), vaList, count);
402 cir::VAEndOp::create(builder, vaList.getLoc(), vaList);
414 return cir::VAArgOp::create(builder, loc,
type, vaList);
Defines enum values for all the target-independent builtin functions.
static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static RValue emitLibraryCall(CIRGenFunction &cgf, const FunctionDecl *fd, const CallExpr *e, mlir::Operation *calleeValue)
static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, bool poisonZero=false)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
mlir::Value createUnaryOp(mlir::Location loc, cir::UnaryOpKind kind, mlir::Value operand)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
Builtin::Context & BuiltinInfo
bool isLibFunction(unsigned ID) const
Return true if this is a builtin for a libc/libm function, with a "__builtin_" prefix (e....
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
mlir::Value getPointer() const
cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, llvm::APFloat fpVal)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::IntType getUInt32Ty()
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
mlir::Type convertType(clang::QualType t)
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitVAStart(mlir::Value vaList, mlir::Value count)
Emits the start of a CIR variable-argument operation (cir.va_start)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock)
Emit a reached-unreachable diagnostic if loc is valid and runtime checking is enabled.
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
mlir::Value emitScalarExpr(const clang::Expr *e)
Emit the computation of the specified expression of scalar type.
void emitVAEnd(mlir::Value vaList)
Emits the end of a CIR variable-argument operation (cir.va_start)
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
clang::ASTContext & getContext() const
RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot returnValue)
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue emitRotate(const CallExpr *e, bool isRotateLeft)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
mlir::Type convertType(clang::QualType type)
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID)
Given a builtin id for a function like "__builtin_fabsf", return a Function* for "fabsf".
cir::FuncOp getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType, clang::GlobalDecl gd, bool forVTable, bool dontDefer=false, bool isThunk=false, ForDefinition_t isForDefinition=NotForDefinition, mlir::ArrayAttr extraAttrs={})
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(mlir::Value v)
static RValue getComplex(mlir::Value v)
Contains the address where the return value of a function can be stored, and whether the address is v...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
This represents one expression.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsFloat - Return true if this is a constant which we can fold and convert to a floating point...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Represents a call to the builtin function __builtin_va_arg.
const Expr * getSubExpr() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
static bool builtinCheckKind()
static bool asmLabelAttr()
static bool msvcBuiltins()
static bool cgFPOptionsRAII()
static bool builtinCallF128()
static bool fpConstraints()
static bool builtinCallMathErrno()
static bool builtinCall()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.