1 //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- 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 "ByteCodeExprGen.h" 10 #include "ByteCodeEmitter.h" 11 #include "ByteCodeGenError.h" 12 #include "Context.h" 13 #include "Function.h" 14 #include "Program.h" 15 #include "State.h" 16 #include "Type.h" 17 18 using namespace clang; 19 using namespace clang::interp; 20 21 using APSInt = llvm::APSInt; 22 template <typename T> using Expected = llvm::Expected<T>; 23 template <typename T> using Optional = llvm::Optional<T>; 24 25 namespace clang { 26 namespace interp { 27 28 /// Scope used to handle temporaries in toplevel variable declarations. 29 template <class Emitter> class DeclScope final : public LocalScope<Emitter> { 30 public: 31 DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD) 32 : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} 33 34 void addExtended(const Scope::Local &Local) override { 35 return this->addLocal(Local); 36 } 37 38 private: 39 Program::DeclScope Scope; 40 }; 41 42 /// Scope used to handle initialization methods. 43 template <class Emitter> class OptionScope { 44 public: 45 using InitFnRef = typename ByteCodeExprGen<Emitter>::InitFnRef; 46 using ChainedInitFnRef = std::function<bool(InitFnRef)>; 47 48 /// Root constructor, compiling or discarding primitives. 49 OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult) 50 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 51 OldInitFn(std::move(Ctx->InitFn)) { 52 Ctx->DiscardResult = NewDiscardResult; 53 Ctx->InitFn = llvm::Optional<InitFnRef>{}; 54 } 55 56 /// Root constructor, setting up compilation state. 57 OptionScope(ByteCodeExprGen<Emitter> *Ctx, InitFnRef NewInitFn) 58 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 59 OldInitFn(std::move(Ctx->InitFn)) { 60 Ctx->DiscardResult = true; 61 Ctx->InitFn = NewInitFn; 62 } 63 64 /// Extends the chain of initialisation pointers. 65 OptionScope(ByteCodeExprGen<Emitter> *Ctx, ChainedInitFnRef NewInitFn) 66 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 67 OldInitFn(std::move(Ctx->InitFn)) { 68 assert(OldInitFn && "missing initializer"); 69 Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); }; 70 } 71 72 ~OptionScope() { 73 Ctx->DiscardResult = OldDiscardResult; 74 Ctx->InitFn = std::move(OldInitFn); 75 } 76 77 private: 78 /// Parent context. 79 ByteCodeExprGen<Emitter> *Ctx; 80 /// Old discard flag to restore. 81 bool OldDiscardResult; 82 /// Old pointer emitter to restore. 83 llvm::Optional<InitFnRef> OldInitFn; 84 }; 85 86 } // namespace interp 87 } // namespace clang 88 89 template <class Emitter> 90 bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { 91 auto *SubExpr = CE->getSubExpr(); 92 switch (CE->getCastKind()) { 93 94 case CK_LValueToRValue: { 95 return dereference( 96 CE->getSubExpr(), DerefKind::Read, 97 [](PrimType) { 98 // Value loaded - nothing to do here. 99 return true; 100 }, 101 [this, CE](PrimType T) { 102 // Pointer on stack - dereference it. 103 if (!this->emitLoadPop(T, CE)) 104 return false; 105 return DiscardResult ? this->emitPop(T, CE) : true; 106 }); 107 } 108 109 case CK_ArrayToPointerDecay: 110 case CK_AtomicToNonAtomic: 111 case CK_ConstructorConversion: 112 case CK_FunctionToPointerDecay: 113 case CK_NonAtomicToAtomic: 114 case CK_NoOp: 115 case CK_UserDefinedConversion: 116 return this->Visit(SubExpr); 117 118 case CK_ToVoid: 119 return discard(SubExpr); 120 121 default: { 122 // TODO: implement other casts. 123 return this->bail(CE); 124 } 125 } 126 } 127 128 template <class Emitter> 129 bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { 130 if (DiscardResult) 131 return true; 132 133 auto Val = LE->getValue(); 134 QualType LitTy = LE->getType(); 135 if (Optional<PrimType> T = classify(LitTy)) 136 return emitConst(*T, getIntWidth(LitTy), LE->getValue(), LE); 137 return this->bail(LE); 138 } 139 140 template <class Emitter> 141 bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) { 142 return this->Visit(PE->getSubExpr()); 143 } 144 145 template <class Emitter> 146 bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { 147 const Expr *LHS = BO->getLHS(); 148 const Expr *RHS = BO->getRHS(); 149 150 // Deal with operations which have composite or void types. 151 switch (BO->getOpcode()) { 152 case BO_Comma: 153 if (!discard(LHS)) 154 return false; 155 if (!this->Visit(RHS)) 156 return false; 157 return true; 158 default: 159 break; 160 } 161 162 // Typecheck the args. 163 Optional<PrimType> LT = classify(LHS->getType()); 164 Optional<PrimType> RT = classify(RHS->getType()); 165 if (!LT || !RT) { 166 return this->bail(BO); 167 } 168 169 if (Optional<PrimType> T = classify(BO->getType())) { 170 if (!visit(LHS)) 171 return false; 172 if (!visit(RHS)) 173 return false; 174 175 auto Discard = [this, T, BO](bool Result) { 176 if (!Result) 177 return false; 178 return DiscardResult ? this->emitPop(*T, BO) : true; 179 }; 180 181 switch (BO->getOpcode()) { 182 case BO_EQ: 183 return Discard(this->emitEQ(*LT, BO)); 184 case BO_NE: 185 return Discard(this->emitNE(*LT, BO)); 186 case BO_LT: 187 return Discard(this->emitLT(*LT, BO)); 188 case BO_LE: 189 return Discard(this->emitLE(*LT, BO)); 190 case BO_GT: 191 return Discard(this->emitGT(*LT, BO)); 192 case BO_GE: 193 return Discard(this->emitGE(*LT, BO)); 194 case BO_Sub: 195 return Discard(this->emitSub(*T, BO)); 196 case BO_Add: 197 return Discard(this->emitAdd(*T, BO)); 198 case BO_Mul: 199 return Discard(this->emitMul(*T, BO)); 200 default: 201 return this->bail(BO); 202 } 203 } 204 205 return this->bail(BO); 206 } 207 208 template <class Emitter> 209 bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { 210 OptionScope<Emitter> Scope(this, /*discardResult=*/true); 211 return this->Visit(E); 212 } 213 214 template <class Emitter> 215 bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { 216 OptionScope<Emitter> Scope(this, /*discardResult=*/false); 217 return this->Visit(E); 218 } 219 220 template <class Emitter> 221 bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { 222 if (Optional<PrimType> T = classify(E->getType())) { 223 return visit(E); 224 } else { 225 return this->bail(E); 226 } 227 } 228 229 template <class Emitter> 230 bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) { 231 switch (T) { 232 case PT_Bool: 233 return this->emitZeroBool(E); 234 case PT_Sint8: 235 return this->emitZeroSint8(E); 236 case PT_Uint8: 237 return this->emitZeroUint8(E); 238 case PT_Sint16: 239 return this->emitZeroSint16(E); 240 case PT_Uint16: 241 return this->emitZeroUint16(E); 242 case PT_Sint32: 243 return this->emitZeroSint32(E); 244 case PT_Uint32: 245 return this->emitZeroUint32(E); 246 case PT_Sint64: 247 return this->emitZeroSint64(E); 248 case PT_Uint64: 249 return this->emitZeroUint64(E); 250 case PT_Ptr: 251 return this->emitNullPtr(E); 252 } 253 } 254 255 template <class Emitter> 256 bool ByteCodeExprGen<Emitter>::dereference( 257 const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 258 llvm::function_ref<bool(PrimType)> Indirect) { 259 if (Optional<PrimType> T = classify(LV->getType())) { 260 if (!LV->refersToBitField()) { 261 // Only primitive, non bit-field types can be dereferenced directly. 262 if (auto *DE = dyn_cast<DeclRefExpr>(LV)) { 263 if (!DE->getDecl()->getType()->isReferenceType()) { 264 if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 265 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 266 if (auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 267 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 268 } 269 } 270 } 271 272 if (!visit(LV)) 273 return false; 274 return Indirect(*T); 275 } 276 277 return false; 278 } 279 280 template <class Emitter> 281 bool ByteCodeExprGen<Emitter>::dereferenceParam( 282 const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 283 llvm::function_ref<bool(PrimType)> Direct, 284 llvm::function_ref<bool(PrimType)> Indirect) { 285 auto It = this->Params.find(PD); 286 if (It != this->Params.end()) { 287 unsigned Idx = It->second; 288 switch (AK) { 289 case DerefKind::Read: 290 return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 291 292 case DerefKind::Write: 293 if (!Direct(T)) 294 return false; 295 if (!this->emitSetParam(T, Idx, LV)) 296 return false; 297 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 298 299 case DerefKind::ReadWrite: 300 if (!this->emitGetParam(T, Idx, LV)) 301 return false; 302 if (!Direct(T)) 303 return false; 304 if (!this->emitSetParam(T, Idx, LV)) 305 return false; 306 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 307 } 308 return true; 309 } 310 311 // If the param is a pointer, we can dereference a dummy value. 312 if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 313 if (auto Idx = P.getOrCreateDummy(PD)) 314 return this->emitGetPtrGlobal(*Idx, PD); 315 return false; 316 } 317 318 // Value cannot be produced - try to emit pointer and do stuff with it. 319 return visit(LV) && Indirect(T); 320 } 321 322 template <class Emitter> 323 bool ByteCodeExprGen<Emitter>::dereferenceVar( 324 const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 325 llvm::function_ref<bool(PrimType)> Direct, 326 llvm::function_ref<bool(PrimType)> Indirect) { 327 auto It = Locals.find(VD); 328 if (It != Locals.end()) { 329 const auto &L = It->second; 330 switch (AK) { 331 case DerefKind::Read: 332 if (!this->emitGetLocal(T, L.Offset, LV)) 333 return false; 334 return DiscardResult ? this->emitPop(T, LV) : true; 335 336 case DerefKind::Write: 337 if (!Direct(T)) 338 return false; 339 if (!this->emitSetLocal(T, L.Offset, LV)) 340 return false; 341 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 342 343 case DerefKind::ReadWrite: 344 if (!this->emitGetLocal(T, L.Offset, LV)) 345 return false; 346 if (!Direct(T)) 347 return false; 348 if (!this->emitSetLocal(T, L.Offset, LV)) 349 return false; 350 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 351 } 352 } else if (auto Idx = getGlobalIdx(VD)) { 353 switch (AK) { 354 case DerefKind::Read: 355 if (!this->emitGetGlobal(T, *Idx, LV)) 356 return false; 357 return DiscardResult ? this->emitPop(T, LV) : true; 358 359 case DerefKind::Write: 360 if (!Direct(T)) 361 return false; 362 if (!this->emitSetGlobal(T, *Idx, LV)) 363 return false; 364 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 365 366 case DerefKind::ReadWrite: 367 if (!this->emitGetGlobal(T, *Idx, LV)) 368 return false; 369 if (!Direct(T)) 370 return false; 371 if (!this->emitSetGlobal(T, *Idx, LV)) 372 return false; 373 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 374 } 375 } 376 377 // If the declaration is a constant value, emit it here even 378 // though the declaration was not evaluated in the current scope. 379 // The access mode can only be read in this case. 380 if (!DiscardResult && AK == DerefKind::Read) { 381 if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 382 QualType VT = VD->getType(); 383 if (VT.isConstQualified() && VT->isFundamentalType()) 384 return this->Visit(VD->getInit()); 385 } 386 } 387 388 // Value cannot be produced - try to emit pointer. 389 return visit(LV) && Indirect(T); 390 } 391 392 template <class Emitter> 393 bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits, 394 const APInt &Value, const Expr *E) { 395 switch (T) { 396 case PT_Sint8: 397 return this->emitConstSint8(Value.getSExtValue(), E); 398 case PT_Uint8: 399 return this->emitConstUint8(Value.getZExtValue(), E); 400 case PT_Sint16: 401 return this->emitConstSint16(Value.getSExtValue(), E); 402 case PT_Uint16: 403 return this->emitConstUint16(Value.getZExtValue(), E); 404 case PT_Sint32: 405 return this->emitConstSint32(Value.getSExtValue(), E); 406 case PT_Uint32: 407 return this->emitConstUint32(Value.getZExtValue(), E); 408 case PT_Sint64: 409 return this->emitConstSint64(Value.getSExtValue(), E); 410 case PT_Uint64: 411 return this->emitConstUint64(Value.getZExtValue(), E); 412 case PT_Bool: 413 return this->emitConstBool(Value.getBoolValue(), E); 414 case PT_Ptr: 415 llvm_unreachable("Invalid integral type"); 416 break; 417 } 418 } 419 420 template <class Emitter> 421 unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 422 PrimType Ty, 423 bool IsConst, 424 bool IsExtended) { 425 Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>()); 426 Scope::Local Local = this->createLocal(D); 427 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) 428 Locals.insert({VD, Local}); 429 VarScope->add(Local, IsExtended); 430 return Local.Offset; 431 } 432 433 template <class Emitter> 434 llvm::Optional<unsigned> 435 ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 436 QualType Ty; 437 438 const ValueDecl *Key = nullptr; 439 bool IsTemporary = false; 440 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) { 441 Key = VD; 442 Ty = VD->getType(); 443 } 444 if (auto *E = Src.dyn_cast<const Expr *>()) { 445 IsTemporary = true; 446 Ty = E->getType(); 447 } 448 449 Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(), 450 Ty.isConstQualified(), IsTemporary); 451 if (!D) 452 return {}; 453 454 Scope::Local Local = this->createLocal(D); 455 if (Key) 456 Locals.insert({Key, Local}); 457 VarScope->add(Local, IsExtended); 458 return Local.Offset; 459 } 460 461 template <class Emitter> 462 bool ByteCodeExprGen<Emitter>::visitInitializer( 463 const Expr *Init, InitFnRef InitFn) { 464 OptionScope<Emitter> Scope(this, InitFn); 465 return this->Visit(Init); 466 } 467 468 template <class Emitter> 469 bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) { 470 // Generate a pointer to the local, loading refs. 471 if (Optional<unsigned> Idx = getGlobalIdx(VD)) { 472 if (VD->getType()->isReferenceType()) 473 return this->emitGetGlobalPtr(*Idx, E); 474 else 475 return this->emitGetPtrGlobal(*Idx, E); 476 } 477 return this->bail(VD); 478 } 479 480 template <class Emitter> 481 llvm::Optional<unsigned> 482 ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) { 483 if (VD->isConstexpr()) { 484 // Constexpr decl - it must have already been defined. 485 return P.getGlobal(VD); 486 } 487 if (!VD->hasLocalStorage()) { 488 // Not constexpr, but a global var - can have pointer taken. 489 Program::DeclScope Scope(P, VD); 490 return P.getOrCreateGlobal(VD); 491 } 492 return {}; 493 } 494 495 template <class Emitter> 496 const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 497 if (auto *PT = dyn_cast<PointerType>(Ty)) 498 return PT->getPointeeType()->getAs<RecordType>(); 499 else 500 return Ty->getAs<RecordType>(); 501 } 502 503 template <class Emitter> 504 Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 505 if (auto *RecordTy = getRecordTy(Ty)) { 506 return getRecord(RecordTy->getDecl()); 507 } 508 return nullptr; 509 } 510 511 template <class Emitter> 512 Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 513 return P.getOrCreateRecord(RD); 514 } 515 516 template <class Emitter> 517 bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) { 518 ExprScope<Emitter> RootScope(this); 519 if (!visit(Exp)) 520 return false; 521 522 if (Optional<PrimType> T = classify(Exp)) 523 return this->emitRet(*T, Exp); 524 else 525 return this->emitRetValue(Exp); 526 } 527 528 template <class Emitter> 529 bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 530 const Expr *Init = VD->getInit(); 531 532 if (Optional<unsigned> I = P.createGlobal(VD)) { 533 if (Optional<PrimType> T = classify(VD->getType())) { 534 { 535 // Primitive declarations - compute the value and set it. 536 DeclScope<Emitter> LocalScope(this, VD); 537 if (!visit(Init)) 538 return false; 539 } 540 541 // If the declaration is global, save the value for later use. 542 if (!this->emitDup(*T, VD)) 543 return false; 544 if (!this->emitInitGlobal(*T, *I, VD)) 545 return false; 546 return this->emitRet(*T, VD); 547 } else { 548 { 549 // Composite declarations - allocate storage and initialize it. 550 DeclScope<Emitter> LocalScope(this, VD); 551 if (!visitGlobalInitializer(Init, *I)) 552 return false; 553 } 554 555 // Return a pointer to the global. 556 if (!this->emitGetPtrGlobal(*I, VD)) 557 return false; 558 return this->emitRetValue(VD); 559 } 560 } 561 562 return this->bail(VD); 563 } 564 565 template <class Emitter> 566 void ByteCodeExprGen<Emitter>::emitCleanup() { 567 for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 568 C->emitDestruction(); 569 } 570 571 namespace clang { 572 namespace interp { 573 574 template class ByteCodeExprGen<ByteCodeEmitter>; 575 template class ByteCodeExprGen<EvalEmitter>; 576 577 } // namespace interp 578 } // namespace clang 579