diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp | 273 | 
1 files changed, 187 insertions, 86 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index e5e34a5f3ed6..265ef27a46b0 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -71,7 +71,8 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,  /// block.  llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,                                                      const Twine &Name) { -  return new llvm::AllocaInst(Ty, nullptr, Name, AllocaInsertPt); +  return new llvm::AllocaInst(Ty, CGM.getDataLayout().getAllocaAddrSpace(), +                              nullptr, Name, AllocaInsertPt);  }  /// CreateDefaultAlignTempAlloca - This creates an alloca with the @@ -534,7 +535,8 @@ bool CodeGenFunction::sanitizePerformTypeCheck() const {  void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,                                      llvm::Value *Ptr, QualType Ty, -                                    CharUnits Alignment, bool SkipNullCheck) { +                                    CharUnits Alignment, +                                    SanitizerSet SkippedChecks) {    if (!sanitizePerformTypeCheck())      return; @@ -552,7 +554,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,    bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||                             TCK == TCK_UpcastToVirtualBase;    if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) && -      !SkipNullCheck) { +      !SkippedChecks.has(SanitizerKind::Null)) {      // The glvalue must not be an empty glvalue.      llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr); @@ -568,7 +570,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,      }    } -  if (SanOpts.has(SanitizerKind::ObjectSize) && !Ty->isIncompleteType()) { +  if (SanOpts.has(SanitizerKind::ObjectSize) && +      !SkippedChecks.has(SanitizerKind::ObjectSize) && +      !Ty->isIncompleteType()) {      uint64_t Size = getContext().getTypeSizeInChars(Ty).getQuantity();      // The glvalue must refer to a large enough storage region. @@ -578,22 +582,24 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,      llvm::Type *Tys[2] = { IntPtrTy, Int8PtrTy };      llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, Tys);      llvm::Value *Min = Builder.getFalse(); +    llvm::Value *NullIsUnknown = Builder.getFalse();      llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy); -    llvm::Value *LargeEnough = -        Builder.CreateICmpUGE(Builder.CreateCall(F, {CastAddr, Min}), -                              llvm::ConstantInt::get(IntPtrTy, Size)); +    llvm::Value *LargeEnough = Builder.CreateICmpUGE( +        Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown}), +        llvm::ConstantInt::get(IntPtrTy, Size));      Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));    }    uint64_t AlignVal = 0; -  if (SanOpts.has(SanitizerKind::Alignment)) { +  if (SanOpts.has(SanitizerKind::Alignment) && +      !SkippedChecks.has(SanitizerKind::Alignment)) {      AlignVal = Alignment.getQuantity();      if (!Ty->isIncompleteType() && !AlignVal)        AlignVal = getContext().getTypeAlignInChars(Ty).getQuantity();      // The glvalue must be suitably aligned. -    if (AlignVal) { +    if (AlignVal > 1) {        llvm::Value *Align =            Builder.CreateAnd(Builder.CreatePtrToInt(Ptr, IntPtrTy),                              llvm::ConstantInt::get(IntPtrTy, AlignVal - 1)); @@ -624,6 +630,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,    //       or call a non-static member function    CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();    if (SanOpts.has(SanitizerKind::Vptr) && +      !SkippedChecks.has(SanitizerKind::Vptr) &&        (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||         TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference ||         TCK == TCK_UpcastToVirtualBase) && @@ -947,15 +954,47 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,                          E->getType());  } +bool CodeGenFunction::IsWrappedCXXThis(const Expr *Obj) { +  const Expr *Base = Obj; +  while (!isa<CXXThisExpr>(Base)) { +    // The result of a dynamic_cast can be null. +    if (isa<CXXDynamicCastExpr>(Base)) +      return false; + +    if (const auto *CE = dyn_cast<CastExpr>(Base)) { +      Base = CE->getSubExpr(); +    } else if (const auto *PE = dyn_cast<ParenExpr>(Base)) { +      Base = PE->getSubExpr(); +    } else if (const auto *UO = dyn_cast<UnaryOperator>(Base)) { +      if (UO->getOpcode() == UO_Extension) +        Base = UO->getSubExpr(); +      else +        return false; +    } else { +      return false; +    } +  } +  return true; +} +  LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {    LValue LV;    if (SanOpts.has(SanitizerKind::ArrayBounds) && isa<ArraySubscriptExpr>(E))      LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/true);    else      LV = EmitLValue(E); -  if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) +  if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) { +    SanitizerSet SkippedChecks; +    if (const auto *ME = dyn_cast<MemberExpr>(E)) { +      bool IsBaseCXXThis = IsWrappedCXXThis(ME->getBase()); +      if (IsBaseCXXThis) +        SkippedChecks.set(SanitizerKind::Alignment, true); +      if (IsBaseCXXThis || isa<DeclRefExpr>(ME->getBase())) +        SkippedChecks.set(SanitizerKind::Null, true); +    }      EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(), -                  E->getType(), LV.getAlignment()); +                  E->getType(), LV.getAlignment(), SkippedChecks); +  }    return LV;  } @@ -1033,7 +1072,19 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {      const auto *cleanups = cast<ExprWithCleanups>(E);      enterFullExpression(cleanups);      RunCleanupsScope Scope(*this); -    return EmitLValue(cleanups->getSubExpr()); +    LValue LV = EmitLValue(cleanups->getSubExpr()); +    if (LV.isSimple()) { +      // Defend against branches out of gnu statement expressions surrounded by +      // cleanups. +      llvm::Value *V = LV.getPointer(); +      Scope.ForceCleanup({&V}); +      return LValue::MakeAddr(Address(V, LV.getAlignment()), LV.getType(), +                              getContext(), LV.getAlignmentSource(), +                              LV.getTBAAInfo()); +    } +    // FIXME: Is it possible to create an ExprWithCleanups that produces a +    // bitfield lvalue or some other non-simple lvalue? +    return LV;    }    case Expr::CXXDefaultArgExprClass: @@ -1265,6 +1316,53 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {    return MDHelper.createRange(Min, End);  } +bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty, +                                           SourceLocation Loc) { +  bool HasBoolCheck = SanOpts.has(SanitizerKind::Bool); +  bool HasEnumCheck = SanOpts.has(SanitizerKind::Enum); +  if (!HasBoolCheck && !HasEnumCheck) +    return false; + +  bool IsBool = hasBooleanRepresentation(Ty) || +                NSAPI(CGM.getContext()).isObjCBOOLType(Ty); +  bool NeedsBoolCheck = HasBoolCheck && IsBool; +  bool NeedsEnumCheck = HasEnumCheck && Ty->getAs<EnumType>(); +  if (!NeedsBoolCheck && !NeedsEnumCheck) +    return false; + +  // Single-bit booleans don't need to be checked. Special-case this to avoid +  // a bit width mismatch when handling bitfield values. This is handled by +  // EmitFromMemory for the non-bitfield case. +  if (IsBool && +      cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1) +    return false; + +  llvm::APInt Min, End; +  if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) +    return true; + +  SanitizerScope SanScope(this); +  llvm::Value *Check; +  --End; +  if (!Min) { +    Check = Builder.CreateICmpULE( +        Value, llvm::ConstantInt::get(getLLVMContext(), End)); +  } else { +    llvm::Value *Upper = Builder.CreateICmpSLE( +        Value, llvm::ConstantInt::get(getLLVMContext(), End)); +    llvm::Value *Lower = Builder.CreateICmpSGE( +        Value, llvm::ConstantInt::get(getLLVMContext(), Min)); +    Check = Builder.CreateAnd(Upper, Lower); +  } +  llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc), +                                  EmitCheckTypeDescriptor(Ty)}; +  SanitizerMask Kind = +      NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool; +  EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue, +            StaticArgs, EmitCheckValue(Value)); +  return true; +} +  llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,                                                 QualType Ty,                                                 SourceLocation Loc, @@ -1273,26 +1371,28 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,                                                 QualType TBAABaseType,                                                 uint64_t TBAAOffset,                                                 bool isNontemporal) { -  // For better performance, handle vector loads differently. -  if (Ty->isVectorType()) { -    const llvm::Type *EltTy = Addr.getElementType(); - -    const auto *VTy = cast<llvm::VectorType>(EltTy); - -    // Handle vectors of size 3 like size 4 for better performance. -    if (VTy->getNumElements() == 3) { - -      // Bitcast to vec4 type. -      llvm::VectorType *vec4Ty = llvm::VectorType::get(VTy->getElementType(), -                                                         4); -      Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4"); -      // Now load value. -      llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4"); - -      // Shuffle vector to get vec3. -      V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty), -                                      {0, 1, 2}, "extractVec"); -      return EmitFromMemory(V, Ty); +  if (!CGM.getCodeGenOpts().PreserveVec3Type) { +    // For better performance, handle vector loads differently. +    if (Ty->isVectorType()) { +      const llvm::Type *EltTy = Addr.getElementType(); + +      const auto *VTy = cast<llvm::VectorType>(EltTy); + +      // Handle vectors of size 3 like size 4 for better performance. +      if (VTy->getNumElements() == 3) { + +        // Bitcast to vec4 type. +        llvm::VectorType *vec4Ty = +            llvm::VectorType::get(VTy->getElementType(), 4); +        Address Cast = Builder.CreateElementBitCast(Addr, vec4Ty, "castToVec4"); +        // Now load value. +        llvm::Value *V = Builder.CreateLoad(Cast, Volatile, "loadVec4"); + +        // Shuffle vector to get vec3. +        V = Builder.CreateShuffleVector(V, llvm::UndefValue::get(vec4Ty), +                                        {0, 1, 2}, "extractVec"); +        return EmitFromMemory(V, Ty); +      }      }    } @@ -1317,35 +1417,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,                                        false /*ConvertTypeToTag*/);    } -  bool IsBool = hasBooleanRepresentation(Ty) || -                NSAPI(CGM.getContext()).isObjCBOOLType(Ty); -  bool NeedsBoolCheck = SanOpts.has(SanitizerKind::Bool) && IsBool; -  bool NeedsEnumCheck = -      SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>(); -  if (NeedsBoolCheck || NeedsEnumCheck) { -    SanitizerScope SanScope(this); -    llvm::APInt Min, End; -    if (getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) { -      --End; -      llvm::Value *Check; -      if (!Min) -        Check = Builder.CreateICmpULE( -          Load, llvm::ConstantInt::get(getLLVMContext(), End)); -      else { -        llvm::Value *Upper = Builder.CreateICmpSLE( -          Load, llvm::ConstantInt::get(getLLVMContext(), End)); -        llvm::Value *Lower = Builder.CreateICmpSGE( -          Load, llvm::ConstantInt::get(getLLVMContext(), Min)); -        Check = Builder.CreateAnd(Upper, Lower); -      } -      llvm::Constant *StaticArgs[] = { -        EmitCheckSourceLocation(Loc), -        EmitCheckTypeDescriptor(Ty) -      }; -      SanitizerMask Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool; -      EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue, -                StaticArgs, EmitCheckValue(Load)); -    } +  if (EmitScalarRangeCheck(Load, Ty, Loc)) { +    // In order to prevent the optimizer from throwing away the check, don't +    // attach range metadata to the load.    } else if (CGM.getCodeGenOpts().OptimizationLevel > 0)      if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))        Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo); @@ -1386,24 +1460,25 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,                                          uint64_t TBAAOffset,                                          bool isNontemporal) { -  // Handle vectors differently to get better performance. -  if (Ty->isVectorType()) { -    llvm::Type *SrcTy = Value->getType(); -    auto *VecTy = cast<llvm::VectorType>(SrcTy); -    // Handle vec3 special. -    if (VecTy->getNumElements() == 3) { -      // Our source is a vec3, do a shuffle vector to make it a vec4. -      llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), -                                Builder.getInt32(2), -                                llvm::UndefValue::get(Builder.getInt32Ty())}; -      llvm::Value *MaskV = llvm::ConstantVector::get(Mask); -      Value = Builder.CreateShuffleVector(Value, -                                          llvm::UndefValue::get(VecTy), -                                          MaskV, "extractVec"); -      SrcTy = llvm::VectorType::get(VecTy->getElementType(), 4); -    } -    if (Addr.getElementType() != SrcTy) { -      Addr = Builder.CreateElementBitCast(Addr, SrcTy, "storetmp"); +  if (!CGM.getCodeGenOpts().PreserveVec3Type) { +    // Handle vectors differently to get better performance. +    if (Ty->isVectorType()) { +      llvm::Type *SrcTy = Value->getType(); +      auto *VecTy = cast<llvm::VectorType>(SrcTy); +      // Handle vec3 special. +      if (VecTy->getNumElements() == 3) { +        // Our source is a vec3, do a shuffle vector to make it a vec4. +        llvm::Constant *Mask[] = {Builder.getInt32(0), Builder.getInt32(1), +                                  Builder.getInt32(2), +                                  llvm::UndefValue::get(Builder.getInt32Ty())}; +        llvm::Value *MaskV = llvm::ConstantVector::get(Mask); +        Value = Builder.CreateShuffleVector(Value, llvm::UndefValue::get(VecTy), +                                            MaskV, "extractVec"); +        SrcTy = llvm::VectorType::get(VecTy->getElementType(), 4); +      } +      if (Addr.getElementType() != SrcTy) { +        Addr = Builder.CreateElementBitCast(Addr, SrcTy, "storetmp"); +      }      }    } @@ -1487,10 +1562,11 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {      return EmitLoadOfGlobalRegLValue(LV);    assert(LV.isBitField() && "Unknown LValue type!"); -  return EmitLoadOfBitfieldLValue(LV); +  return EmitLoadOfBitfieldLValue(LV, Loc);  } -RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) { +RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, +                                                 SourceLocation Loc) {    const CGBitFieldInfo &Info = LV.getBitFieldInfo();    // Get the output type. @@ -1515,7 +1591,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {                                "bf.clear");    }    Val = Builder.CreateIntCast(Val, ResLTy, Info.IsSigned, "bf.cast"); - +  EmitScalarRangeCheck(Val, LV.getType(), Loc);    return RValue::get(Val);  } @@ -2545,8 +2621,8 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,    llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(        FnType, FnName, -      llvm::AttributeSet::get(CGF.getLLVMContext(), -                              llvm::AttributeSet::FunctionIndex, B), +      llvm::AttributeList::get(CGF.getLLVMContext(), +                               llvm::AttributeList::FunctionIndex, B),        /*Local=*/true);    llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs);    if (!MayReturn) { @@ -2709,6 +2785,24 @@ void CodeGenFunction::EmitCfiSlowPathCheck(    EmitBlock(Cont);  } +// Emit a stub for __cfi_check function so that the linker knows about this +// symbol in LTO mode. +void CodeGenFunction::EmitCfiCheckStub() { +  llvm::Module *M = &CGM.getModule(); +  auto &Ctx = M->getContext(); +  llvm::Function *F = llvm::Function::Create( +      llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false), +      llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M); +  llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F); +  // FIXME: consider emitting an intrinsic call like +  // call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2) +  // which can be lowered in CrossDSOCFI pass to the actual contents of +  // __cfi_check. This would allow inlining of __cfi_check calls. +  llvm::CallInst::Create( +      llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap), "", BB); +  llvm::ReturnInst::Create(Ctx, nullptr, BB); +} +  // This function is basically a switch over the CFI failure kind, which is  // extracted from CFICheckFailData (1st function argument). Each case is either  // llvm.trap or a call to one of the two runtime handlers, based on @@ -2821,7 +2915,7 @@ llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {    if (!CGM.getCodeGenOpts().TrapFuncName.empty()) {      auto A = llvm::Attribute::get(getLLVMContext(), "trap-func-name",                                    CGM.getCodeGenOpts().TrapFuncName); -    TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, A); +    TrapCall->addAttribute(llvm::AttributeList::FunctionIndex, A);    }    return TrapCall; @@ -3335,7 +3429,14 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {      AlignmentSource AlignSource;      Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource);      QualType PtrTy = BaseExpr->getType()->getPointeeType(); -    EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy); +    SanitizerSet SkippedChecks; +    bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr); +    if (IsBaseCXXThis) +      SkippedChecks.set(SanitizerKind::Alignment, true); +    if (IsBaseCXXThis || isa<DeclRefExpr>(BaseExpr)) +      SkippedChecks.set(SanitizerKind::Null, true); +    EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, +                  /*Alignment=*/CharUnits::Zero(), SkippedChecks);      BaseLV = MakeAddrLValue(Addr, PtrTy, AlignSource);    } else      BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);  | 
