#ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H
#define LLVM_CLANG_AST_INTERP_FUNCTION_H
#include "Descriptor.h"
#include "Source.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace interp {
class Program;
class ByteCodeEmitter;
class Pointer;
enum PrimType : uint32_t;
class Scope final {
public:
struct Local {
unsigned Offset;
Descriptor *Desc;
};
using LocalVectorTy = llvm::SmallVector<Local, 8>;
Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {
return llvm::make_range(Descriptors.begin(), Descriptors.end());
}
private:
LocalVectorTy Descriptors;
};
class Function final {
public:
using ParamDescriptor = std::pair<PrimType, Descriptor *>;
unsigned getFrameSize() const { return FrameSize; }
unsigned getArgSize() const { return ArgSize; }
CodePtr getCodeBegin() const { return Code.data(); }
CodePtr getCodeEnd() const { return Code.data() + Code.size(); }
const FunctionDecl *getDecl() const { return F; }
const std::string getName() const {
if (!F)
return "<<expr>>";
return F->getQualifiedNameAsString();
}
SourceLocation getLoc() const { return Loc; }
ParamDescriptor getParamDescriptor(unsigned Offset) const;
bool hasRVO() const { return HasRVO; }
bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); }
llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>
scopes() const {
return llvm::make_range(Scopes.begin(), Scopes.end());
}
using arg_reverse_iterator =
SmallVectorImpl<PrimType>::const_reverse_iterator;
llvm::iterator_range<arg_reverse_iterator> args_reverse() const {
return llvm::reverse(ParamTypes);
}
Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }
SourceInfo getSource(CodePtr PC) const;
bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); }
bool isVirtual() const;
bool isConstructor() const { return isa<CXXConstructorDecl>(F); }
bool isDestructor() const { return isa<CXXDestructorDecl>(F); }
const CXXRecordDecl *getParentDecl() const {
if (const auto *MD = dyn_cast<CXXMethodDecl>(F))
return MD->getParent();
return nullptr;
}
bool isLambdaStaticInvoker() const {
if (const auto *MD = dyn_cast<CXXMethodDecl>(F))
return MD->isLambdaStaticInvoker();
return false;
}
bool isLambdaCallOperator() const {
if (const auto *MD = dyn_cast<CXXMethodDecl>(F))
return clang::isLambdaCallOperator(MD);
return false;
}
bool isFullyCompiled() const { return IsFullyCompiled; }
bool hasThisPointer() const { return HasThisPointer; }
bool hasBody() const { return HasBody; }
bool isDefined() const { return Defined; }
bool isVariadic() const { return Variadic; }
unsigned getBuiltinID() const { return F->getBuiltinID(); }
bool isBuiltin() const { return F->getBuiltinID() != 0; }
bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; }
unsigned getNumParams() const { return ParamTypes.size(); }
unsigned getNumWrittenParams() const {
assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO()));
return getNumParams() - hasThisPointer() - hasRVO();
}
unsigned getWrittenArgSize() const {
return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO()));
}
bool isThisPointerExplicit() const {
if (const auto *MD = dyn_cast<CXXMethodDecl>(F))
return MD->isExplicitObjectMemberFunction();
return false;
}
unsigned getParamOffset(unsigned ParamIndex) const {
return ParamOffsets[ParamIndex];
}
private:
Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
llvm::SmallVectorImpl<PrimType> &&ParamTypes,
llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
bool HasRVO, bool UnevaluatedBuiltin);
void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,
bool NewHasBody) {
FrameSize = NewFrameSize;
Code = std::move(NewCode);
SrcMap = std::move(NewSrcMap);
Scopes = std::move(NewScopes);
IsValid = true;
HasBody = NewHasBody;
}
void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
void setDefined(bool D) { Defined = D; }
private:
friend class Program;
friend class ByteCodeEmitter;
Program &P;
SourceLocation Loc;
const FunctionDecl *F;
unsigned FrameSize = 0;
unsigned ArgSize;
std::vector<std::byte> Code;
SourceMap SrcMap;
llvm::SmallVector<Scope, 2> Scopes;
llvm::SmallVector<PrimType, 8> ParamTypes;
llvm::DenseMap<unsigned, ParamDescriptor> Params;
llvm::SmallVector<unsigned, 8> ParamOffsets;
bool IsValid = false;
bool IsFullyCompiled = false;
bool HasThisPointer = false;
bool HasRVO = false;
bool HasBody = false;
bool Defined = false;
bool Variadic = false;
bool IsUnevaluatedBuiltin = false;
public:
void dump() const;
void dump(llvm::raw_ostream &OS) const;
};
}
}
#endif