1*ef202c30SJF Bastien //===--- PatternInit.cpp - Pattern Initialization -------------------------===//
2*ef202c30SJF Bastien //
3*ef202c30SJF Bastien // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ef202c30SJF Bastien // See https://llvm.org/LICENSE.txt for license information.
5*ef202c30SJF Bastien // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ef202c30SJF Bastien //
7*ef202c30SJF Bastien //===----------------------------------------------------------------------===//
8*ef202c30SJF Bastien 
9*ef202c30SJF Bastien #include "PatternInit.h"
10*ef202c30SJF Bastien #include "CodeGenModule.h"
11*ef202c30SJF Bastien #include "llvm/IR/Constant.h"
12*ef202c30SJF Bastien #include "llvm/IR/Type.h"
13*ef202c30SJF Bastien 
14*ef202c30SJF Bastien llvm::Constant *clang::CodeGen::initializationPatternFor(CodeGenModule &CGM,
15*ef202c30SJF Bastien                                                          llvm::Type *Ty) {
16*ef202c30SJF Bastien   // The following value is a guaranteed unmappable pointer value and has a
17*ef202c30SJF Bastien   // repeated byte-pattern which makes it easier to synthesize. We use it for
18*ef202c30SJF Bastien   // pointers as well as integers so that aggregates are likely to be
19*ef202c30SJF Bastien   // initialized with this repeated value.
20*ef202c30SJF Bastien   constexpr uint64_t LargeValue = 0xAAAAAAAAAAAAAAAAull;
21*ef202c30SJF Bastien   // For 32-bit platforms it's a bit trickier because, across systems, only the
22*ef202c30SJF Bastien   // zero page can reasonably be expected to be unmapped, and even then we need
23*ef202c30SJF Bastien   // a very low address. We use a smaller value, and that value sadly doesn't
24*ef202c30SJF Bastien   // have a repeated byte-pattern. We don't use it for integers.
25*ef202c30SJF Bastien   constexpr uint32_t SmallValue = 0x000000AA;
26*ef202c30SJF Bastien   // Floating-point values are initialized as NaNs because they propagate. Using
27*ef202c30SJF Bastien   // a repeated byte pattern means that it will be easier to initialize
28*ef202c30SJF Bastien   // all-floating-point aggregates and arrays with memset. Further, aggregates
29*ef202c30SJF Bastien   // which mix integral and a few floats might also initialize with memset
30*ef202c30SJF Bastien   // followed by a handful of stores for the floats. Using fairly unique NaNs
31*ef202c30SJF Bastien   // also means they'll be easier to distinguish in a crash.
32*ef202c30SJF Bastien   constexpr bool NegativeNaN = true;
33*ef202c30SJF Bastien   constexpr uint64_t NaNPayload = 0xFFFFFFFFFFFFFFFFull;
34*ef202c30SJF Bastien   if (Ty->isIntOrIntVectorTy()) {
35*ef202c30SJF Bastien     unsigned BitWidth = cast<llvm::IntegerType>(
36*ef202c30SJF Bastien                             Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
37*ef202c30SJF Bastien                             ->getBitWidth();
38*ef202c30SJF Bastien     if (BitWidth <= 64)
39*ef202c30SJF Bastien       return llvm::ConstantInt::get(Ty, LargeValue);
40*ef202c30SJF Bastien     return llvm::ConstantInt::get(
41*ef202c30SJF Bastien         Ty, llvm::APInt::getSplat(BitWidth, llvm::APInt(64, LargeValue)));
42*ef202c30SJF Bastien   }
43*ef202c30SJF Bastien   if (Ty->isPtrOrPtrVectorTy()) {
44*ef202c30SJF Bastien     auto *PtrTy = cast<llvm::PointerType>(
45*ef202c30SJF Bastien         Ty->isVectorTy() ? Ty->getVectorElementType() : Ty);
46*ef202c30SJF Bastien     unsigned PtrWidth = CGM.getContext().getTargetInfo().getPointerWidth(
47*ef202c30SJF Bastien         PtrTy->getAddressSpace());
48*ef202c30SJF Bastien     llvm::Type *IntTy = llvm::IntegerType::get(CGM.getLLVMContext(), PtrWidth);
49*ef202c30SJF Bastien     uint64_t IntValue;
50*ef202c30SJF Bastien     switch (PtrWidth) {
51*ef202c30SJF Bastien     default:
52*ef202c30SJF Bastien       llvm_unreachable("pattern initialization of unsupported pointer width");
53*ef202c30SJF Bastien     case 64:
54*ef202c30SJF Bastien       IntValue = LargeValue;
55*ef202c30SJF Bastien       break;
56*ef202c30SJF Bastien     case 32:
57*ef202c30SJF Bastien       IntValue = SmallValue;
58*ef202c30SJF Bastien       break;
59*ef202c30SJF Bastien     }
60*ef202c30SJF Bastien     auto *Int = llvm::ConstantInt::get(IntTy, IntValue);
61*ef202c30SJF Bastien     return llvm::ConstantExpr::getIntToPtr(Int, PtrTy);
62*ef202c30SJF Bastien   }
63*ef202c30SJF Bastien   if (Ty->isFPOrFPVectorTy()) {
64*ef202c30SJF Bastien     unsigned BitWidth = llvm::APFloat::semanticsSizeInBits(
65*ef202c30SJF Bastien         (Ty->isVectorTy() ? Ty->getVectorElementType() : Ty)
66*ef202c30SJF Bastien             ->getFltSemantics());
67*ef202c30SJF Bastien     llvm::APInt Payload(64, NaNPayload);
68*ef202c30SJF Bastien     if (BitWidth >= 64)
69*ef202c30SJF Bastien       Payload = llvm::APInt::getSplat(BitWidth, Payload);
70*ef202c30SJF Bastien     return llvm::ConstantFP::getQNaN(Ty, NegativeNaN, &Payload);
71*ef202c30SJF Bastien   }
72*ef202c30SJF Bastien   if (Ty->isArrayTy()) {
73*ef202c30SJF Bastien     // Note: this doesn't touch tail padding (at the end of an object, before
74*ef202c30SJF Bastien     // the next array object). It is instead handled by replaceUndef.
75*ef202c30SJF Bastien     auto *ArrTy = cast<llvm::ArrayType>(Ty);
76*ef202c30SJF Bastien     llvm::SmallVector<llvm::Constant *, 8> Element(
77*ef202c30SJF Bastien         ArrTy->getNumElements(),
78*ef202c30SJF Bastien         initializationPatternFor(CGM, ArrTy->getElementType()));
79*ef202c30SJF Bastien     return llvm::ConstantArray::get(ArrTy, Element);
80*ef202c30SJF Bastien   }
81*ef202c30SJF Bastien 
82*ef202c30SJF Bastien   // Note: this doesn't touch struct padding. It will initialize as much union
83*ef202c30SJF Bastien   // padding as is required for the largest type in the union. Padding is
84*ef202c30SJF Bastien   // instead handled by replaceUndef. Stores to structs with volatile members
85*ef202c30SJF Bastien   // don't have a volatile qualifier when initialized according to C++. This is
86*ef202c30SJF Bastien   // fine because stack-based volatiles don't really have volatile semantics
87*ef202c30SJF Bastien   // anyways, and the initialization shouldn't be observable.
88*ef202c30SJF Bastien   auto *StructTy = cast<llvm::StructType>(Ty);
89*ef202c30SJF Bastien   llvm::SmallVector<llvm::Constant *, 8> Struct(StructTy->getNumElements());
90*ef202c30SJF Bastien   for (unsigned El = 0; El != Struct.size(); ++El)
91*ef202c30SJF Bastien     Struct[El] = initializationPatternFor(CGM, StructTy->getElementType(El));
92*ef202c30SJF Bastien   return llvm::ConstantStruct::get(StructTy, Struct);
93*ef202c30SJF Bastien }
94