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 "PrimType.h" 15 #include "Program.h" 16 #include "State.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 llvm_unreachable("unknown primitive type"); 254 } 255 256 template <class Emitter> 257 bool ByteCodeExprGen<Emitter>::dereference( 258 const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 259 llvm::function_ref<bool(PrimType)> Indirect) { 260 if (Optional<PrimType> T = classify(LV->getType())) { 261 if (!LV->refersToBitField()) { 262 // Only primitive, non bit-field types can be dereferenced directly. 263 if (auto *DE = dyn_cast<DeclRefExpr>(LV)) { 264 if (!DE->getDecl()->getType()->isReferenceType()) { 265 if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 266 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 267 if (auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 268 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 269 } 270 } 271 } 272 273 if (!visit(LV)) 274 return false; 275 return Indirect(*T); 276 } 277 278 return false; 279 } 280 281 template <class Emitter> 282 bool ByteCodeExprGen<Emitter>::dereferenceParam( 283 const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 284 llvm::function_ref<bool(PrimType)> Direct, 285 llvm::function_ref<bool(PrimType)> Indirect) { 286 auto It = this->Params.find(PD); 287 if (It != this->Params.end()) { 288 unsigned Idx = It->second; 289 switch (AK) { 290 case DerefKind::Read: 291 return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 292 293 case DerefKind::Write: 294 if (!Direct(T)) 295 return false; 296 if (!this->emitSetParam(T, Idx, LV)) 297 return false; 298 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 299 300 case DerefKind::ReadWrite: 301 if (!this->emitGetParam(T, Idx, LV)) 302 return false; 303 if (!Direct(T)) 304 return false; 305 if (!this->emitSetParam(T, Idx, LV)) 306 return false; 307 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 308 } 309 return true; 310 } 311 312 // If the param is a pointer, we can dereference a dummy value. 313 if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 314 if (auto Idx = P.getOrCreateDummy(PD)) 315 return this->emitGetPtrGlobal(*Idx, PD); 316 return false; 317 } 318 319 // Value cannot be produced - try to emit pointer and do stuff with it. 320 return visit(LV) && Indirect(T); 321 } 322 323 template <class Emitter> 324 bool ByteCodeExprGen<Emitter>::dereferenceVar( 325 const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 326 llvm::function_ref<bool(PrimType)> Direct, 327 llvm::function_ref<bool(PrimType)> Indirect) { 328 auto It = Locals.find(VD); 329 if (It != Locals.end()) { 330 const auto &L = It->second; 331 switch (AK) { 332 case DerefKind::Read: 333 if (!this->emitGetLocal(T, L.Offset, LV)) 334 return false; 335 return DiscardResult ? this->emitPop(T, LV) : true; 336 337 case DerefKind::Write: 338 if (!Direct(T)) 339 return false; 340 if (!this->emitSetLocal(T, L.Offset, LV)) 341 return false; 342 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 343 344 case DerefKind::ReadWrite: 345 if (!this->emitGetLocal(T, L.Offset, LV)) 346 return false; 347 if (!Direct(T)) 348 return false; 349 if (!this->emitSetLocal(T, L.Offset, LV)) 350 return false; 351 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 352 } 353 } else if (auto Idx = getGlobalIdx(VD)) { 354 switch (AK) { 355 case DerefKind::Read: 356 if (!this->emitGetGlobal(T, *Idx, LV)) 357 return false; 358 return DiscardResult ? this->emitPop(T, LV) : true; 359 360 case DerefKind::Write: 361 if (!Direct(T)) 362 return false; 363 if (!this->emitSetGlobal(T, *Idx, LV)) 364 return false; 365 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 366 367 case DerefKind::ReadWrite: 368 if (!this->emitGetGlobal(T, *Idx, LV)) 369 return false; 370 if (!Direct(T)) 371 return false; 372 if (!this->emitSetGlobal(T, *Idx, LV)) 373 return false; 374 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 375 } 376 } 377 378 // If the declaration is a constant value, emit it here even 379 // though the declaration was not evaluated in the current scope. 380 // The access mode can only be read in this case. 381 if (!DiscardResult && AK == DerefKind::Read) { 382 if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 383 QualType VT = VD->getType(); 384 if (VT.isConstQualified() && VT->isFundamentalType()) 385 return this->Visit(VD->getInit()); 386 } 387 } 388 389 // Value cannot be produced - try to emit pointer. 390 return visit(LV) && Indirect(T); 391 } 392 393 template <class Emitter> 394 bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits, 395 const APInt &Value, const Expr *E) { 396 switch (T) { 397 case PT_Sint8: 398 return this->emitConstSint8(Value.getSExtValue(), E); 399 case PT_Uint8: 400 return this->emitConstUint8(Value.getZExtValue(), E); 401 case PT_Sint16: 402 return this->emitConstSint16(Value.getSExtValue(), E); 403 case PT_Uint16: 404 return this->emitConstUint16(Value.getZExtValue(), E); 405 case PT_Sint32: 406 return this->emitConstSint32(Value.getSExtValue(), E); 407 case PT_Uint32: 408 return this->emitConstUint32(Value.getZExtValue(), E); 409 case PT_Sint64: 410 return this->emitConstSint64(Value.getSExtValue(), E); 411 case PT_Uint64: 412 return this->emitConstUint64(Value.getZExtValue(), E); 413 case PT_Bool: 414 return this->emitConstBool(Value.getBoolValue(), E); 415 case PT_Ptr: 416 llvm_unreachable("Invalid integral type"); 417 break; 418 } 419 llvm_unreachable("unknown primitive type"); 420 } 421 422 template <class Emitter> 423 unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 424 PrimType Ty, 425 bool IsConst, 426 bool IsExtended) { 427 Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>()); 428 Scope::Local Local = this->createLocal(D); 429 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) 430 Locals.insert({VD, Local}); 431 VarScope->add(Local, IsExtended); 432 return Local.Offset; 433 } 434 435 template <class Emitter> 436 llvm::Optional<unsigned> 437 ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 438 QualType Ty; 439 440 const ValueDecl *Key = nullptr; 441 bool IsTemporary = false; 442 if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) { 443 Key = VD; 444 Ty = VD->getType(); 445 } 446 if (auto *E = Src.dyn_cast<const Expr *>()) { 447 IsTemporary = true; 448 Ty = E->getType(); 449 } 450 451 Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(), 452 Ty.isConstQualified(), IsTemporary); 453 if (!D) 454 return {}; 455 456 Scope::Local Local = this->createLocal(D); 457 if (Key) 458 Locals.insert({Key, Local}); 459 VarScope->add(Local, IsExtended); 460 return Local.Offset; 461 } 462 463 template <class Emitter> 464 bool ByteCodeExprGen<Emitter>::visitInitializer( 465 const Expr *Init, InitFnRef InitFn) { 466 OptionScope<Emitter> Scope(this, InitFn); 467 return this->Visit(Init); 468 } 469 470 template <class Emitter> 471 bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) { 472 // Generate a pointer to the local, loading refs. 473 if (Optional<unsigned> Idx = getGlobalIdx(VD)) { 474 if (VD->getType()->isReferenceType()) 475 return this->emitGetGlobalPtr(*Idx, E); 476 else 477 return this->emitGetPtrGlobal(*Idx, E); 478 } 479 return this->bail(VD); 480 } 481 482 template <class Emitter> 483 llvm::Optional<unsigned> 484 ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) { 485 if (VD->isConstexpr()) { 486 // Constexpr decl - it must have already been defined. 487 return P.getGlobal(VD); 488 } 489 if (!VD->hasLocalStorage()) { 490 // Not constexpr, but a global var - can have pointer taken. 491 Program::DeclScope Scope(P, VD); 492 return P.getOrCreateGlobal(VD); 493 } 494 return {}; 495 } 496 497 template <class Emitter> 498 const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 499 if (auto *PT = dyn_cast<PointerType>(Ty)) 500 return PT->getPointeeType()->getAs<RecordType>(); 501 else 502 return Ty->getAs<RecordType>(); 503 } 504 505 template <class Emitter> 506 Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 507 if (auto *RecordTy = getRecordTy(Ty)) { 508 return getRecord(RecordTy->getDecl()); 509 } 510 return nullptr; 511 } 512 513 template <class Emitter> 514 Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 515 return P.getOrCreateRecord(RD); 516 } 517 518 template <class Emitter> 519 bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) { 520 ExprScope<Emitter> RootScope(this); 521 if (!visit(Exp)) 522 return false; 523 524 if (Optional<PrimType> T = classify(Exp)) 525 return this->emitRet(*T, Exp); 526 else 527 return this->emitRetValue(Exp); 528 } 529 530 template <class Emitter> 531 bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 532 const Expr *Init = VD->getInit(); 533 534 if (Optional<unsigned> I = P.createGlobal(VD)) { 535 if (Optional<PrimType> T = classify(VD->getType())) { 536 { 537 // Primitive declarations - compute the value and set it. 538 DeclScope<Emitter> LocalScope(this, VD); 539 if (!visit(Init)) 540 return false; 541 } 542 543 // If the declaration is global, save the value for later use. 544 if (!this->emitDup(*T, VD)) 545 return false; 546 if (!this->emitInitGlobal(*T, *I, VD)) 547 return false; 548 return this->emitRet(*T, VD); 549 } else { 550 { 551 // Composite declarations - allocate storage and initialize it. 552 DeclScope<Emitter> LocalScope(this, VD); 553 if (!visitGlobalInitializer(Init, *I)) 554 return false; 555 } 556 557 // Return a pointer to the global. 558 if (!this->emitGetPtrGlobal(*I, VD)) 559 return false; 560 return this->emitRetValue(VD); 561 } 562 } 563 564 return this->bail(VD); 565 } 566 567 template <class Emitter> 568 void ByteCodeExprGen<Emitter>::emitCleanup() { 569 for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 570 C->emitDestruction(); 571 } 572 573 namespace clang { 574 namespace interp { 575 576 template class ByteCodeExprGen<ByteCodeEmitter>; 577 template class ByteCodeExprGen<EvalEmitter>; 578 579 } // namespace interp 580 } // namespace clang 581