Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/CodeGen/CGCall.h
Line
Count
Source (jump to first uncovered line)
1
//===----- CGCall.h - Encapsulate calling convention details ----*- C++ -*-===//
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
// These classes wrap the information about a call or function
10
// definition used to handle ABI compliancy.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H
15
#define LLVM_CLANG_LIB_CODEGEN_CGCALL_H
16
17
#include "CGValue.h"
18
#include "EHScopeStack.h"
19
#include "clang/AST/ASTFwd.h"
20
#include "clang/AST/CanonicalType.h"
21
#include "clang/AST/GlobalDecl.h"
22
#include "clang/AST/Type.h"
23
#include "llvm/ADT/STLForwardCompat.h"
24
#include "llvm/IR/Value.h"
25
26
namespace llvm {
27
class Type;
28
class Value;
29
} // namespace llvm
30
31
namespace clang {
32
class Decl;
33
class FunctionDecl;
34
class TargetOptions;
35
class VarDecl;
36
37
namespace CodeGen {
38
39
/// Abstract information about a function or function prototype.
40
class CGCalleeInfo {
41
  /// The function prototype of the callee.
42
  const FunctionProtoType *CalleeProtoTy;
43
  /// The function declaration of the callee.
44
  GlobalDecl CalleeDecl;
45
46
public:
47
0
  explicit CGCalleeInfo() : CalleeProtoTy(nullptr) {}
48
  CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl)
49
0
      : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
50
  CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
51
0
      : CalleeProtoTy(calleeProtoTy) {}
52
  CGCalleeInfo(GlobalDecl calleeDecl)
53
0
      : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
54
55
0
  const FunctionProtoType *getCalleeFunctionProtoType() const {
56
0
    return CalleeProtoTy;
57
0
  }
58
0
  const GlobalDecl getCalleeDecl() const { return CalleeDecl; }
59
};
60
61
/// All available information about a concrete callee.
62
class CGCallee {
63
  enum class SpecialKind : uintptr_t {
64
    Invalid,
65
    Builtin,
66
    PseudoDestructor,
67
    Virtual,
68
69
    Last = Virtual
70
  };
71
72
  struct BuiltinInfoStorage {
73
    const FunctionDecl *Decl;
74
    unsigned ID;
75
  };
76
  struct PseudoDestructorInfoStorage {
77
    const CXXPseudoDestructorExpr *Expr;
78
  };
79
  struct VirtualInfoStorage {
80
    const CallExpr *CE;
81
    GlobalDecl MD;
82
    Address Addr;
83
    llvm::FunctionType *FTy;
84
  };
85
86
  SpecialKind KindOrFunctionPointer;
87
  union {
88
    CGCalleeInfo AbstractInfo;
89
    BuiltinInfoStorage BuiltinInfo;
90
    PseudoDestructorInfoStorage PseudoDestructorInfo;
91
    VirtualInfoStorage VirtualInfo;
92
  };
93
94
0
  explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
95
96
  CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
97
0
      : KindOrFunctionPointer(SpecialKind::Builtin) {
98
0
    BuiltinInfo.Decl = builtinDecl;
99
0
    BuiltinInfo.ID = builtinID;
100
0
  }
101
102
public:
103
0
  CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
104
105
  /// Construct a callee.  Call this constructor directly when this
106
  /// isn't a direct call.
107
  CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
108
      : KindOrFunctionPointer(
109
0
            SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) {
110
0
    AbstractInfo = abstractInfo;
111
0
    assert(functionPtr && "configuring callee without function pointer");
112
0
    assert(functionPtr->getType()->isPointerTy());
113
0
  }
114
115
  static CGCallee forBuiltin(unsigned builtinID,
116
0
                             const FunctionDecl *builtinDecl) {
117
0
    CGCallee result(SpecialKind::Builtin);
118
0
    result.BuiltinInfo.Decl = builtinDecl;
119
0
    result.BuiltinInfo.ID = builtinID;
120
0
    return result;
121
0
  }
122
123
0
  static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
124
0
    CGCallee result(SpecialKind::PseudoDestructor);
125
0
    result.PseudoDestructorInfo.Expr = E;
126
0
    return result;
127
0
  }
128
129
  static CGCallee forDirect(llvm::Constant *functionPtr,
130
0
                            const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
131
0
    return CGCallee(abstractInfo, functionPtr);
132
0
  }
133
134
  static CGCallee forDirect(llvm::FunctionCallee functionPtr,
135
0
                            const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
136
0
    return CGCallee(abstractInfo, functionPtr.getCallee());
137
0
  }
138
139
  static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
140
0
                             llvm::FunctionType *FTy) {
141
0
    CGCallee result(SpecialKind::Virtual);
142
0
    result.VirtualInfo.CE = CE;
143
0
    result.VirtualInfo.MD = MD;
144
0
    result.VirtualInfo.Addr = Addr;
145
0
    result.VirtualInfo.FTy = FTy;
146
0
    return result;
147
0
  }
148
149
0
  bool isBuiltin() const {
150
0
    return KindOrFunctionPointer == SpecialKind::Builtin;
151
0
  }
152
0
  const FunctionDecl *getBuiltinDecl() const {
153
0
    assert(isBuiltin());
154
0
    return BuiltinInfo.Decl;
155
0
  }
156
0
  unsigned getBuiltinID() const {
157
0
    assert(isBuiltin());
158
0
    return BuiltinInfo.ID;
159
0
  }
160
161
0
  bool isPseudoDestructor() const {
162
0
    return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
163
0
  }
164
0
  const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
165
0
    assert(isPseudoDestructor());
166
0
    return PseudoDestructorInfo.Expr;
167
0
  }
168
169
0
  bool isOrdinary() const {
170
0
    return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
171
0
  }
172
0
  CGCalleeInfo getAbstractInfo() const {
173
0
    if (isVirtual())
174
0
      return VirtualInfo.MD;
175
0
    assert(isOrdinary());
176
0
    return AbstractInfo;
177
0
  }
178
0
  llvm::Value *getFunctionPointer() const {
179
0
    assert(isOrdinary());
180
0
    return reinterpret_cast<llvm::Value *>(uintptr_t(KindOrFunctionPointer));
181
0
  }
182
0
  void setFunctionPointer(llvm::Value *functionPtr) {
183
0
    assert(isOrdinary());
184
0
    KindOrFunctionPointer =
185
0
        SpecialKind(reinterpret_cast<uintptr_t>(functionPtr));
186
0
  }
187
188
0
  bool isVirtual() const {
189
0
    return KindOrFunctionPointer == SpecialKind::Virtual;
190
0
  }
191
0
  const CallExpr *getVirtualCallExpr() const {
192
0
    assert(isVirtual());
193
0
    return VirtualInfo.CE;
194
0
  }
195
0
  GlobalDecl getVirtualMethodDecl() const {
196
0
    assert(isVirtual());
197
0
    return VirtualInfo.MD;
198
0
  }
199
0
  Address getThisAddress() const {
200
0
    assert(isVirtual());
201
0
    return VirtualInfo.Addr;
202
0
  }
203
0
  llvm::FunctionType *getVirtualFunctionType() const {
204
0
    assert(isVirtual());
205
0
    return VirtualInfo.FTy;
206
0
  }
207
208
  /// If this is a delayed callee computation of some sort, prepare
209
  /// a concrete callee.
210
  CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
211
};
212
213
struct CallArg {
214
private:
215
  union {
216
    RValue RV;
217
    LValue LV; /// The argument is semantically a load from this l-value.
218
  };
219
  bool HasLV;
220
221
  /// A data-flow flag to make sure getRValue and/or copyInto are not
222
  /// called twice for duplicated IR emission.
223
  mutable bool IsUsed;
224
225
public:
226
  QualType Ty;
227
  CallArg(RValue rv, QualType ty)
228
0
      : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
229
  CallArg(LValue lv, QualType ty)
230
0
      : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
231
0
  bool hasLValue() const { return HasLV; }
232
0
  QualType getType() const { return Ty; }
233
234
  /// \returns an independent RValue. If the CallArg contains an LValue,
235
  /// a temporary copy is returned.
236
  RValue getRValue(CodeGenFunction &CGF) const;
237
238
0
  LValue getKnownLValue() const {
239
0
    assert(HasLV && !IsUsed);
240
0
    return LV;
241
0
  }
242
0
  RValue getKnownRValue() const {
243
0
    assert(!HasLV && !IsUsed);
244
0
    return RV;
245
0
  }
246
0
  void setRValue(RValue _RV) {
247
0
    assert(!HasLV);
248
0
    RV = _RV;
249
0
  }
250
251
0
  bool isAggregate() const { return HasLV || RV.isAggregate(); }
252
253
  void copyInto(CodeGenFunction &CGF, Address A) const;
254
};
255
256
/// CallArgList - Type for representing both the value and type of
257
/// arguments in a call.
258
class CallArgList : public SmallVector<CallArg, 8> {
259
public:
260
0
  CallArgList() = default;
261
262
  struct Writeback {
263
    /// The original argument.  Note that the argument l-value
264
    /// is potentially null.
265
    LValue Source;
266
267
    /// The temporary alloca.
268
    Address Temporary;
269
270
    /// A value to "use" after the writeback, or null.
271
    llvm::Value *ToUse;
272
  };
273
274
  struct CallArgCleanup {
275
    EHScopeStack::stable_iterator Cleanup;
276
277
    /// The "is active" insertion point.  This instruction is temporary and
278
    /// will be removed after insertion.
279
    llvm::Instruction *IsActiveIP;
280
  };
281
282
0
  void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
283
284
0
  void addUncopiedAggregate(LValue LV, QualType type) {
285
0
    push_back(CallArg(LV, type));
286
0
  }
287
288
  /// Add all the arguments from another CallArgList to this one. After doing
289
  /// this, the old CallArgList retains its list of arguments, but must not
290
  /// be used to emit a call.
291
0
  void addFrom(const CallArgList &other) {
292
0
    insert(end(), other.begin(), other.end());
293
0
    Writebacks.insert(Writebacks.end(), other.Writebacks.begin(),
294
0
                      other.Writebacks.end());
295
0
    CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),
296
0
                                other.CleanupsToDeactivate.begin(),
297
0
                                other.CleanupsToDeactivate.end());
298
0
    assert(!(StackBase && other.StackBase) && "can't merge stackbases");
299
0
    if (!StackBase)
300
0
      StackBase = other.StackBase;
301
0
  }
302
303
0
  void addWriteback(LValue srcLV, Address temporary, llvm::Value *toUse) {
304
0
    Writeback writeback = {srcLV, temporary, toUse};
305
0
    Writebacks.push_back(writeback);
306
0
  }
307
308
0
  bool hasWritebacks() const { return !Writebacks.empty(); }
309
310
  typedef llvm::iterator_range<SmallVectorImpl<Writeback>::const_iterator>
311
      writeback_const_range;
312
313
0
  writeback_const_range writebacks() const {
314
0
    return writeback_const_range(Writebacks.begin(), Writebacks.end());
315
0
  }
316
317
  void addArgCleanupDeactivation(EHScopeStack::stable_iterator Cleanup,
318
0
                                 llvm::Instruction *IsActiveIP) {
319
0
    CallArgCleanup ArgCleanup;
320
0
    ArgCleanup.Cleanup = Cleanup;
321
0
    ArgCleanup.IsActiveIP = IsActiveIP;
322
0
    CleanupsToDeactivate.push_back(ArgCleanup);
323
0
  }
324
325
0
  ArrayRef<CallArgCleanup> getCleanupsToDeactivate() const {
326
0
    return CleanupsToDeactivate;
327
0
  }
328
329
  void allocateArgumentMemory(CodeGenFunction &CGF);
330
0
  llvm::Instruction *getStackBase() const { return StackBase; }
331
  void freeArgumentMemory(CodeGenFunction &CGF) const;
332
333
  /// Returns if we're using an inalloca struct to pass arguments in
334
  /// memory.
335
0
  bool isUsingInAlloca() const { return StackBase; }
336
337
private:
338
  SmallVector<Writeback, 1> Writebacks;
339
340
  /// Deactivate these cleanups immediately before making the call.  This
341
  /// is used to cleanup objects that are owned by the callee once the call
342
  /// occurs.
343
  SmallVector<CallArgCleanup, 1> CleanupsToDeactivate;
344
345
  /// The stacksave call.  It dominates all of the argument evaluation.
346
  llvm::CallInst *StackBase = nullptr;
347
};
348
349
/// FunctionArgList - Type for representing both the decl and type
350
/// of parameters to a function. The decl must be either a
351
/// ParmVarDecl or ImplicitParamDecl.
352
class FunctionArgList : public SmallVector<const VarDecl *, 16> {};
353
354
/// ReturnValueSlot - Contains the address where the return value of a
355
/// function can be stored, and whether the address is volatile or not.
356
class ReturnValueSlot {
357
  Address Addr = Address::invalid();
358
359
  // Return value slot flags
360
  unsigned IsVolatile : 1;
361
  unsigned IsUnused : 1;
362
  unsigned IsExternallyDestructed : 1;
363
364
public:
365
  ReturnValueSlot()
366
0
      : IsVolatile(false), IsUnused(false), IsExternallyDestructed(false) {}
367
  ReturnValueSlot(Address Addr, bool IsVolatile, bool IsUnused = false,
368
                  bool IsExternallyDestructed = false)
369
      : Addr(Addr), IsVolatile(IsVolatile), IsUnused(IsUnused),
370
0
        IsExternallyDestructed(IsExternallyDestructed) {}
371
372
0
  bool isNull() const { return !Addr.isValid(); }
373
0
  bool isVolatile() const { return IsVolatile; }
374
0
  Address getValue() const { return Addr; }
375
0
  bool isUnused() const { return IsUnused; }
376
0
  bool isExternallyDestructed() const { return IsExternallyDestructed; }
377
};
378
379
/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
380
/// though we had emitted it ourselves. We remove any attributes on F that
381
/// conflict with the attributes we add here.
382
///
383
/// This is useful for adding attrs to bitcode modules that you want to link
384
/// with but don't control, such as CUDA's libdevice.  When linking with such
385
/// a bitcode library, you might want to set e.g. its functions'
386
/// "unsafe-fp-math" attribute to match the attr of the functions you're
387
/// codegen'ing.  Otherwise, LLVM will interpret the bitcode module's lack of
388
/// unsafe-fp-math attrs as tantamount to unsafe-fp-math=false, and then LLVM
389
/// will propagate unsafe-fp-math=false up to every transitive caller of a
390
/// function in the bitcode library!
391
///
392
/// With the exception of fast-math attrs, this will only make the attributes
393
/// on the function more conservative.  But it's unsafe to call this on a
394
/// function which relies on particular fast-math attributes for correctness.
395
/// It's up to you to ensure that this is safe.
396
void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,
397
                                              const CodeGenOptions &CodeGenOpts,
398
                                              const LangOptions &LangOpts,
399
                                              const TargetOptions &TargetOpts,
400
                                              bool WillInternalize);
401
402
enum class FnInfoOpts {
403
  None = 0,
404
  IsInstanceMethod = 1 << 0,
405
  IsChainCall = 1 << 1,
406
  IsDelegateCall = 1 << 2,
407
};
408
409
0
inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) {
410
0
  return static_cast<FnInfoOpts>(llvm::to_underlying(A) |
411
0
                                 llvm::to_underlying(B));
412
0
}
413
414
0
inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) {
415
0
  return static_cast<FnInfoOpts>(llvm::to_underlying(A) &
416
0
                                 llvm::to_underlying(B));
417
0
}
418
419
0
inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) {
420
0
  A = A | B;
421
0
  return A;
422
0
}
423
424
0
inline FnInfoOpts operator&=(FnInfoOpts A, FnInfoOpts B) {
425
0
  A = A & B;
426
0
  return A;
427
0
}
428
429
} // end namespace CodeGen
430
} // end namespace clang
431
432
#endif