diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/BackendUtil.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 36 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 29 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 27 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 157 | ||||
-rw-r--r-- | clang/lib/CodeGen/SanitizerHandler.h | 88 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp | 37 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp | 61 |
9 files changed, 320 insertions, 123 deletions
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 1b72578..0b8b824 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1027,12 +1027,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline( MPM.addPass( createModuleToFunctionPassAdaptor(ObjCARCExpandPass())); }); - PB.registerPipelineEarlySimplificationEPCallback( - [](ModulePassManager &MPM, OptimizationLevel Level, - ThinOrFullLTOPhase) { - if (Level != OptimizationLevel::O0) - MPM.addPass(ObjCARCAPElimPass()); - }); PB.registerScalarOptimizerLateEPCallback( [](FunctionPassManager &FPM, OptimizationLevel Level) { if (Level != OptimizationLevel::O0) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0bceece..d9bd443 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2852,20 +2852,28 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, if (AI.getInReg()) Attrs.addAttribute(llvm::Attribute::InReg); - // Depending on the ABI, this may be either a byval or a dead_on_return - // argument. - if (AI.getIndirectByVal()) { - Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); - } else { - // Add dead_on_return when the object's lifetime ends in the callee. - // This includes trivially-destructible objects, as well as objects - // whose destruction / clean-up is carried out within the callee (e.g., - // Obj-C ARC-managed structs, MSVC callee-destroyed objects). - if (!ParamType.isDestructedType() || !ParamType->isRecordType() || - ParamType->castAs<RecordType>() - ->getDecl() - ->isParamDestroyedInCallee()) - Attrs.addAttribute(llvm::Attribute::DeadOnReturn); + // HLSL out and inout parameters must not be marked with ByVal or + // DeadOnReturn attributes because stores to these parameters by the + // callee are visible to the caller. + if (auto ParamABI = FI.getExtParameterInfo(ArgNo).getABI(); + ParamABI != ParameterABI::HLSLOut && + ParamABI != ParameterABI::HLSLInOut) { + + // Depending on the ABI, this may be either a byval or a dead_on_return + // argument. + if (AI.getIndirectByVal()) { + Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); + } else { + // Add dead_on_return when the object's lifetime ends in the callee. + // This includes trivially-destructible objects, as well as objects + // whose destruction / clean-up is carried out within the callee + // (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects). + if (!ParamType.isDestructedType() || !ParamType->isRecordType() || + ParamType->castAs<RecordType>() + ->getDecl() + ->isParamDestroyedInCallee()) + Attrs.addAttribute(llvm::Attribute::DeadOnReturn); + } } auto *Decl = ParamType->getAsRecordDecl(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a371b67..77fc3a2 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -6435,7 +6435,7 @@ CodeGenFunction::LexicalScope::~LexicalScope() { static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) { std::string Label; switch (Handler) { -#define SANITIZER_CHECK(Enum, Name, Version) \ +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ case Enum: \ Label = "__ubsan_check_" #Name; \ break; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c7688..90aed79 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -85,6 +85,16 @@ enum VariableTypeDescriptorKind : uint16_t { // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// +static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { + switch (ID) { +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ + case SanitizerHandler::Enum: \ + return Msg; + LIST_SANITIZER_CHECKS +#undef SANITIZER_CHECK + } +} + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. RawAddress @@ -3649,7 +3659,7 @@ struct SanitizerHandlerInfo { } const SanitizerHandlerInfo SanitizerHandlers[] = { -#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version}, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) {#Name, Version}, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; @@ -3954,6 +3964,8 @@ void CodeGenFunction::EmitCfiCheckFail() { StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, SourceLocation()); + ApplyDebugLocation ADL = ApplyDebugLocation::CreateArtificial(*this); + // This function is not affected by NoSanitizeList. This function does // not have a source location, but "src:*" would still apply. Revert any // changes to SanOpts made in StartFunction. @@ -4051,6 +4063,15 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; + llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); + llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID); + + if (getDebugInfo() && !TrapMessage.empty() && + CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) { + TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor( + TrapLocation, "Undefined Behavior Sanitizer", TrapMessage); + } + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); @@ -4059,8 +4080,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, auto Call = TrapBB->begin(); assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB"); - Call->applyMergedLocation(Call->getDebugLoc(), - Builder.getCurrentDebugLocation()); + Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation); + Builder.CreateCondBr(Checked, Cont, TrapBB, MDHelper.createLikelyBranchWeights()); } else { @@ -4069,6 +4090,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, MDHelper.createLikelyBranchWeights()); EmitBlock(TrapBB); + ApplyDebugLocation applyTrapDI(*this, TrapLocation); + llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID)); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 359e30c..b8238a4 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2146,30 +2146,9 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { return; } - // We might be deleting a pointer to array. If so, GEP down to the - // first non-array element. - // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*) - if (DeleteTy->isConstantArrayType()) { - llvm::Value *Zero = Builder.getInt32(0); - SmallVector<llvm::Value*,8> GEP; - - GEP.push_back(Zero); // point at the outermost array - - // For each layer of array type we're pointing at: - while (const ConstantArrayType *Arr - = getContext().getAsConstantArrayType(DeleteTy)) { - // 1. Unpeel the array type. - DeleteTy = Arr->getElementType(); - - // 2. GEP to the first element of the array. - GEP.push_back(Zero); - } - - Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), - Ptr.getAlignment(), "del.first"); - } - - assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); + // We might be deleting a pointer to array. + DeleteTy = getContext().getBaseElementType(DeleteTy); + Ptr = Ptr.withElementType(ConvertTypeForMem(DeleteTy)); if (E->isArrayForm()) { EmitArrayDelete(*this, E, Ptr, DeleteTy); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index ce2dd4d..91237cf 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7080,6 +7080,110 @@ private: return ConstLength.getSExtValue() != 1; } + /// A helper class to copy structures with overlapped elements, i.e. those + /// which have mappings of both "s" and "s.mem". Consecutive elements that + /// are not explicitly copied have mapping nodes synthesized for them, + /// taking care to avoid generating zero-sized copies. + class CopyOverlappedEntryGaps { + CodeGenFunction &CGF; + MapCombinedInfoTy &CombinedInfo; + OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE; + const ValueDecl *MapDecl = nullptr; + const Expr *MapExpr = nullptr; + Address BP = Address::invalid(); + bool IsNonContiguous = false; + uint64_t DimSize = 0; + // These elements track the position as the struct is iterated over + // (in order of increasing element address). + const RecordDecl *LastParent = nullptr; + uint64_t Cursor = 0; + unsigned LastIndex = -1u; + Address LB = Address::invalid(); + + public: + CopyOverlappedEntryGaps(CodeGenFunction &CGF, + MapCombinedInfoTy &CombinedInfo, + OpenMPOffloadMappingFlags Flags, + const ValueDecl *MapDecl, const Expr *MapExpr, + Address BP, Address LB, bool IsNonContiguous, + uint64_t DimSize) + : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl), + MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous), + DimSize(DimSize), LB(LB) {} + + void processField( + const OMPClauseMappableExprCommon::MappableComponent &MC, + const FieldDecl *FD, + llvm::function_ref<LValue(CodeGenFunction &, const MemberExpr *)> + EmitMemberExprBase) { + const RecordDecl *RD = FD->getParent(); + const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); + uint64_t FieldOffset = RL.getFieldOffset(FD->getFieldIndex()); + uint64_t FieldSize = + CGF.getContext().getTypeSize(FD->getType().getCanonicalType()); + Address ComponentLB = Address::invalid(); + + if (FD->getType()->isLValueReferenceType()) { + const auto *ME = cast<MemberExpr>(MC.getAssociatedExpression()); + LValue BaseLVal = EmitMemberExprBase(CGF, ME); + ComponentLB = + CGF.EmitLValueForFieldInitialization(BaseLVal, FD).getAddress(); + } else { + ComponentLB = + CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()).getAddress(); + } + + if (!LastParent) + LastParent = RD; + if (FD->getParent() == LastParent) { + if (FD->getFieldIndex() != LastIndex + 1) + copyUntilField(FD, ComponentLB); + } else { + LastParent = FD->getParent(); + if (((int64_t)FieldOffset - (int64_t)Cursor) > 0) + copyUntilField(FD, ComponentLB); + } + Cursor = FieldOffset + FieldSize; + LastIndex = FD->getFieldIndex(); + LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); + } + + void copyUntilField(const FieldDecl *FD, Address ComponentLB) { + llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + llvm::Value *Size = + CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, LBPtr); + copySizedChunk(LBPtr, Size); + } + + void copyUntilEnd(Address HB) { + if (LastParent) { + const ASTRecordLayout &RL = + CGF.getContext().getASTRecordLayout(LastParent); + if ((uint64_t)CGF.getContext().toBits(RL.getSize()) <= Cursor) + return; + } + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + llvm::Value *Size = CGF.Builder.CreatePtrDiff( + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), + LBPtr); + copySizedChunk(LBPtr, Size); + } + + void copySizedChunk(llvm::Value *Base, llvm::Value *Size) { + CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); + CombinedInfo.DevicePtrDecls.push_back(nullptr); + CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); + CombinedInfo.Pointers.push_back(Base); + CombinedInfo.Sizes.push_back( + CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); + CombinedInfo.Types.push_back(Flags); + CombinedInfo.Mappers.push_back(nullptr); + CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); + } + }; + /// Generate the base pointers, section pointers, sizes, map type bits, and /// user-defined mappers (all included in \a CombinedInfo) for the provided /// map type, map or motion modifiers, and expression components. @@ -7570,63 +7674,22 @@ private: getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, /*AddPtrFlag=*/false, /*AddIsTargetParamFlag=*/false, IsNonContiguous); - llvm::Value *Size = nullptr; + CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl, + MapExpr, BP, LB, IsNonContiguous, + DimSize); // Do bitcopy of all non-overlapped structure elements. for (OMPClauseMappableExprCommon::MappableExprComponentListRef Component : OverlappedElements) { - Address ComponentLB = Address::invalid(); for (const OMPClauseMappableExprCommon::MappableComponent &MC : Component) { if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { - const auto *FD = dyn_cast<FieldDecl>(VD); - if (FD && FD->getType()->isLValueReferenceType()) { - const auto *ME = - cast<MemberExpr>(MC.getAssociatedExpression()); - LValue BaseLVal = EmitMemberExprBase(CGF, ME); - ComponentLB = - CGF.EmitLValueForFieldInitialization(BaseLVal, FD) - .getAddress(); - } else { - ComponentLB = - CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) - .getAddress(); + if (const auto *FD = dyn_cast<FieldDecl>(VD)) { + CopyGaps.processField(MC, FD, EmitMemberExprBase); } - llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); - llvm::Value *LBPtr = LB.emitRawPointer(CGF); - Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, - LBPtr); - break; } } - assert(Size && "Failed to determine structure size"); - CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); - CombinedInfo.DevicePtrDecls.push_back(nullptr); - CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); - CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( - Size, CGF.Int64Ty, /*isSigned=*/true)); - CombinedInfo.Types.push_back(Flags); - CombinedInfo.Mappers.push_back(nullptr); - CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize - : 1); - LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } - CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); - CombinedInfo.DevicePtrDecls.push_back(nullptr); - CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); - llvm::Value *LBPtr = LB.emitRawPointer(CGF); - Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), - LBPtr); - CombinedInfo.Sizes.push_back( - CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); - CombinedInfo.Types.push_back(Flags); - CombinedInfo.Mappers.push_back(nullptr); - CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize - : 1); + CopyGaps.copyUntilEnd(HB); break; } llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); diff --git a/clang/lib/CodeGen/SanitizerHandler.h b/clang/lib/CodeGen/SanitizerHandler.h index bb42e39..a66e7ab 100644 --- a/clang/lib/CodeGen/SanitizerHandler.h +++ b/clang/lib/CodeGen/SanitizerHandler.h @@ -14,35 +14,69 @@ #define LLVM_CLANG_LIB_CODEGEN_SANITIZER_HANDLER_H #define LIST_SANITIZER_CHECKS \ - SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ - SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \ - SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \ - SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ - SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ - SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ - SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ - SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ - SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ - SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ - SANITIZER_CHECK(MissingReturn, missing_return, 0) \ - SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ - SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ - SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ - SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \ - SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ - SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \ - SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ - SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ - SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ - SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ - SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ - SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) \ - SANITIZER_CHECK(BoundsSafety, bounds_safety, 0) + SANITIZER_CHECK(AddOverflow, add_overflow, 0, "Integer addition overflowed") \ + SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0, \ + "_builtin_unreachable(), execution reached an unreachable " \ + "program point") \ + SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0, \ + "Control flow integrity check failed") \ + SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0, \ + "Integer divide or remainder overflowed") \ + SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0, \ + "Dynamic type cache miss, member call made on an object " \ + "whose dynamic type differs from the expected type") \ + SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0, \ + "Floating-point to integer conversion overflowed") \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0, \ + "Function called with mismatched signature") \ + SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0, \ + "Implicit integer conversion overflowed or lost data") \ + SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0, \ + "Invalid use of builtin function") \ + SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0, \ + "Invalid Objective-C cast") \ + SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0, \ + "Loaded an invalid or uninitialized value for the type") \ + SANITIZER_CHECK(MissingReturn, missing_return, 0, \ + "Execution reached the end of a value-returning function " \ + "without returning a value") \ + SANITIZER_CHECK(MulOverflow, mul_overflow, 0, \ + "Integer multiplication overflowed") \ + SANITIZER_CHECK(NegateOverflow, negate_overflow, 0, \ + "Integer negation overflowed") \ + SANITIZER_CHECK( \ + NullabilityArg, nullability_arg, 0, \ + "Passing null as an argument which is annotated with _Nonnull") \ + SANITIZER_CHECK(NullabilityReturn, nullability_return, 1, \ + "Returning null from a function with a return type " \ + "annotated with _Nonnull") \ + SANITIZER_CHECK(NonnullArg, nonnull_arg, 0, \ + "Passing null pointer as an argument which is declared to " \ + "never be null") \ + SANITIZER_CHECK(NonnullReturn, nonnull_return, 1, \ + "Returning null pointer from a function which is declared " \ + "to never return null") \ + SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0, "Array index out of bounds") \ + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0, \ + "Pointer arithmetic overflowed bounds") \ + SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0, \ + "Shift exponent is too large for the type") \ + SANITIZER_CHECK(SubOverflow, sub_overflow, 0, \ + "Integer subtraction overflowed") \ + SANITIZER_CHECK(TypeMismatch, type_mismatch, 1, \ + "Type mismatch in operation") \ + SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0, \ + "Alignment assumption violated") \ + SANITIZER_CHECK( \ + VLABoundNotPositive, vla_bound_not_positive, 0, \ + "Variable length array bound evaluates to non-positive value") \ + SANITIZER_CHECK(BoundsSafety, bounds_safety, 0, \ + "") // BoundsSafety Msg is empty because it is not considered + // part of UBSan; therefore, no trap reason is emitted for + // this case. enum SanitizerHandler { -#define SANITIZER_CHECK(Enum, Name, Version) Enum, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) Enum, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp index 7dccf82..70f510a 100644 --- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp @@ -274,7 +274,7 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments, void CodeGenFunction::AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst, const CallExpr *E) { - constexpr const char *Tag = "amdgpu-as"; + constexpr const char *Tag = "amdgpu-synchronize-as"; LLVMContext &Ctx = Inst->getContext(); SmallVector<MMRAMetadata::TagT, 3> MMRAs; @@ -633,6 +633,41 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); return Builder.CreateCall(F, {Addr}); } + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32: + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64: + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64: + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128: { + + Intrinsic::ID IID; + switch (BuiltinID) { + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32: + IID = Intrinsic::amdgcn_global_load_monitor_b32; + break; + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64: + IID = Intrinsic::amdgcn_global_load_monitor_b64; + break; + case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128: + IID = Intrinsic::amdgcn_global_load_monitor_b128; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32: + IID = Intrinsic::amdgcn_flat_load_monitor_b32; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64: + IID = Intrinsic::amdgcn_flat_load_monitor_b64; + break; + case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128: + IID = Intrinsic::amdgcn_flat_load_monitor_b128; + break; + } + + llvm::Type *LoadTy = ConvertType(E->getType()); + llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); + llvm::Value *Val = EmitScalarExpr(E->getArg(1)); + llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); + return Builder.CreateCall(F, {Addr, Val}); + } case AMDGPU::BI__builtin_amdgcn_load_to_lds: { // Should this have asan instrumentation? return emitBuiltinWithOneOverloadedType<5>(*this, E, diff --git a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp index b7fd70e..33a8d8f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/WebAssembly.cpp @@ -12,7 +12,10 @@ #include "CGBuiltin.h" #include "clang/Basic/TargetBuiltins.h" +#include "llvm/ADT/APInt.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/IntrinsicsWebAssembly.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace CodeGen; @@ -218,6 +221,64 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func); return Builder.CreateCall(Callee); } + case WebAssembly::BI__builtin_wasm_test_function_pointer_signature: { + Value *FuncRef = EmitScalarExpr(E->getArg(0)); + + // Get the function type from the argument's static type + QualType ArgType = E->getArg(0)->getType(); + const PointerType *PtrTy = ArgType->getAs<PointerType>(); + assert(PtrTy && "Sema should have ensured this is a function pointer"); + + const FunctionType *FuncTy = PtrTy->getPointeeType()->getAs<FunctionType>(); + assert(FuncTy && "Sema should have ensured this is a function pointer"); + + // In the llvm IR, we won't have access any more to the type of the function + // pointer so we need to insert this type information somehow. The + // @llvm.wasm.ref.test.func takes varargs arguments whose values are unused + // to indicate the type of the function to test for. See the test here: + // llvm/test/CodeGen/WebAssembly/ref-test-func.ll + // + // The format is: first we include the return types (since this is a C + // function pointer, there will be 0 or one of these) then a token type to + // indicate the boundary between return types and param types, then the + // param types. + + llvm::FunctionType *LLVMFuncTy = + cast<llvm::FunctionType>(ConvertType(QualType(FuncTy, 0))); + + unsigned NParams = LLVMFuncTy->getNumParams(); + std::vector<Value *> Args; + Args.reserve(NParams + 3); + // The only real argument is the FuncRef + Args.push_back(FuncRef); + + // Add the type information + auto addType = [this, &Args](llvm::Type *T) { + if (T->isVoidTy()) { + // Do nothing + } else if (T->isFloatingPointTy()) { + Args.push_back(ConstantFP::get(T, 0)); + } else if (T->isIntegerTy()) { + Args.push_back(ConstantInt::get(T, 0)); + } else if (T->isPointerTy()) { + Args.push_back(ConstantPointerNull::get(llvm::PointerType::get( + getLLVMContext(), T->getPointerAddressSpace()))); + } else { + // TODO: Handle reference types. For now, we reject them in Sema. + llvm_unreachable("Unhandled type"); + } + }; + + addType(LLVMFuncTy->getReturnType()); + // The token type indicates the boundary between return types and param + // types. + Args.push_back(PoisonValue::get(llvm::Type::getTokenTy(getLLVMContext()))); + for (unsigned i = 0; i < NParams; i++) { + addType(LLVMFuncTy->getParamType(i)); + } + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_test_func); + return Builder.CreateCall(Callee, Args); + } case WebAssembly::BI__builtin_wasm_swizzle_i8x16: { Value *Src = EmitScalarExpr(E->getArg(0)); Value *Indices = EmitScalarExpr(E->getArg(1)); |