Skip to content

Commit

Permalink
Merge from 'master' to 'sycl-web' (intel#22)
Browse files Browse the repository at this point in the history
  CONFLICT (content): Merge conflict in clang/lib/Driver/ToolChains/Clang.cpp
  • Loading branch information
sndmitriev committed Oct 17, 2019
2 parents bdba33b + 3b598b9 commit 820f77c
Show file tree
Hide file tree
Showing 138 changed files with 5,634 additions and 2,604 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
/// vtable optimization.

CODEGENOPT(VirtualFunctionElimination, 1, 0) ///< Whether to apply the dead
/// virtual function elimination
/// optimization.

/// Whether to use public LTO visibility for entities in std and stdext
/// namespaces. This is enabled by clang-cl's /MT and /MTd flags.
CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,13 @@ def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
HelpText<"Emits more virtual tables to improve devirtualization">;
def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group<f_Group>,
Flags<[CoreOption]>;

def fvirtual_function_elimination : Flag<["-"], "fvirtual-function-elimination">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>,
HelpText<"Enables dead virtual function elimination optimization. Requires -flto=full">;
def fno_virtual_function_elimination : Flag<["-"], "fno-virtual-function_elimination">, Group<f_Group>,
Flags<[CoreOption]>;

def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Treat signed integer overflow as two's complement">;
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
Expand Down
18 changes: 14 additions & 4 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2786,11 +2786,16 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,

bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
if (!CGM.getCodeGenOpts().WholeProgramVTables ||
!SanOpts.has(SanitizerKind::CFIVCall) ||
!CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall) ||
!CGM.HasHiddenLTOVisibility(RD))
return false;

if (CGM.getCodeGenOpts().VirtualFunctionElimination)
return true;

if (!SanOpts.has(SanitizerKind::CFIVCall) ||
!CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
return false;

std::string TypeName = RD->getQualifiedNameAsString();
return !getContext().getSanitizerBlacklist().isBlacklistedType(
SanitizerKind::CFIVCall, TypeName);
Expand All @@ -2813,8 +2818,13 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
TypeId});
llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);

EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
SanitizerHandler::CFICheckFail, nullptr, nullptr);
std::string TypeName = RD->getQualifiedNameAsString();
if (SanOpts.has(SanitizerKind::CFIVCall) &&
!getContext().getSanitizerBlacklist().isBlacklistedType(
SanitizerKind::CFIVCall, TypeName)) {
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
SanitizerHandler::CFICheckFail, {}, {});
}

return Builder.CreateBitCast(
Builder.CreateExtractValue(CheckedLoad, 0),
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,6 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
CGM.getModule(), Descriptor->getType(),
/*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor);
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.setPragmaSectionAttributes(CurFuncDecl, GV);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV);

// Remember the descriptor for this type.
Expand Down Expand Up @@ -2911,7 +2910,6 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
}

auto FilenameGV = CGM.GetAddrOfConstantCString(FilenameString, ".src");
CGM.setPragmaSectionAttributes(CurFuncDecl, cast<llvm::GlobalVariable>(FilenameGV.getPointer()));
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(
cast<llvm::GlobalVariable>(FilenameGV.getPointer()));
Filename = FilenameGV.getPointer();
Expand Down Expand Up @@ -3085,7 +3083,6 @@ void CodeGenFunction::EmitCheck(
new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
llvm::GlobalVariable::PrivateLinkage, Info);
InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.setPragmaSectionAttributes(CurFuncDecl, InfoPtr);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy));
ArgTypes.push_back(Int8PtrTy);
Expand Down
35 changes: 33 additions & 2 deletions clang/lib/CodeGen/CGVTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
assert(!VTable->isDeclaration() && "Shouldn't set properties on declaration");
CGM.setGVProperties(VTable, RD);

CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
CGM.EmitVTableTypeMetadata(RD, VTable, *VTLayout.get());

return VTable;
}
Expand Down Expand Up @@ -1039,7 +1039,32 @@ bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
return true;
}

void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
llvm::GlobalObject::VCallVisibility
CodeGenModule::GetVCallVisibilityLevel(const CXXRecordDecl *RD) {
LinkageInfo LV = RD->getLinkageAndVisibility();
llvm::GlobalObject::VCallVisibility TypeVis;
if (!isExternallyVisible(LV.getLinkage()))
TypeVis = llvm::GlobalObject::VCallVisibilityTranslationUnit;
else if (HasHiddenLTOVisibility(RD))
TypeVis = llvm::GlobalObject::VCallVisibilityLinkageUnit;
else
TypeVis = llvm::GlobalObject::VCallVisibilityPublic;

for (auto B : RD->bases())
if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
TypeVis = std::min(TypeVis,
GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl()));

for (auto B : RD->vbases())
if (B.getType()->getAsCXXRecordDecl()->isDynamicClass())
TypeVis = std::min(TypeVis,
GetVCallVisibilityLevel(B.getType()->getAsCXXRecordDecl()));

return TypeVis;
}

void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD,
llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout) {
if (!getCodeGenOpts().LTOUnit)
return;
Expand Down Expand Up @@ -1099,4 +1124,10 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD);
}
}

if (getCodeGenOpts().VirtualFunctionElimination) {
llvm::GlobalObject::VCallVisibility TypeVis = GetVCallVisibilityLevel(RD);
if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
VTable->addVCallVisibilityMetadata(TypeVis);
}
}
27 changes: 5 additions & 22 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,8 +1732,11 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
return AddedAttr;
}

void CodeGenModule::setPragmaSectionAttributes(const Decl *D,
llvm::GlobalObject *GO) {
void CodeGenModule::setNonAliasAttributes(GlobalDecl GD,
llvm::GlobalObject *GO) {
const Decl *D = GD.getDecl();
SetCommonAttributes(GD, GO);

if (D) {
if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) {
if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>())
Expand All @@ -1751,26 +1754,6 @@ void CodeGenModule::setPragmaSectionAttributes(const Decl *D,
if (!D->getAttr<SectionAttr>())
F->addFnAttr("implicit-section-name", SA->getName());

if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>())
F->addFnAttr("bss-section", SA->getName());
if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>())
F->addFnAttr("data-section", SA->getName());
if (auto *SA = D->getAttr<PragmaClangRodataSectionAttr>())
F->addFnAttr("rodata-section", SA->getName());
if (auto *SA = D->getAttr<PragmaClangRelroSectionAttr>())
F->addFnAttr("relro-section", SA->getName());
}
}
}

void CodeGenModule::setNonAliasAttributes(GlobalDecl GD,
llvm::GlobalObject *GO) {
const Decl *D = GD.getDecl();
SetCommonAttributes(GD, GO);
setPragmaSectionAttributes(D, GO);

if (D) {
if (auto *F = dyn_cast<llvm::Function>(GO)) {
llvm::AttrBuilder Attrs;
if (GetCPUAndFeaturesAttributes(GD, Attrs)) {
// We know that GetCPUAndFeaturesAttributes will always have the
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1293,8 +1293,16 @@ class CodeGenModule : public CodeGenTypeCache {
/// optimization.
bool HasHiddenLTOVisibility(const CXXRecordDecl *RD);

/// Returns the vcall visibility of the given type. This is the scope in which
/// a virtual function call could be made which ends up being dispatched to a
/// member function of this class. This scope can be wider than the visibility
/// of the class itself when the class has a more-visible dynamic base class.
llvm::GlobalObject::VCallVisibility
GetVCallVisibilityLevel(const CXXRecordDecl *RD);

/// Emit type metadata for the given vtable using the given layout.
void EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
void EmitVTableTypeMetadata(const CXXRecordDecl *RD,
llvm::GlobalVariable *VTable,
const VTableLayout &VTLayout);

/// Generate a cross-DSO type identifier for MD.
Expand Down Expand Up @@ -1360,11 +1368,6 @@ class CodeGenModule : public CodeGenTypeCache {
/// \param QT is the clang QualType of the null pointer.
llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT);

/// Set section attributes requested by "#pragma clang section"
/// \param D is the declaration to read semantic attributes from.
/// \param GO is the global object to set section attributes.
void setPragmaSectionAttributes(const Decl *D, llvm::GlobalObject *GO);

private:
llvm::Constant *GetOrCreateLLVMFunction(
StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
Expand Down
105 changes: 70 additions & 35 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,53 +644,88 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
}
// Compute the address of the virtual function pointer.
llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);

// Check the address of the function pointer if CFI on member function
// pointers is enabled.
llvm::Constant *CheckSourceLocation;
llvm::Constant *CheckTypeDesc;
bool ShouldEmitCFICheck = CGF.SanOpts.has(SanitizerKind::CFIMFCall) &&
CGM.HasHiddenLTOVisibility(RD);
if (ShouldEmitCFICheck) {
CodeGenFunction::SanitizerScope SanScope(&CGF);

CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc());
CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
CheckSourceLocation,
CheckTypeDesc,
};

llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
bool ShouldEmitVFEInfo = CGM.getCodeGenOpts().VirtualFunctionElimination &&
CGM.HasHiddenLTOVisibility(RD);
llvm::Value *VirtualFn = nullptr;

llvm::Value *TypeTest = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {VFPAddr, TypeId});
{
CodeGenFunction::SanitizerScope SanScope(&CGF);
llvm::Value *TypeId = nullptr;
llvm::Value *CheckResult = nullptr;

if (ShouldEmitCFICheck || ShouldEmitVFEInfo) {
// If doing CFI or VFE, we will need the metadata node to check against.
llvm::Metadata *MD =
CGM.CreateMetadataIdentifierForVirtualMemPtrType(QualType(MPT, 0));
TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
}

if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
CGF.EmitTrapCheck(TypeTest);
llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);

if (ShouldEmitVFEInfo) {
// If doing VFE, load from the vtable with a type.checked.load intrinsic
// call. Note that we use the GEP to calculate the address to load from
// and pass 0 as the offset to the intrinsic. This is because every
// vtable slot of the correct type is marked with matching metadata, and
// we know that the load must be from one of these slots.
llvm::Value *CheckedLoad = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
{VFPAddr, llvm::ConstantInt::get(CGM.Int32Ty, 0), TypeId});
CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
VirtualFn = Builder.CreateExtractValue(CheckedLoad, 0);
VirtualFn = Builder.CreateBitCast(VirtualFn, FTy->getPointerTo(),
"memptr.virtualfn");
} else {
llvm::Value *AllVtables = llvm::MetadataAsValue::get(
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
CGF.EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIMFCall),
SanitizerHandler::CFICheckFail, StaticData,
{VTable, ValidVtable});
// When not doing VFE, emit a normal load, as it allows more
// optimisations than type.checked.load.
if (ShouldEmitCFICheck) {
CheckResult = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test),
{Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
}
VFPAddr =
Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo());
VirtualFn = Builder.CreateAlignedLoad(VFPAddr, CGF.getPointerAlign(),
"memptr.virtualfn");
}
assert(VirtualFn && "Virtual fuction pointer not created!");
assert((!ShouldEmitCFICheck || !ShouldEmitVFEInfo || CheckResult) &&
"Check result required but not created!");

if (ShouldEmitCFICheck) {
// If doing CFI, emit the check.
CheckSourceLocation = CGF.EmitCheckSourceLocation(E->getBeginLoc());
CheckTypeDesc = CGF.EmitCheckTypeDescriptor(QualType(MPT, 0));
llvm::Constant *StaticData[] = {
llvm::ConstantInt::get(CGF.Int8Ty, CodeGenFunction::CFITCK_VMFCall),
CheckSourceLocation,
CheckTypeDesc,
};

FnVirtual = Builder.GetInsertBlock();
}
if (CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIMFCall)) {
CGF.EmitTrapCheck(CheckResult);
} else {
llvm::Value *AllVtables = llvm::MetadataAsValue::get(
CGM.getLLVMContext(),
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
CGF.EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIMFCall),
SanitizerHandler::CFICheckFail, StaticData,
{VTable, ValidVtable});
}

FnVirtual = Builder.GetInsertBlock();
}
} // End of sanitizer scope

// Load the virtual function to call.
VFPAddr = Builder.CreateBitCast(VFPAddr, FTy->getPointerTo()->getPointerTo());
llvm::Value *VirtualFn = Builder.CreateAlignedLoad(
VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn");
CGF.EmitBranch(FnEnd);

// In the non-virtual path, the function pointer is actually a
Expand Down Expand Up @@ -1634,7 +1669,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
EmitFundamentalRTTIDescriptors(RD);

if (!VTable->isDeclarationForLinker())
CGM.EmitVTableTypeMetadata(VTable, VTLayout);
CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
}

bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField(
Expand Down
27 changes: 24 additions & 3 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5505,9 +5505,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
}

bool WholeProgramVTables =
Args.hasFlag(options::OPT_fwhole_program_vtables,
options::OPT_fno_whole_program_vtables, false);
bool VirtualFunctionElimination =
Args.hasFlag(options::OPT_fvirtual_function_elimination,
options::OPT_fno_virtual_function_elimination, false);
if (VirtualFunctionElimination) {
// VFE requires full LTO (currently, this might be relaxed to allow ThinLTO
// in the future).
if (D.getLTOMode() != LTOK_Full)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fvirtual-function-elimination"
<< "-flto=full";

CmdArgs.push_back("-fvirtual-function-elimination");
}

// VFE requires whole-program-vtables, and enables it by default.
bool WholeProgramVTables = Args.hasFlag(
options::OPT_fwhole_program_vtables,
options::OPT_fno_whole_program_vtables, VirtualFunctionElimination);
if (VirtualFunctionElimination && !WholeProgramVTables) {
D.Diag(diag::err_drv_argument_not_allowed_with)
<< "-fno-whole-program-vtables"
<< "-fvirtual-function-elimination";
}

if (WholeProgramVTables) {
if (!D.isUsingLTO())
D.Diag(diag::err_drv_argument_only_allowed_with)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CodeViewGHash = Args.hasArg(OPT_gcodeview_ghash);
Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
Opts.VirtualFunctionElimination =
Args.hasArg(OPT_fvirtual_function_elimination);
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
Opts.SplitDwarfOutput = Args.getLastArgValue(OPT_split_dwarf_output);
Expand Down
Loading

0 comments on commit 820f77c

Please sign in to comment.