clang 10.0.0git

ByteCodeEmitter.cpp
Go to the documentation of this file.
1 //===--- ByteCodeEmitter.cpp - Instruction emitter for the VM ---*- 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 #include "ByteCodeEmitter.h"
10 #include "Context.h"
11 #include "Opcode.h"
12 #include "Program.h"
13 #include "clang/AST/DeclCXX.h"
14
15 using namespace clang;
16 using namespace clang::interp;
17
18 using APSInt = llvm::APSInt;
19 using Error = llvm::Error;
20
21 Expected<Function *> ByteCodeEmitter::compileFunc(const FunctionDecl *F) {
22 // Do not try to compile undefined functions.
23 if (!F->isDefined(F) || (!F->hasBody() && F->willHaveBody()))
24 return nullptr;
25
26 // Set up argument indices.
27 unsigned ParamOffset = 0;
28 SmallVector<PrimType, 8> ParamTypes;
29 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
30
31 // If the return is not a primitive, a pointer to the storage where the value
32 // is initialized in is passed as the first argument.
33 QualType Ty = F->getReturnType();
34 if (!Ty->isVoidType() && !Ctx.classify(Ty)) {
35 ParamTypes.push_back(PT_Ptr);
36 ParamOffset += align(primSize(PT_Ptr));
37 }
38
39 // Assign descriptors to all parameters.
40 // Composite objects are lowered to pointers.
41 for (const ParmVarDecl *PD : F->parameters()) {
42 PrimType Ty;
43 if (llvm::Optional<PrimType> T = Ctx.classify(PD->getType())) {
44 Ty = *T;
45 } else {
46 Ty = PT_Ptr;
47 }
48
49 Descriptor *Desc = P.createDescriptor(PD, Ty);
50 ParamDescriptors.insert({ParamOffset, {Ty, Desc}});
51 Params.insert({PD, ParamOffset});
52 ParamOffset += align(primSize(Ty));
53 ParamTypes.push_back(Ty);
54 }
55
56 // Create a handle over the emitted code.
57 Function *Func = P.createFunction(F, ParamOffset, std::move(ParamTypes),
58 std::move(ParamDescriptors));
59 // Compile the function body.
60 if (!F->isConstexpr() || !visitFunc(F)) {
61 // Return a dummy function if compilation failed.
62 if (BailLocation)
63 return llvm::make_error<ByteCodeGenError>(*BailLocation);
64 else
65 return Func;
66 } else {
67 // Create scopes from descriptors.
68 llvm::SmallVector<Scope, 2> Scopes;
69 for (auto &DS : Descriptors) {
70 Scopes.emplace_back(std::move(DS));
71 }
72
73 // Set the function's code.
74 Func->setCode(NextLocalOffset, std::move(Code), std::move(SrcMap),
75 std::move(Scopes));
76 return Func;
77 }
78 }
79
80 Scope::Local ByteCodeEmitter::createLocal(Descriptor *D) {
81 NextLocalOffset += sizeof(Block);
82 unsigned Location = NextLocalOffset;
83 NextLocalOffset += align(D->getAllocSize());
84 return {Location, D};
85 }
86
87 void ByteCodeEmitter::emitLabel(LabelTy Label) {
88 const size_t Target = Code.size();
89 LabelOffsets.insert({Label, Target});
90 auto It = LabelRelocs.find(Label);
91 if (It != LabelRelocs.end()) {
92 for (unsigned Reloc : It->second) {
93 using namespace llvm::support;
94
95 /// Rewrite the operand of all jumps to this label.
96 void *Location = Code.data() + Reloc - sizeof(int32_t);
97 const int32_t Offset = Target - static_cast<int64_t>(Reloc);
98 endian::write<int32_t, endianness::native, 1>(Location, Offset);
99 }
100 LabelRelocs.erase(It);
101 }
102 }
103
104 int32_t ByteCodeEmitter::getOffset(LabelTy Label) {
105 // Compute the PC offset which the jump is relative to.
106 const int64_t Position = Code.size() + sizeof(Opcode) + sizeof(int32_t);
107
108 // If target is known, compute jump offset.
109 auto It = LabelOffsets.find(Label);
110 if (It != LabelOffsets.end()) {
111 return It->second - Position;
112 }
113
114 // Otherwise, record relocation and return dummy offset.
115 LabelRelocs[Label].push_back(Position);
116 return 0ull;
117 }
118
119 bool ByteCodeEmitter::bail(const SourceLocation &Loc) {
120 if (!BailLocation)
121 BailLocation = Loc;
122 return false;
123 }
124
125 template <typename... Tys>
126 bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &SI) {
127 bool Success = true;
128
129 /// Helper to write bytecode and bail out if 32-bit offsets become invalid.
130 auto emit = [this, &Success](const char *Data, size_t Size) {
131 if (Code.size() + Size > std::numeric_limits<unsigned>::max()) {
132 Success = false;
133 return;
134 }
135 Code.insert(Code.end(), Data, Data + Size);
136 };
137
138 /// The opcode is followed by arguments. The source info is
139 /// attached to the address after the opcode.
140 emit(reinterpret_cast<const char *>(&Op), sizeof(Opcode));
141 if (SI)
142 SrcMap.emplace_back(Code.size(), SI);
143
144 /// The initializer list forces the expression to be evaluated
145 /// for each argument in the variadic template, in order.
146 (void)std::initializer_list<int>{
147 (emit(reinterpret_cast<const char *>(&Args), sizeof(Args)), 0)...};
148
149 return Success;
150 }
151
152 bool ByteCodeEmitter::jumpTrue(const LabelTy &Label) {
153 return emitJt(getOffset(Label), SourceInfo{});
154 }
155
156 bool ByteCodeEmitter::jumpFalse(const LabelTy &Label) {
157 return emitJf(getOffset(Label), SourceInfo{});
158 }
159
160 bool ByteCodeEmitter::jump(const LabelTy &Label) {
161 return emitJmp(getOffset(Label), SourceInfo{});
162 }
163
164 bool ByteCodeEmitter::fallthrough(const LabelTy &Label) {
165 emitLabel(Label);
166 return true;
167 }
168
169 //===----------------------------------------------------------------------===//
170 // Opcode emitters
171 //===----------------------------------------------------------------------===//
172
173 #define GET_LINK_IMPL
174 #include "Opcodes.inc"
175 #undef GET_LINK_IMPL
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1783
clang::interp::primSize
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:17
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:654
clang::FunctionDecl::willHaveBody
bool willHaveBody() const
True if this function will eventually have a body, once it&#39;s fully parsed.
Definition: Decl.h:2347
clang::FunctionDecl::isConstexpr
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2200
clang::interp::Program::createDescriptor
Descriptor * createDescriptor(const DeclTy &D, PrimType Type, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false)
Creates a descriptor for a primitive type.
Definition: Program.h:101
clang::interp::align
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:57
clang::FunctionDecl::isDefined
bool isDefined(const FunctionDecl *&Definition) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:2883
ByteCodeEmitter.h
clang::FunctionDecl::getReturnType
QualType getReturnType() const
Definition: Decl.h:2445
clang::interp::SourceInfo
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:81
clang::MultiVersionKind::Target
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1595
clang::interp::Context::classify
llvm::Optional< PrimType > classify(QualType T)
Classifies an expression.
Definition: Context.cpp:61
clang::interp::ByteCodeEmitter::Params
llvm::DenseMap< const ParmVarDecl *, unsigned > Params
Parameter indices.
Definition: ByteCodeEmitter.h:72
llvm::Optional< PrimType >
clang::interp::ByteCodeEmitter::bail
bool bail(const Stmt *S)
Bails out if a given node cannot be compiled.
Definition: ByteCodeEmitter.h:58
clang::interp::ByteCodeEmitter::jumpTrue
bool jumpTrue(const LabelTy &Label)
Emits jumps.
Definition: ByteCodeEmitter.cpp:152
clang::interp::Block
A memory block, either on the stack or in the heap.
Definition: Block.h:37
max
__DEVICE__ int max(int __a, int __b)
Definition: __clang_cuda_device_functions.h:1628
clang::interp::ByteCodeEmitter::compileFunc
llvm::Expected< Function * > compileFunc(const FunctionDecl *F)
Compiles the function into the module.
Definition: ByteCodeEmitter.cpp:21
Context.h
clang::FunctionDecl::parameters
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2399
llvm::Expected
Definition: LLVM.h:38
clang::interp::PrimType
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:27
Error
llvm::Error Error
Definition: ByteCodeEmitter.cpp:19
clang::interp::ByteCodeEmitter::fallthrough
bool fallthrough(const LabelTy &Label)
Definition: ByteCodeEmitter.cpp:164
clang::interp::Descriptor
Describes a memory block created by an allocation site.
Definition: Descriptor.h:51
clang::interp::ByteCodeEmitter::jumpFalse
bool jumpFalse(const LabelTy &Label)
Definition: ByteCodeEmitter.cpp:156
Offset
unsigned Offset
Definition: Format.cpp:1827
Label
std::string Label
Definition: UsingDeclarationsSorter.cpp:69
clang::interp::Scope::Local
Information about a local&#39;s storage.
Definition: Function.h:35
clang::FunctionDecl::hasBody
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:2859
clang::DiagnosticLevelMask::Error
clang::interp::ByteCodeEmitter::jump
bool jump(const LabelTy &Label)
Definition: ByteCodeEmitter.cpp:160
clang::interp::Program::createFunction
Function * createFunction(const FunctionDecl *Def, Ts &&... Args)
Creates a new function from a code range.
Definition: Program.h:76
Program.h
clang::interp::ByteCodeEmitter::createLocal
Local createLocal(Descriptor *D)
Callback for local registration.
Definition: ByteCodeEmitter.cpp:80
Opcode.h
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
clang::interp::Descriptor::getAllocSize
unsigned getAllocSize() const
Returns the allocated size, including metadata.
Definition: Descriptor.h:134
APSInt
llvm::APSInt APSInt
Definition: ByteCodeEmitter.cpp:18
clang::interp::Function
Bytecode function.
Definition: Function.h:59
llvm::SmallVector< PrimType, 8 >
clang::interp::ByteCodeEmitter::emitLabel
void emitLabel(LabelTy Label)
Define a label.
Definition: ByteCodeEmitter.cpp:87
clang::interp::ByteCodeEmitter::visitFunc
virtual bool visitFunc(const FunctionDecl *E)=0
Methods implemented by the compiler.
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:21
clang::interp::PT_Ptr
Definition: PrimType.h:37
clang::interp::ByteCodeEmitter::Descriptors
llvm::SmallVector< SmallVector< Local, 8 >, 2 > Descriptors
Local descriptors.
Definition: ByteCodeEmitter.h:74
DeclCXX.h
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:6777
clang::interp
Definition: ASTContext.h:146
clang::interp::ByteCodeEmitter::LabelTy
uint32_t LabelTy
Definition: ByteCodeEmitter.h:34
clang::interp::Opcode
Opcode
Definition: Opcode.h:21