summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools/clang/lib/CodeGen/CGCall.h')
-rw-r--r--gnu/llvm/tools/clang/lib/CodeGen/CGCall.h118
1 files changed, 99 insertions, 19 deletions
diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h
index 7e10407fc31..99a36e4e12f 100644
--- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h
+++ b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.h
@@ -18,6 +18,7 @@
#include "CGValue.h"
#include "EHScopeStack.h"
#include "clang/AST/CanonicalType.h"
+#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
@@ -42,9 +43,9 @@ namespace CodeGen {
/// Abstract information about a function or function prototype.
class CGCalleeInfo {
- /// \brief The function prototype of the callee.
+ /// The function prototype of the callee.
const FunctionProtoType *CalleeProtoTy;
- /// \brief The function declaration of the callee.
+ /// The function declaration of the callee.
const Decl *CalleeDecl;
public:
@@ -68,8 +69,9 @@ public:
Invalid,
Builtin,
PseudoDestructor,
+ Virtual,
- Last = PseudoDestructor
+ Last = Virtual
};
struct BuiltinInfoStorage {
@@ -79,12 +81,19 @@ public:
struct PseudoDestructorInfoStorage {
const CXXPseudoDestructorExpr *Expr;
};
+ struct VirtualInfoStorage {
+ const CallExpr *CE;
+ GlobalDecl MD;
+ Address Addr;
+ llvm::FunctionType *FTy;
+ };
SpecialKind KindOrFunctionPointer;
union {
CGCalleeInfo AbstractInfo;
BuiltinInfoStorage BuiltinInfo;
PseudoDestructorInfoStorage PseudoDestructorInfo;
+ VirtualInfoStorage VirtualInfo;
};
explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
@@ -127,6 +136,16 @@ public:
return CGCallee(abstractInfo, functionPtr);
}
+ static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr,
+ llvm::FunctionType *FTy) {
+ CGCallee result(SpecialKind::Virtual);
+ result.VirtualInfo.CE = CE;
+ result.VirtualInfo.MD = MD;
+ result.VirtualInfo.Addr = Addr;
+ result.VirtualInfo.FTy = FTy;
+ return result;
+ }
+
bool isBuiltin() const {
return KindOrFunctionPointer == SpecialKind::Builtin;
}
@@ -150,7 +169,9 @@ public:
bool isOrdinary() const {
return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
}
- const CGCalleeInfo &getAbstractInfo() const {
+ CGCalleeInfo getAbstractInfo() const {
+ if (isVirtual())
+ return VirtualInfo.MD.getDecl();
assert(isOrdinary());
return AbstractInfo;
}
@@ -158,29 +179,86 @@ public:
assert(isOrdinary());
return reinterpret_cast<llvm::Value*>(uintptr_t(KindOrFunctionPointer));
}
- llvm::FunctionType *getFunctionType() const {
- return cast<llvm::FunctionType>(
- getFunctionPointer()->getType()->getPointerElementType());
- }
void setFunctionPointer(llvm::Value *functionPtr) {
assert(isOrdinary());
KindOrFunctionPointer = SpecialKind(uintptr_t(functionPtr));
}
+
+ bool isVirtual() const {
+ return KindOrFunctionPointer == SpecialKind::Virtual;
+ }
+ const CallExpr *getVirtualCallExpr() const {
+ assert(isVirtual());
+ return VirtualInfo.CE;
+ }
+ GlobalDecl getVirtualMethodDecl() const {
+ assert(isVirtual());
+ return VirtualInfo.MD;
+ }
+ Address getThisAddress() const {
+ assert(isVirtual());
+ return VirtualInfo.Addr;
+ }
+
+ llvm::FunctionType *getFunctionType() const {
+ if (isVirtual())
+ return VirtualInfo.FTy;
+ return cast<llvm::FunctionType>(
+ getFunctionPointer()->getType()->getPointerElementType());
+ }
+
+ /// If this is a delayed callee computation of some sort, prepare
+ /// a concrete callee.
+ CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const;
};
struct CallArg {
- RValue RV;
+ private:
+ union {
+ RValue RV;
+ LValue LV; /// The argument is semantically a load from this l-value.
+ };
+ bool HasLV;
+
+ /// A data-flow flag to make sure getRValue and/or copyInto are not
+ /// called twice for duplicated IR emission.
+ mutable bool IsUsed;
+
+ public:
QualType Ty;
- bool NeedsCopy;
- CallArg(RValue rv, QualType ty, bool needscopy)
- : RV(rv), Ty(ty), NeedsCopy(needscopy)
- { }
+ CallArg(RValue rv, QualType ty)
+ : RV(rv), HasLV(false), IsUsed(false), Ty(ty) {}
+ CallArg(LValue lv, QualType ty)
+ : LV(lv), HasLV(true), IsUsed(false), Ty(ty) {}
+ bool hasLValue() const { return HasLV; }
+ QualType getType() const { return Ty; }
+
+ /// \returns an independent RValue. If the CallArg contains an LValue,
+ /// a temporary copy is returned.
+ RValue getRValue(CodeGenFunction &CGF) const;
+
+ LValue getKnownLValue() const {
+ assert(HasLV && !IsUsed);
+ return LV;
+ }
+ RValue getKnownRValue() const {
+ assert(!HasLV && !IsUsed);
+ return RV;
+ }
+ void setRValue(RValue _RV) {
+ assert(!HasLV);
+ RV = _RV;
+ }
+
+ bool isAggregate() const { return HasLV || RV.isAggregate(); }
+
+ void copyInto(CodeGenFunction &CGF, Address A) const;
};
/// CallArgList - Type for representing both the value and type of
/// arguments in a call.
class CallArgList :
- public SmallVector<CallArg, 16> {
+ public SmallVector<CallArg, 8> {
public:
CallArgList() : StackBase(nullptr) {}
@@ -204,8 +282,10 @@ public:
llvm::Instruction *IsActiveIP;
};
- void add(RValue rvalue, QualType type, bool needscopy = false) {
- push_back(CallArg(rvalue, type, needscopy));
+ void add(RValue rvalue, QualType type) { push_back(CallArg(rvalue, type)); }
+
+ void addUncopiedAggregate(LValue LV, QualType type) {
+ push_back(CallArg(LV, type));
}
/// Add all the arguments from another CallArgList to this one. After doing
@@ -254,7 +334,7 @@ public:
llvm::Instruction *getStackBase() const { return StackBase; }
void freeArgumentMemory(CodeGenFunction &CGF) const;
- /// \brief Returns if we're using an inalloca struct to pass arguments in
+ /// Returns if we're using an inalloca struct to pass arguments in
/// memory.
bool isUsingInAlloca() const { return StackBase; }
@@ -276,7 +356,7 @@ public:
class FunctionArgList : public SmallVector<const VarDecl*, 16> {
};
- /// ReturnValueSlot - Contains the address where the return value of a
+ /// ReturnValueSlot - Contains the address where the return value of a
/// function can be stored, and whether the address is volatile or not.
class ReturnValueSlot {
llvm::PointerIntPair<llvm::Value *, 2, unsigned int> Value;
@@ -301,7 +381,7 @@ public:
Address getValue() const { return Address(Value.getPointer(), Alignment); }
bool isUnused() const { return Value.getInt() & IS_UNUSED; }
};
-
+
} // end namespace CodeGen
} // end namespace clang