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

24

25

26

28 return nullptr;

29

30 bool IsLambdaStaticInvoker = false;

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

32 MD && MD->isLambdaStaticInvoker()) {

33

34

35

36

37

38 IsLambdaStaticInvoker = true;

39

44 assert(MD->isFunctionTemplateSpecialization() &&

45 "A generic lambda's static-invoker function must be a "

46 "template specialization");

50 void *InsertPos = nullptr;

51 const FunctionDecl *CorrespondingCallOpSpecialization =

53 assert(CorrespondingCallOpSpecialization);

54 FuncDecl = cast(CorrespondingCallOpSpecialization);

55 }

56 }

57

58

62 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;

63

64

65

66

68 bool HasRVO = false;

70 HasRVO = true;

71 ParamTypes.push_back(PT_Ptr);

74 }

75

76

77

78

79 bool HasThisPointer = false;

80 if (const auto *MD = dyn_cast(FuncDecl)) {

81 if (!IsLambdaStaticInvoker) {

82 HasThisPointer = MD->isInstance();

83 if (MD->isImplicitObjectMemberFunction()) {

84 ParamTypes.push_back(PT_Ptr);

87 }

88 }

89

90

92

93

94 if (!MD->getParent()->isCompleteDefinition())

95 return nullptr;

96

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

100

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

102

103 for (auto Cap : LC) {

104

105

106 if (MD->isStatic())

107 return nullptr;

108

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

112 }

113 if (LTC) {

118 }

119 }

120 }

121

122

123

125 std::optional T = Ctx.classify(PD->getType());

128 ParamDescriptors.insert({ParamOffset, {PT, Desc}});

132 ParamTypes.push_back(PT);

133 }

134

135

138 unsigned BuiltinID = FuncDecl->getBuiltinID();

141 std::move(ParamDescriptors), std::move(ParamOffsets),

142 HasThisPointer, HasRVO, BuiltinID);

143 }

144

145 assert(Func);

146

147

150 Func->setDefined(false);

152 }

153

154 Func->setDefined(true);

155

156

157 bool IsEligibleForCompilation = false;

158 if (const auto *MD = dyn_cast(FuncDecl))

159 IsEligibleForCompilation = MD->isLambdaStaticInvoker();

160 if (!IsEligibleForCompilation)

161 IsEligibleForCompilation =

163

164

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

166 Func->setIsFullyCompiled(true);

168 }

169

170

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

174 }

175

176

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

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

179 Func->setIsFullyCompiled(true);

181}

182

183

184

185

186

189

193 llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;

194

195

196

198 std::optional T = Ctx.classify(PD->getType());

201 ParamDescriptors.insert({ParamOffset, {PT, Desc}});

205 ParamTypes.push_back(PT);

206 }

207

209 return nullptr;

210

211

214 std::move(ParamDescriptors), std::move(ParamOffsets),

215 false, false,

216 false);

217

218 assert(Func);

219 Func->setDefined(true);

220

221 Func->setIsFullyCompiled(true);

223}

224

226 NextLocalOffset += sizeof(Block);

227 unsigned Location = NextLocalOffset;

228 NextLocalOffset += align(D->getAllocSize());

229 return {Location, D};

230}

231

233 const size_t Target = Code.size();

235

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

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

238 using namespace llvm::support;

239

240

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

242 assert(aligned(Location));

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

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

245 }

246 LabelRelocs.erase(It);

247 }

248}

249

250int32_t ByteCodeEmitter::getOffset(LabelTy Label) {

251

252 const int64_t Position =

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

254 assert(aligned(Position));

255

256

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

258 return It->second - Position;

259

260

261 LabelRelocs[Label].push_back(Position);

262 return 0ull;

263}

264

265

266

267template

268static void emit(Program &P, std::vectorstd::byte &Code, const T &Val,

270 size_t Size;

271

272 if constexpr (std::is_pointer_v)

273 Size = sizeof(uint32_t);

274 else

275 Size = sizeof(T);

276

277 if (Code.size() + Size > std::numeric_limits::max()) {

279 return;

280 }

281

282

283 size_t ValPos = align(Code.size());

284 Size = align(Size);

285 assert(aligned(ValPos + Size));

286 Code.resize(ValPos + Size);

287

288 if constexpr (!std::is_pointer_v) {

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

290 } else {

291 uint32_t ID = P.getOrCreateNativePointer(Val);

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

293 }

294}

295

296

297

298template

299static void emitSerialized(std::vectorstd::byte &Code, const T &Val,

301 size_t Size = Val.bytesToSerialize();

302

303 if (Code.size() + Size > std::numeric_limits::max()) {

305 return;

306 }

307

308

309 size_t ValPos = align(Code.size());

310 Size = align(Size);

311 assert(aligned(ValPos + Size));

312 Code.resize(ValPos + Size);

313

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

315}

316

317template <>

321}

322

323template <>

327}

328

329template <>

333}

334

335template <>

339}

340

341template <typename... Tys>

342bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &...Args,

345

346

347

349 if (SI)

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

351

354}

355

358}

359

362}

363

366}

367

370 return true;

371}

372

373

374

375

376

377#define GET_LINK_IMPL

378#include "Opcodes.inc"

379#undef GET_LINK_IMPL

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

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

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

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

Emits a serializable value.

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

llvm::MachO::Target Target

Represents a block literal declaration, which is like an unnamed FunctionDecl.

bool hasCaptures() const

True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...

ArrayRef< ParmVarDecl * > parameters() const

BlockExpr - Adaptor class for mixing a BlockDecl with expressions.

const BlockDecl * getBlockDecl() const

Represents a static or instance method of a struct/union/class.

Represents a C++ struct/union/class.

bool isGenericLambda() const

Determine whether this class describes a generic lambda function object (i.e.

capture_const_iterator captures_end() const

capture_const_iterator captures_begin() const

CXXMethodDecl * getLambdaCallOperator() const

Retrieve the lambda call operator of the closure type if this is a closure type.

DeclContext * getParent()

getParent - Returns the containing DeclContext.

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.

FunctionTemplateDecl * getDescribedFunctionTemplate() const

Retrieves the function template that is described by this function declaration.

unsigned getBuiltinID(bool ConsiderWrapperFunctions=false) const

Returns a value indicating whether this function corresponds to a builtin function.

QualType getReturnType() const

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.

bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const

Returns true if the function has a definition that does not need to be instantiated.

bool willHaveBody() const

True if this function will eventually have a body, once it's fully parsed.

Declaration of a template function.

FunctionDecl * findSpecialization(ArrayRef< TemplateArgument > Args, void *&InsertPos)

Return the specialization with the provided arguments if it exists, otherwise return the insertion po...

Represents a parameter to a function.

A (possibly-)qualified type.

A template argument list.

ArrayRef< TemplateArgument > asArray() const

Produce this as an array ref.

bool isPointerType() const

bool isReferenceType() const

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

bool jump(const LabelTy &Label)

void emitLabel(LabelTy Label)

Define a label.

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 fallthrough(const LabelTy &Label)

Local createLocal(Descriptor *D)

Callback for local registration.

Function * compileFunc(const FunctionDecl *FuncDecl)

Compiles the function into the module.

Function * compileObjCBlock(const BlockExpr *BE)

Compile an ObjC block, i.e.

virtual bool visitFunc(const FunctionDecl *E)=0

Methods implemented by the compiler.

bool jumpTrue(const LabelTy &Label)

Emits jumps.

bool jumpFalse(const LabelTy &Label)

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

Local descriptors.

std::optional< PrimType > classify(QualType T) const

Classifies a type.

Wrapper around fixed point types.

The program contains and links the bytecode for all functions.

Function * getFunction(const FunctionDecl *F)

Returns a function.

Descriptor * createDescriptor(const DeclTy &D, PrimType Type, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false)

Creates a descriptor for a primitive type.

Function * createFunction(const FunctionDecl *Def, Ts &&...Args)

Creates a new function from a code range.

Record * getOrCreateRecord(const RecordDecl *RD)

Returns a record or creates one if it does not exist.

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.

size_t primSize(PrimType Type)

Returns the size of a primitive type in bytes.

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

bool isLambdaCallOperator(const CXXMethodDecl *MD)

const FunctionProtoType * T

@ Success

Template argument deduction was successful.

Describes a memory block created by an allocation site.

Information about a local's storage.