diff options
Diffstat (limited to 'clang/lib/AST/Interp/ByteCodeEmitter.cpp')
-rw-r--r-- | clang/lib/AST/Interp/ByteCodeEmitter.cpp | 175 |
1 files changed, 0 insertions, 175 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp deleted file mode 100644 index 7a4569820a1..00000000000 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//===--- ByteCodeEmitter.cpp - Instruction emitter 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 -// -//===----------------------------------------------------------------------===// - -#include "ByteCodeEmitter.h" -#include "Context.h" -#include "Opcode.h" -#include "Program.h" -#include "clang/AST/DeclCXX.h" - -using namespace clang; -using namespace clang::interp; - -using APSInt = llvm::APSInt; -using Error = llvm::Error; - -Expected<Function *> ByteCodeEmitter::compileFunc(const FunctionDecl *F) { - // Do not try to compile undefined functions. - if (!F->isDefined(F) || (!F->hasBody() && F->willHaveBody())) - return nullptr; - - // Set up argument indices. - unsigned ParamOffset = 0; - SmallVector<PrimType, 8> ParamTypes; - llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors; - - // If the return is not a primitive, a pointer to the storage where the value - // is initialized in is passed as the first argument. - QualType Ty = F->getReturnType(); - if (!Ty->isVoidType() && !Ctx.classify(Ty)) { - ParamTypes.push_back(PT_Ptr); - ParamOffset += align(primSize(PT_Ptr)); - } - - // Assign descriptors to all parameters. - // Composite objects are lowered to pointers. - for (const ParmVarDecl *PD : F->parameters()) { - PrimType Ty; - if (llvm::Optional<PrimType> T = Ctx.classify(PD->getType())) { - Ty = *T; - } else { - Ty = PT_Ptr; - } - - Descriptor *Desc = P.createDescriptor(PD, Ty); - ParamDescriptors.insert({ParamOffset, {Ty, Desc}}); - Params.insert({PD, ParamOffset}); - ParamOffset += align(primSize(Ty)); - ParamTypes.push_back(Ty); - } - - // Create a handle over the emitted code. - Function *Func = P.createFunction(F, ParamOffset, std::move(ParamTypes), - std::move(ParamDescriptors)); - // Compile the function body. - if (!F->isConstexpr() || !visitFunc(F)) { - // Return a dummy function if compilation failed. - if (BailLocation) - return llvm::make_error<ByteCodeGenError>(*BailLocation); - else - return Func; - } else { - // Create scopes from descriptors. - llvm::SmallVector<Scope, 2> Scopes; - for (auto &DS : Descriptors) { - Scopes.emplace_back(std::move(DS)); - } - - // Set the function's code. - Func->setCode(NextLocalOffset, std::move(Code), std::move(SrcMap), - std::move(Scopes)); - return Func; - } -} - -Scope::Local ByteCodeEmitter::createLocal(Descriptor *D) { - NextLocalOffset += sizeof(Block); - unsigned Location = NextLocalOffset; - NextLocalOffset += align(D->getAllocSize()); - return {Location, D}; -} - -void ByteCodeEmitter::emitLabel(LabelTy Label) { - const size_t Target = Code.size(); - LabelOffsets.insert({Label, Target}); - auto It = LabelRelocs.find(Label); - if (It != LabelRelocs.end()) { - for (unsigned Reloc : It->second) { - using namespace llvm::support; - - /// Rewrite the operand of all jumps to this label. - void *Location = Code.data() + Reloc - sizeof(int32_t); - const int32_t Offset = Target - static_cast<int64_t>(Reloc); - endian::write<int32_t, endianness::native, 1>(Location, Offset); - } - LabelRelocs.erase(It); - } -} - -int32_t ByteCodeEmitter::getOffset(LabelTy Label) { - // Compute the PC offset which the jump is relative to. - const int64_t Position = Code.size() + sizeof(Opcode) + sizeof(int32_t); - - // If target is known, compute jump offset. - auto It = LabelOffsets.find(Label); - if (It != LabelOffsets.end()) { - return It->second - Position; - } - - // Otherwise, record relocation and return dummy offset. - LabelRelocs[Label].push_back(Position); - return 0ull; -} - -bool ByteCodeEmitter::bail(const SourceLocation &Loc) { - if (!BailLocation) - BailLocation = Loc; - return false; -} - -template <typename... Tys> -bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &SI) { - bool Success = true; - - /// Helper to write bytecode and bail out if 32-bit offsets become invalid. - auto emit = [this, &Success](const char *Data, size_t Size) { - if (Code.size() + Size > std::numeric_limits<unsigned>::max()) { - Success = false; - return; - } - Code.insert(Code.end(), Data, Data + Size); - }; - - /// The opcode is followed by arguments. The source info is - /// attached to the address after the opcode. - emit(reinterpret_cast<const char *>(&Op), sizeof(Opcode)); - if (SI) - SrcMap.emplace_back(Code.size(), SI); - - /// The initializer list forces the expression to be evaluated - /// for each argument in the variadic template, in order. - (void)std::initializer_list<int>{ - (emit(reinterpret_cast<const char *>(&Args), sizeof(Args)), 0)...}; - - return Success; -} - -bool ByteCodeEmitter::jumpTrue(const LabelTy &Label) { - return emitJt(getOffset(Label), SourceInfo{}); -} - -bool ByteCodeEmitter::jumpFalse(const LabelTy &Label) { - return emitJf(getOffset(Label), SourceInfo{}); -} - -bool ByteCodeEmitter::jump(const LabelTy &Label) { - return emitJmp(getOffset(Label), SourceInfo{}); -} - -bool ByteCodeEmitter::fallthrough(const LabelTy &Label) { - emitLabel(Label); - return true; -} - -//===----------------------------------------------------------------------===// -// Opcode emitters -//===----------------------------------------------------------------------===// - -#define GET_LINK_IMPL -#include "Opcodes.inc" -#undef GET_LINK_IMPL |