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