Index: include/clang/CodeGen/Address.h =================================================================== --- include/clang/CodeGen/Address.h +++ include/clang/CodeGen/Address.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H -#define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H +#ifndef LLVM_CLANG_CODEGEN_ADDRESS_H +#define LLVM_CLANG_CODEGEN_ADDRESS_H #include "llvm/IR/Constants.h" #include "clang/AST/CharUnits.h" Index: include/clang/CodeGen/CGCallee.h =================================================================== --- /dev/null +++ include/clang/CodeGen/CGCallee.h @@ -0,0 +1,206 @@ +//===--- CGCallee.h - Encapsulate calling convention details ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes wrap the information about a call or function +// definition used to handle ABI compliancy. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CGCALLEE_H +#define LLVM_CLANG_CODEGEN_CGCALLEE_H + +#include "clang/AST/CanonicalType.h" +#include "clang/AST/GlobalDecl.h" +#include "clang/AST/Type.h" +#include "clang/CodeGen/Address.h" +#include "llvm/IR/Value.h" + +namespace clang { +namespace CodeGen { + +class CodeGenFunction; + +/// Abstract information about a function or function prototype. +class CGCalleeInfo { + /// The function prototype of the callee. + const FunctionProtoType *CalleeProtoTy; + /// The function declaration of the callee. + GlobalDecl CalleeDecl; + +public: + explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {} + CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl) + : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} + CGCalleeInfo(const FunctionProtoType *calleeProtoTy) + : CalleeProtoTy(calleeProtoTy), CalleeDecl() {} + CGCalleeInfo(GlobalDecl calleeDecl) + : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} + + const FunctionProtoType *getCalleeFunctionProtoType() const { + return CalleeProtoTy; + } + const GlobalDecl getCalleeDecl() const { return CalleeDecl; } +}; + +/// All available information about a concrete callee. +class CGCallee { + enum class SpecialKind : uintptr_t { + Invalid, + Builtin, + PseudoDestructor, + Virtual, + + Last = Virtual + }; + + struct BuiltinInfoStorage { + const FunctionDecl *Decl; + unsigned ID; + }; + 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) {} + + CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID) + : KindOrFunctionPointer(SpecialKind::Builtin) { + BuiltinInfo.Decl = builtinDecl; + BuiltinInfo.ID = builtinID; + } + +public: + CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {} + + /// Construct a callee. Call this constructor directly when this + /// isn't a direct call. + CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr) + : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) { + AbstractInfo = abstractInfo; + assert(functionPtr && "configuring callee without function pointer"); + assert(functionPtr->getType()->isPointerTy()); + assert(functionPtr->getType()->getPointerElementType()->isFunctionTy()); + } + + static CGCallee forBuiltin(unsigned builtinID, + const FunctionDecl *builtinDecl) { + CGCallee result(SpecialKind::Builtin); + result.BuiltinInfo.Decl = builtinDecl; + result.BuiltinInfo.ID = builtinID; + return result; + } + + static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) { + CGCallee result(SpecialKind::PseudoDestructor); + result.PseudoDestructorInfo.Expr = E; + return result; + } + + static CGCallee forDirect(llvm::Constant *functionPtr, + const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { + return CGCallee(abstractInfo, functionPtr); + } + + static CGCallee + forDirect(llvm::FunctionCallee functionPtr, + const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { + return CGCallee(abstractInfo, functionPtr.getCallee()); + } + + 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; + } + const FunctionDecl *getBuiltinDecl() const { + assert(isBuiltin()); + return BuiltinInfo.Decl; + } + unsigned getBuiltinID() const { + assert(isBuiltin()); + return BuiltinInfo.ID; + } + + bool isPseudoDestructor() const { + return KindOrFunctionPointer == SpecialKind::PseudoDestructor; + } + const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const { + assert(isPseudoDestructor()); + return PseudoDestructorInfo.Expr; + } + + bool isOrdinary() const { + return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last); + } + CGCalleeInfo getAbstractInfo() const { + if (isVirtual()) + return VirtualInfo.MD; + assert(isOrdinary()); + return AbstractInfo; + } + llvm::Value *getFunctionPointer() const { + assert(isOrdinary()); + return reinterpret_cast(uintptr_t(KindOrFunctionPointer)); + } + 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 *getVirtualFunctionType() const { + assert(isVirtual()); + return VirtualInfo.FTy; + } + + /// If this is a delayed callee computation of some sort, prepare + /// a concrete callee. + CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const; +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif Index: include/clang/CodeGen/CodeGenABITypes.h =================================================================== --- include/clang/CodeGen/CodeGenABITypes.h +++ include/clang/CodeGen/CodeGenABITypes.h @@ -65,6 +65,9 @@ const FunctionProtoType *FTP, const CXXMethodDecl *MD); +const CGFunctionInfo &arrangeCXXMethodDeclaration(CodeGenModule &CGM, + const CXXMethodDecl *MD); + const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM, CanQualType returnType, ArrayRef argTypes, @@ -75,6 +78,9 @@ llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM, const FunctionDecl *FD); +llvm::FunctionType *getFunctionType(CodeGenModule &CGM, + const CGFunctionInfo &FI); + llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T); /// Given a non-bitfield struct field, return its index within the elements of Index: include/clang/CodeGen/FunctionBuilder.h =================================================================== --- /dev/null +++ include/clang/CodeGen/FunctionBuilder.h @@ -0,0 +1,69 @@ +//===--- CodeGen/FunctionBuilder.h - Build LLVM from AST Decls --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FunctionBuilder interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_FUNCTIONBUILDER_H +#define LLVM_CLANG_CODEGEN_FUNCTIONBUILDER_H + +#include +#include "clang/CodeGen/Address.h" +#include "clang/CodeGen/CGCallee.h" +#include "clang/AST/GlobalDecl.h" + +namespace llvm { +class IRBuilderBase; +} + +namespace clang { +namespace CodeGen { + +class CodeGenModule; +class CodeGenFunction; + +/// A public api for working with a subset of the features of +/// CodeGen::CodeGenFunction. +/// +/// This is not really an abstract interface. +class FunctionBuilder { + protected: + FunctionBuilder() {} + FunctionBuilder(const FunctionBuilder&) = delete; + FunctionBuilder(FunctionBuilder&&) = delete; + + public: + virtual ~FunctionBuilder(); + + /// Returns an opaque reference to the underlying CodeGenFunction object. + /// This can be passed to other APIs and is valid for the lifetime of this + /// object. + CodeGen::CodeGenFunction &CGF(); + + /// Gets access to the underlying llvm builder for interop between multiple + /// llvm IR builders. + llvm::IRBuilderBase &getBuilder(); + + /// Perform ABI-specific "this" argument adjustment required prior to + /// a call of a virtual function. The "VirtualCall" argument is true iff the + /// call itself is virtual. `thisAddr` should already have the same type as + /// the function on which the virtual method is defined. + Address emitAdjustThisArgumentForVirtualFunctionCall(Address thisAddr, + GlobalDecl GD, + bool VirtualCall); + + /// Creates a FunctionBuilder. CGM must outlive the result. + static std::unique_ptr Create(CodeGenModule &CGM); +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif Index: lib/CodeGen/CGBuilder.h =================================================================== --- lib/CodeGen/CGBuilder.h +++ lib/CodeGen/CGBuilder.h @@ -11,7 +11,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" -#include "Address.h" +#include "clang/CodeGen/Address.h" #include "CodeGenTypeCache.h" namespace clang { Index: lib/CodeGen/CGCall.h =================================================================== --- lib/CodeGen/CGCall.h +++ lib/CodeGen/CGCall.h @@ -19,11 +19,9 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/Type.h" +#include "clang/CodeGen/CGCallee.h" #include "llvm/IR/Value.h" -// FIXME: Restructure so we don't have to expose so much stuff. -#include "ABIInfo.h" - namespace llvm { class AttributeList; class Function; @@ -40,180 +38,6 @@ namespace CodeGen { -/// Abstract information about a function or function prototype. -class CGCalleeInfo { - /// The function prototype of the callee. - const FunctionProtoType *CalleeProtoTy; - /// The function declaration of the callee. - GlobalDecl CalleeDecl; - -public: - explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl() {} - CGCalleeInfo(const FunctionProtoType *calleeProtoTy, GlobalDecl calleeDecl) - : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {} - CGCalleeInfo(const FunctionProtoType *calleeProtoTy) - : CalleeProtoTy(calleeProtoTy), CalleeDecl() {} - CGCalleeInfo(GlobalDecl calleeDecl) - : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {} - - const FunctionProtoType *getCalleeFunctionProtoType() const { - return CalleeProtoTy; - } - const GlobalDecl getCalleeDecl() const { return CalleeDecl; } - }; - - /// All available information about a concrete callee. - class CGCallee { - enum class SpecialKind : uintptr_t { - Invalid, - Builtin, - PseudoDestructor, - Virtual, - - Last = Virtual - }; - - struct BuiltinInfoStorage { - const FunctionDecl *Decl; - unsigned ID; - }; - 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) {} - - CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID) - : KindOrFunctionPointer(SpecialKind::Builtin) { - BuiltinInfo.Decl = builtinDecl; - BuiltinInfo.ID = builtinID; - } - - public: - CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {} - - /// Construct a callee. Call this constructor directly when this - /// isn't a direct call. - CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr) - : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) { - AbstractInfo = abstractInfo; - assert(functionPtr && "configuring callee without function pointer"); - assert(functionPtr->getType()->isPointerTy()); - assert(functionPtr->getType()->getPointerElementType()->isFunctionTy()); - } - - static CGCallee forBuiltin(unsigned builtinID, - const FunctionDecl *builtinDecl) { - CGCallee result(SpecialKind::Builtin); - result.BuiltinInfo.Decl = builtinDecl; - result.BuiltinInfo.ID = builtinID; - return result; - } - - static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) { - CGCallee result(SpecialKind::PseudoDestructor); - result.PseudoDestructorInfo.Expr = E; - return result; - } - - static CGCallee forDirect(llvm::Constant *functionPtr, - const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { - return CGCallee(abstractInfo, functionPtr); - } - - static CGCallee - forDirect(llvm::FunctionCallee functionPtr, - const CGCalleeInfo &abstractInfo = CGCalleeInfo()) { - return CGCallee(abstractInfo, functionPtr.getCallee()); - } - - 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; - } - const FunctionDecl *getBuiltinDecl() const { - assert(isBuiltin()); - return BuiltinInfo.Decl; - } - unsigned getBuiltinID() const { - assert(isBuiltin()); - return BuiltinInfo.ID; - } - - bool isPseudoDestructor() const { - return KindOrFunctionPointer == SpecialKind::PseudoDestructor; - } - const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const { - assert(isPseudoDestructor()); - return PseudoDestructorInfo.Expr; - } - - bool isOrdinary() const { - return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last); - } - CGCalleeInfo getAbstractInfo() const { - if (isVirtual()) - return VirtualInfo.MD; - assert(isOrdinary()); - return AbstractInfo; - } - llvm::Value *getFunctionPointer() const { - assert(isOrdinary()); - return reinterpret_cast(uintptr_t(KindOrFunctionPointer)); - } - 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 *getVirtualFunctionType() const { - assert(isVirtual()); - return VirtualInfo.FTy; - } - - /// If this is a delayed callee computation of some sort, prepare - /// a concrete callee. - CGCallee prepareConcreteCallee(CodeGenFunction &CGF) const; - }; - struct CallArg { private: union { Index: lib/CodeGen/CGCleanup.h =================================================================== --- lib/CodeGen/CGCleanup.h +++ lib/CodeGen/CGCleanup.h @@ -15,7 +15,7 @@ #include "EHScopeStack.h" -#include "Address.h" +#include "clang/CodeGen/Address.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" Index: lib/CodeGen/CGObjCRuntime.h =================================================================== --- lib/CodeGen/CGObjCRuntime.h +++ lib/CodeGen/CGObjCRuntime.h @@ -18,6 +18,7 @@ #include "CGCall.h" #include "CGCleanup.h" #include "CGValue.h" +#include "ABIInfo.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/IdentifierTable.h" // Selector Index: lib/CodeGen/CGValue.h =================================================================== --- lib/CodeGen/CGValue.h +++ lib/CodeGen/CGValue.h @@ -18,7 +18,7 @@ #include "clang/AST/Type.h" #include "llvm/IR/Value.h" #include "llvm/IR/Type.h" -#include "Address.h" +#include "clang/CodeGen/Address.h" #include "CodeGenTBAA.h" namespace llvm { Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -84,6 +84,7 @@ CodeGenTypes.cpp ConstantInitBuilder.cpp CoverageMappingGen.cpp + FunctionBuilder.cpp ItaniumCXXABI.cpp MacroPPCallbacks.cpp MicrosoftCXXABI.cpp Index: lib/CodeGen/CodeGenABITypes.cpp =================================================================== --- lib/CodeGen/CodeGenABITypes.cpp +++ lib/CodeGen/CodeGenABITypes.cpp @@ -52,6 +52,17 @@ return CGM.getTypes().arrangeCXXMethodType(RD, FTP, MD); } +const CGFunctionInfo & +CodeGen::arrangeCXXMethodDeclaration(CodeGenModule &CGM, + const CXXMethodDecl *MD) { + return CGM.getTypes().arrangeCXXMethodDeclaration(MD); +} + +llvm::FunctionType *CodeGen::getFunctionType(CodeGenModule &CGM, + const CGFunctionInfo &FI) { + return CGM.getTypes().GetFunctionType(FI); +} + const CGFunctionInfo & CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM, CanQualType returnType, Index: lib/CodeGen/FunctionBuilder.cpp =================================================================== --- /dev/null +++ lib/CodeGen/FunctionBuilder.cpp @@ -0,0 +1,48 @@ +//===--- ModuleBuilder.cpp - Emit LLVM Code from ASTs ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This exposes a subset of the CodeGenFunction API. +// +//===----------------------------------------------------------------------===// + +#include "clang/CodeGen/FunctionBuilder.h" +#include "CGCXXABI.h" +#include "CodeGenFunction.h" +#include "clang/Basic/TargetInfo.h" + +using namespace clang; +using namespace CodeGen; + +namespace { +class FunctionBuilderImpl : public FunctionBuilder { + public: + CodeGenFunction CGF; + + FunctionBuilderImpl(CodeGenModule &CGM) + : CGF(CGM, /*suppressNewContext=*/true) {} +}; +} // namespace + +FunctionBuilder::~FunctionBuilder() {} + +std::unique_ptr FunctionBuilder::Create(CodeGenModule &CGM) { + return std::unique_ptr(new FunctionBuilderImpl(CGM)); +} + +CodeGenFunction &FunctionBuilder::CGF() { + return static_cast(this)->CGF; +} + +llvm::IRBuilderBase &FunctionBuilder::getBuilder() { return CGF().Builder; } + +Address FunctionBuilder::emitAdjustThisArgumentForVirtualFunctionCall( + Address thisAddr, GlobalDecl GD, bool VirtualCall) { + return CGF().CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( + CGF(), GD, thisAddr, VirtualCall); +}