clang: lib/AST/ByteCode/ByteCodeEmitter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

18#include <type_traits>

19

20using namespace clang;

22

25 assert(FuncDecl);

28

29

30

32 return;

33

34

35 if (const auto *MD = dyn_cast(FuncDecl);

37

38 const Record *R = P.getOrCreateRecord(MD->getParent());

39 assert(R);

40 llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;

42

43 MD->getParent()->getCaptureFields(LC, LTC);

44

45 for (auto Cap : LC) {

48 Offset, Cap.second->getType()->isReferenceType()};

49 }

50 if (LTC) {

54 }

55 }

56

57

58 unsigned ParamIndex = 0;

59 unsigned Drop = Func->hasRVO() +

60 (Func->hasThisPointer() && Func->isThisPointerExplicit());

61 for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) {

65 ++ParamIndex;

66 }

67

68 Func->setDefined(true);

69

70

71 bool IsEligibleForCompilation = Func->isLambdaStaticInvoker() ||

73 FuncDecl->hasAttr();

74

75

76 if (!IsEligibleForCompilation || visitFunc(FuncDecl)) {

77 Func->setIsFullyCompiled(true);

78 return;

79 }

80

81

84 Scopes.emplace_back(std::move(DS));

85 }

86

87

88 Func->setCode(FuncDecl, NextLocalOffset, std::move(Code), std::move(SrcMap),

89 std::move(Scopes), FuncDecl->hasBody());

90 Func->setIsFullyCompiled(true);

91}

92

94 NextLocalOffset += sizeof(Block);

95 unsigned Location = NextLocalOffset;

97 return {Location, D};

98}

99

101 const size_t Target = Code.size();

102 LabelOffsets.insert({Label, Target});

103

104 if (auto It = LabelRelocs.find(Label); It != LabelRelocs.end()) {

105 for (unsigned Reloc : It->second) {

106 using namespace llvm::support;

107

108

109 void *Location = Code.data() + Reloc - align(sizeof(int32_t));

110 assert(aligned(Location));

111 const int32_t Offset = Target - static_cast<int64_t>(Reloc);

112 endian::write<int32_t, llvm::endianness::native>(Location, Offset);

113 }

114 LabelRelocs.erase(It);

115 }

116}

117

118int32_t ByteCodeEmitter::getOffset(LabelTy Label) {

119

120 const int64_t Position =

121 Code.size() + align(sizeof(Opcode)) + align(sizeof(int32_t));

122 assert(aligned(Position));

123

124

125 if (auto It = LabelOffsets.find(Label); It != LabelOffsets.end())

126 return It->second - Position;

127

128

129 LabelRelocs[Label].push_back(Position);

130 return 0ull;

131}

132

133

134

135template

137 const T &Val, bool &Success) {

138 size_t ValPos = Code.size();

139 size_t Size;

140

141 if constexpr (std::is_pointer_v)

142 Size = align(sizeof(uint32_t));

143 else

144 Size = align(sizeof(T));

145

146 if (ValPos + Size > std::numeric_limits::max()) {

148 return;

149 }

150

151

153 assert(aligned(ValPos + Size));

154 Code.resize_for_overwrite(ValPos + Size);

155

156 if constexpr (!std::is_pointer_v) {

157 new (Code.data() + ValPos) T(Val);

158 } else {

160 new (Code.data() + ValPos) uint32_t(ID);

161 }

162}

163

164

165

166template

169 size_t ValPos = Code.size();

170 size_t Size = align(Val.bytesToSerialize());

171

172 if (ValPos + Size > std::numeric_limits::max()) {

174 return;

175 }

176

177

179 assert(aligned(ValPos + Size));

180 Code.resize_for_overwrite(ValPos + Size);

181

182 Val.serialize(Code.data() + ValPos);

183}

184

185template <>

190

191template <>

196

197template <>

202

203template <>

208

209template <typename... Tys>

210bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args, SourceInfo SI) {

212

213

214

217 SrcMap.emplace_back(Code.size(), *LocOverride);

218 else if (SI)

219 SrcMap.emplace_back(Code.size(), SI);

220

223}

224

226 return emitJt(getOffset(Label), SourceInfo{});

227}

228

230 return emitJf(getOffset(Label), SourceInfo{});

231}

232

234 return emitJmp(getOffset(Label), SourceInfo{});

235}

236

241

245 if (!this->emitBCP(getOffset(EndLabel), T, E))

246 return false;

247 if (!this->visit(Arg))

248 return false;

249 return true;

250}

251

252

253

254

255

256#define GET_LINK_IMPL

257#include "Opcodes.inc"

258#undef GET_LINK_IMPL

This file provides some common utility functions for processing Lambda related AST Constructs.

static void emitSerialized(llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)

Emits a serializable value.

Definition ByteCodeEmitter.cpp:167

static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)

Helper to write bytecode and bail out if 32-bit offsets become invalid.

Definition ByteCodeEmitter.cpp:136

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

This represents one expression.

Represents a member of a struct/union/class.

const RecordDecl * getParent() const

Returns the parent of this field declaration, which is the struct in which this field is defined.

Represents a function declaration or definition.

bool isThisDeclarationADefinition() const

Returns whether this specific declaration of the function is also a definition that does not contain ...

ArrayRef< ParmVarDecl * > parameters() const

param_iterator param_begin()

bool isConstexpr() const

Whether this is a (C++11) constexpr function or constexpr constructor.

bool hasBody(const FunctionDecl *&Definition) const

Returns true if the function has a body.

Represents a parameter to a function.

A (possibly-)qualified type.

bool isPointerOrReferenceType() const

A memory block, either on the stack or in the heap.

bool jump(const LabelTy &Label)

Definition ByteCodeEmitter.cpp:233

void emitLabel(LabelTy Label)

Define a label.

Definition ByteCodeEmitter.cpp:100

ParamOffset LambdaThisCapture

Offset of the This parameter in a lambda record.

llvm::DenseMap< const ParmVarDecl *, ParamOffset > Params

Parameter indices.

llvm::DenseMap< const ValueDecl *, ParamOffset > LambdaCaptures

Lambda captures.

bool speculate(const CallExpr *E, const LabelTy &EndLabel)

Speculative execution.

Definition ByteCodeEmitter.cpp:242

void compileFunc(const FunctionDecl *FuncDecl, Function *Func=nullptr)

Compiles the function into the module.

Definition ByteCodeEmitter.cpp:23

bool fallthrough(const LabelTy &Label)

Definition ByteCodeEmitter.cpp:237

Local createLocal(Descriptor *D)

Callback for local registration.

Definition ByteCodeEmitter.cpp:93

virtual bool visitFunc(const FunctionDecl *E)=0

Methods implemented by the compiler.

bool jumpTrue(const LabelTy &Label)

Emits jumps.

Definition ByteCodeEmitter.cpp:225

std::optional< SourceInfo > LocOverride

bool jumpFalse(const LabelTy &Label)

Definition ByteCodeEmitter.cpp:229

virtual bool visit(const Expr *E)=0

llvm::SmallVector< SmallVector< Local, 8 >, 2 > Descriptors

Local descriptors.

Wrapper around fixed point types.

If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.

If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.

The program contains and links the bytecode for all functions.

unsigned getOrCreateNativePointer(const void *Ptr)

Marshals a native pointer to an ID for embedding in bytecode.

Structure/Class descriptor.

const Field * getField(const FieldDecl *FD) const

Returns a field.

Describes the statement/declaration an opcode was generated from.

constexpr bool aligned(uintptr_t Value)

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

PrimType

Enumeration of the primitive types of the VM.

The JSON file list parser is used to communicate input to InstallAPI.

@ Success

Annotation was successful.

bool isLambdaCallOperator(const CXXMethodDecl *MD)

const FunctionProtoType * T

Describes a memory block created by an allocation site.

unsigned getAllocSize() const

Returns the allocated size, including metadata.

Information about a local's storage.