samitolvanen updated this revision to Diff 383514. samitolvanen added a comment.
Addressed comments. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108479/new/ https://reviews.llvm.org/D108479 Files: clang/docs/LanguageExtensions.rst clang/include/clang/AST/APValue.h clang/include/clang/Basic/Builtins.def clang/lib/AST/APValue.cpp clang/lib/AST/ExprConstant.cpp clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGExprConstant.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp clang/test/CodeGen/builtin-addressof-nocfi.c clang/test/SemaCXX/builtins.cpp
Index: clang/test/SemaCXX/builtins.cpp =================================================================== --- clang/test/SemaCXX/builtins.cpp +++ clang/test/SemaCXX/builtins.cpp @@ -39,6 +39,14 @@ S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} } +namespace addressof_nocfi { + void a(void) {} + static_assert(__builtin_addressof_nocfi(a) == a, ""); + + struct S {} s; + static_assert(__builtin_addressof_nocfi(s) == &s, ""); +} + void no_ms_builtins() { __assume(1); // expected-error {{use of undeclared}} __noop(1); // expected-error {{use of undeclared}} Index: clang/test/CodeGen/builtin-addressof-nocfi.c =================================================================== --- /dev/null +++ clang/test/CodeGen/builtin-addressof-nocfi.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fsanitize=cfi-icall -o - %s | FileCheck %s + +#if !__has_builtin(__builtin_addressof_nocfi) +#error "missing __builtin_addressof_nocfi" +#endif + +void a(void) {} +void b(void) {} +void c(void (*p)(void)) { + p(); +} + +// CHECK: @e = constant void ()* no_cfi @a +void (*const e)(void) = __builtin_addressof_nocfi(a); +// CHECK: @f = global [2 x void ()*] [void ()* @b, void ()* no_cfi @b] +void (*f[])(void) = {b, __builtin_addressof_nocfi(b)}; + +void d(void) { + // CHECK: store void ()* no_cfi @b, void ()** %g + void (*g)(void) = __builtin_addressof_nocfi(b); + // CHECK: call void @c(void ()* no_cfi @a) + c(__builtin_addressof_nocfi(a)); + e(); + f[1](); + g(); +} Index: clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -66,7 +66,8 @@ case Builtin::BI__builtin_expect: case Builtin::BI__builtin_expect_with_probability: case Builtin::BI__builtin_assume_aligned: - case Builtin::BI__builtin_addressof: { + case Builtin::BI__builtin_addressof: + case Builtin::BI__builtin_addressof_nocfi: { // For __builtin_unpredictable, __builtin_expect, // __builtin_expect_with_probability and __builtin_assume_aligned, // just return the value of the subexpression. Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1749,6 +1749,7 @@ return ExprError(); break; case Builtin::BI__builtin_addressof: + case Builtin::BI__builtin_addressof_nocfi: if (SemaBuiltinAddressof(*this, TheCall)) return ExprError(); break; Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -1889,8 +1889,12 @@ if (D->hasAttr<WeakRefAttr>()) return CGM.GetWeakRefReference(D).getPointer(); - if (auto FD = dyn_cast<FunctionDecl>(D)) - return CGM.GetAddrOfFunction(FD); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + llvm::Constant *C = CGM.GetAddrOfFunction(FD); + if (base.isNoCFIValue()) + return llvm::NoCFIValue::get(cast<llvm::GlobalValue>(C)); + return C; + } if (auto VD = dyn_cast<VarDecl>(D)) { // We can never refer to a variable with local storage. Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -4439,6 +4439,9 @@ } case Builtin::BI__builtin_addressof: return RValue::get(EmitLValue(E->getArg(0)).getPointer(*this)); + case Builtin::BI__builtin_addressof_nocfi: + return RValue::get(llvm::NoCFIValue::get( + cast<GlobalValue>(EmitLValue(E->getArg(0)).getPointer(*this)))); case Builtin::BI__builtin_operator_new: return EmitBuiltinNewDeleteCall( E->getCallee()->getType()->castAs<FunctionProtoType>(), E, false); Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -8982,6 +8982,11 @@ switch (BuiltinOp) { case Builtin::BI__builtin_addressof: return evaluateLValue(E->getArg(0), Result); + case Builtin::BI__builtin_addressof_nocfi: + if (!evaluateLValue(E->getArg(0), Result)) + return false; + Result.Base.setNoCFIValue(true); + return true; case Builtin::BI__builtin_assume_aligned: { // We need to be very careful here because: if the pointer does not have the // asserted alignment, then the behavior is undefined, and undefined Index: clang/lib/AST/APValue.cpp =================================================================== --- clang/lib/AST/APValue.cpp +++ clang/lib/AST/APValue.cpp @@ -40,9 +40,10 @@ "Type is insufficiently aligned"); APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V) - : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {} + : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V, + false} {} APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V) - : Ptr(P), Local{I, V} {} + : Ptr(P), Local{I, V, false} {} APValue::LValueBase APValue::LValueBase::getDynamicAlloc(DynamicAllocLValue LV, QualType Type) { @@ -124,6 +125,15 @@ return QualType::getFromOpaquePtr(DynamicAllocType); } +bool APValue::LValueBase::isNoCFIValue() const { + return (is<const ValueDecl *>() ? Local.NoCFIValue : false); +} + +void APValue::LValueBase::setNoCFIValue(bool NoCFI) { + if (is<const ValueDecl *>()) + Local.NoCFIValue = NoCFI; +} + void APValue::LValueBase::Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(Ptr.getOpaqueValue()); if (is<TypeInfoLValue>() || is<DynamicAllocLValue>()) Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -1559,6 +1559,7 @@ // Clang builtins (not available in GCC). BUILTIN(__builtin_addressof, "v*v&", "nct") +BUILTIN(__builtin_addressof_nocfi, "v*v&", "nct") BUILTIN(__builtin_operator_new, "v*z", "tc") BUILTIN(__builtin_operator_delete, "vv*", "tn") BUILTIN(__builtin_char_memchr, "c*cC*iz", "n") Index: clang/include/clang/AST/APValue.h =================================================================== --- clang/include/clang/AST/APValue.h +++ clang/include/clang/AST/APValue.h @@ -176,6 +176,8 @@ unsigned getVersion() const; QualType getTypeInfoType() const; QualType getDynamicAllocType() const; + bool isNoCFIValue() const; + void setNoCFIValue(bool NoCFI); QualType getType() const; @@ -190,6 +192,7 @@ PtrTy Ptr; struct LocalState { unsigned CallIndex, Version; + bool NoCFIValue; }; union { LocalState Local; Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -2517,6 +2517,13 @@ return __builtin_addressof(value); } +``__builtin_addressof_nocfi`` +----------------------------- + +``__builtin_addressof_nocfi`` is similar to ``__builtin_addressof``, but +with ``-fsanitize=cfi``, when passed a function, it returns the address of +the function body instead of a pointer to the CFI jump table. + ``__builtin_operator_new`` and ``__builtin_operator_delete`` ------------------------------------------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits