164 lines
4.9 KiB
C
164 lines
4.9 KiB
C
|
//===--- Function.h - Bytecode function for the VM --------------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// Defines the Function class which holds all bytecode function-specific data.
|
||
|
//
|
||
|
// The scope class which describes local variables is also defined here.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H
|
||
|
#define LLVM_CLANG_AST_INTERP_FUNCTION_H
|
||
|
|
||
|
#include "Pointer.h"
|
||
|
#include "Source.h"
|
||
|
#include "clang/AST/Decl.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
|
||
|
namespace clang {
|
||
|
namespace interp {
|
||
|
class Program;
|
||
|
class ByteCodeEmitter;
|
||
|
enum PrimType : uint32_t;
|
||
|
|
||
|
/// Describes a scope block.
|
||
|
///
|
||
|
/// The block gathers all the descriptors of the locals defined in this block.
|
||
|
class Scope {
|
||
|
public:
|
||
|
/// Information about a local's storage.
|
||
|
struct Local {
|
||
|
/// Offset of the local in frame.
|
||
|
unsigned Offset;
|
||
|
/// Descriptor of the local.
|
||
|
Descriptor *Desc;
|
||
|
};
|
||
|
|
||
|
using LocalVectorTy = llvm::SmallVector<Local, 8>;
|
||
|
|
||
|
Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
|
||
|
|
||
|
llvm::iterator_range<LocalVectorTy::iterator> locals() {
|
||
|
return llvm::make_range(Descriptors.begin(), Descriptors.end());
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
/// Object descriptors in this block.
|
||
|
LocalVectorTy Descriptors;
|
||
|
};
|
||
|
|
||
|
/// Bytecode function.
|
||
|
///
|
||
|
/// Contains links to the bytecode of the function, as well as metadata
|
||
|
/// describing all arguments and stack-local variables.
|
||
|
class Function {
|
||
|
public:
|
||
|
using ParamDescriptor = std::pair<PrimType, Descriptor *>;
|
||
|
|
||
|
/// Returns the size of the function's local stack.
|
||
|
unsigned getFrameSize() const { return FrameSize; }
|
||
|
/// Returns the size of the argument stackx
|
||
|
unsigned getArgSize() const { return ArgSize; }
|
||
|
|
||
|
/// Returns a pointer to the start of the code.
|
||
|
CodePtr getCodeBegin() const;
|
||
|
/// Returns a pointer to the end of the code.
|
||
|
CodePtr getCodeEnd() const;
|
||
|
|
||
|
/// Returns the original FunctionDecl.
|
||
|
const FunctionDecl *getDecl() const { return F; }
|
||
|
|
||
|
/// Returns the lcoation.
|
||
|
SourceLocation getLoc() const { return Loc; }
|
||
|
|
||
|
/// Returns a parameter descriptor.
|
||
|
ParamDescriptor getParamDescriptor(unsigned Offset) const;
|
||
|
|
||
|
/// Checks if the first argument is a RVO pointer.
|
||
|
bool hasRVO() const { return ParamTypes.size() != Params.size(); }
|
||
|
|
||
|
/// Range over the scope blocks.
|
||
|
llvm::iterator_range<llvm::SmallVector<Scope, 2>::iterator> scopes() {
|
||
|
return llvm::make_range(Scopes.begin(), Scopes.end());
|
||
|
}
|
||
|
|
||
|
/// Range over argument types.
|
||
|
using arg_reverse_iterator = SmallVectorImpl<PrimType>::reverse_iterator;
|
||
|
llvm::iterator_range<arg_reverse_iterator> args_reverse() {
|
||
|
return llvm::make_range(ParamTypes.rbegin(), ParamTypes.rend());
|
||
|
}
|
||
|
|
||
|
/// Returns a specific scope.
|
||
|
Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
|
||
|
|
||
|
/// Returns the source information at a given PC.
|
||
|
SourceInfo getSource(CodePtr PC) const;
|
||
|
|
||
|
/// Checks if the function is valid to call in constexpr.
|
||
|
bool isConstexpr() const { return IsValid; }
|
||
|
|
||
|
/// Checks if the function is virtual.
|
||
|
bool isVirtual() const;
|
||
|
|
||
|
/// Checks if the function is a constructor.
|
||
|
bool isConstructor() const { return isa<CXXConstructorDecl>(F); }
|
||
|
|
||
|
private:
|
||
|
/// Construct a function representing an actual function.
|
||
|
Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
|
||
|
llvm::SmallVector<PrimType, 8> &&ParamTypes,
|
||
|
llvm::DenseMap<unsigned, ParamDescriptor> &&Params);
|
||
|
|
||
|
/// Sets the code of a function.
|
||
|
void setCode(unsigned NewFrameSize, std::vector<char> &&NewCode, SourceMap &&NewSrcMap,
|
||
|
llvm::SmallVector<Scope, 2> &&NewScopes) {
|
||
|
FrameSize = NewFrameSize;
|
||
|
Code = std::move(NewCode);
|
||
|
SrcMap = std::move(NewSrcMap);
|
||
|
Scopes = std::move(NewScopes);
|
||
|
IsValid = true;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
friend class Program;
|
||
|
friend class ByteCodeEmitter;
|
||
|
|
||
|
/// Program reference.
|
||
|
Program &P;
|
||
|
/// Location of the executed code.
|
||
|
SourceLocation Loc;
|
||
|
/// Declaration this function was compiled from.
|
||
|
const FunctionDecl *F;
|
||
|
/// Local area size: storage + metadata.
|
||
|
unsigned FrameSize;
|
||
|
/// Size of the argument stack.
|
||
|
unsigned ArgSize;
|
||
|
/// Program code.
|
||
|
std::vector<char> Code;
|
||
|
/// Opcode-to-expression mapping.
|
||
|
SourceMap SrcMap;
|
||
|
/// List of block descriptors.
|
||
|
llvm::SmallVector<Scope, 2> Scopes;
|
||
|
/// List of argument types.
|
||
|
llvm::SmallVector<PrimType, 8> ParamTypes;
|
||
|
/// Map from byte offset to parameter descriptor.
|
||
|
llvm::DenseMap<unsigned, ParamDescriptor> Params;
|
||
|
/// Flag to indicate if the function is valid.
|
||
|
bool IsValid = false;
|
||
|
|
||
|
public:
|
||
|
/// Dumps the disassembled bytecode to \c llvm::errs().
|
||
|
void dump() const;
|
||
|
void dump(llvm::raw_ostream &OS) const;
|
||
|
};
|
||
|
|
||
|
} // namespace interp
|
||
|
} // namespace clang
|
||
|
|
||
|
#endif
|