r355491 - Inline asm constraints: allow ICE-like pointers for the "n" constraint (PR40890)
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 8 01:15:39 PST 2019
Merged to release_80 in r355674.
On Wed, Mar 6, 2019 at 11:25 AM Hans Wennborg via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
>
> Author: hans
> Date: Wed Mar 6 02:26:19 2019
> New Revision: 355491
>
> URL: http://llvm.org/viewvc/llvm-project?rev=355491&view=rev
> Log:
> Inline asm constraints: allow ICE-like pointers for the "n" constraint (PR40890)
>
> Apparently GCC allows this, and there's code relying on it (see bug).
>
> The idea is to allow expression that would have been allowed if they
> were cast to int. So I based the code on how such a cast would be done
> (the CK_PointerToIntegral case in IntExprEvaluator::VisitCastExpr()).
>
> Differential Revision: https://reviews.llvm.org/D58821
>
> Modified:
> cfe/trunk/include/clang/AST/APValue.h
> cfe/trunk/lib/AST/APValue.cpp
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/CodeGen/CGStmt.cpp
> cfe/trunk/lib/Sema/SemaStmtAsm.cpp
> cfe/trunk/test/CodeGen/x86-64-inline-asm.c
> cfe/trunk/test/Sema/inline-asm-validate-x86.c
>
> Modified: cfe/trunk/include/clang/AST/APValue.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/APValue.h?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/APValue.h (original)
> +++ cfe/trunk/include/clang/AST/APValue.h Wed Mar 6 02:26:19 2019
> @@ -262,6 +262,12 @@ public:
> return const_cast<APValue*>(this)->getInt();
> }
>
> + /// Try to convert this value to an integral constant. This works if it's an
> + /// integer, null pointer, or offset from a null pointer. Returns true on
> + /// success.
> + bool toIntegralConstant(APSInt &Result, QualType SrcTy,
> + const ASTContext &Ctx) const;
> +
> APFloat &getFloat() {
> assert(isFloat() && "Invalid accessor");
> return *(APFloat*)(char*)Data.buffer;
>
> Modified: cfe/trunk/lib/AST/APValue.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/APValue.cpp?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/APValue.cpp (original)
> +++ cfe/trunk/lib/AST/APValue.cpp Wed Mar 6 02:26:19 2019
> @@ -614,6 +614,26 @@ std::string APValue::getAsString(ASTCont
> return Result;
> }
>
> +bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy,
> + const ASTContext &Ctx) const {
> + if (isInt()) {
> + Result = getInt();
> + return true;
> + }
> +
> + if (isLValue() && isNullPointer()) {
> + Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy);
> + return true;
> + }
> +
> + if (isLValue() && !getLValueBase()) {
> + Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy);
> + return true;
> + }
> +
> + return false;
> +}
> +
> const APValue::LValueBase APValue::getLValueBase() const {
> assert(isLValue() && "Invalid accessor");
> return ((const LV*)(const void*)Data.buffer)->Base;
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Mar 6 02:26:19 2019
> @@ -9872,13 +9872,12 @@ bool IntExprEvaluator::VisitCastExpr(con
> return true;
> }
>
> - uint64_t V;
> - if (LV.isNullPointer())
> - V = Info.Ctx.getTargetNullPointerValue(SrcType);
> - else
> - V = LV.getLValueOffset().getQuantity();
> + APSInt AsInt;
> + APValue V;
> + LV.moveInto(V);
> + if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx))
> + llvm_unreachable("Can't cast this!");
>
> - APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
> return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Wed Mar 6 02:26:19 2019
> @@ -1838,8 +1838,15 @@ llvm::Value* CodeGenFunction::EmitAsmInp
> // (immediate or symbolic), try to emit it as such.
> if (!Info.allowsRegister() && !Info.allowsMemory()) {
> if (Info.requiresImmediateConstant()) {
> - llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
> - return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
> + Expr::EvalResult EVResult;
> + InputExpr->EvaluateAsRValue(EVResult, getContext(), true);
> +
> + llvm::APSInt IntResult;
> + if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
> + getContext()))
> + llvm_unreachable("Invalid immediate constant!");
> +
> + return llvm::ConstantInt::get(getLLVMContext(), IntResult);
> }
>
> Expr::EvalResult Result;
>
> Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Wed Mar 6 02:26:19 2019
> @@ -385,11 +385,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
> return StmtError(
> Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
> << Info.getConstraintStr() << InputExpr->getSourceRange());
> - llvm::APSInt Result = EVResult.Val.getInt();
> - if (!Info.isValidAsmImmediate(Result))
> +
> + // For compatibility with GCC, we also allow pointers that would be
> + // integral constant expressions if they were cast to int.
> + llvm::APSInt IntResult;
> + if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
> + Context))
> + return StmtError(
> + Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
> + << Info.getConstraintStr() << InputExpr->getSourceRange());
> +
> + if (!Info.isValidAsmImmediate(IntResult))
> return StmtError(Diag(InputExpr->getBeginLoc(),
> diag::err_invalid_asm_value_for_constraint)
> - << Result.toString(10) << Info.getConstraintStr()
> + << IntResult.toString(10) << Info.getConstraintStr()
> << InputExpr->getSourceRange());
> }
>
>
> Modified: cfe/trunk/test/CodeGen/x86-64-inline-asm.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86-64-inline-asm.c?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGen/x86-64-inline-asm.c (original)
> +++ cfe/trunk/test/CodeGen/x86-64-inline-asm.c Wed Mar 6 02:26:19 2019
> @@ -1,6 +1,7 @@
> // REQUIRES: x86-registered-target
> // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -DWARN -verify
> // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -Werror -verify
> +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -S -o - | FileCheck %s
> void f() {
> asm("movaps %xmm3, (%esi, 2)");
> // expected-note at 1 {{instantiated into assembly here}}
> @@ -15,3 +16,17 @@ static unsigned var[1] = {};
> void g(void) { asm volatile("movd %%xmm0, %0"
> :
> : "m"(var)); }
> +
> +void pr40890(void) {
> + struct s {
> + int a, b;
> + } s;
> + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a));
> + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b));
> + __asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));
> +
> +// CHECK-LABEL: pr40890
> +// CHECK: #define S_A abcd$0
> +// CHECK: #define S_B abcd$4
> +// CHECK: #define BEEF abcd$244837814038255
> +}
>
> Modified: cfe/trunk/test/Sema/inline-asm-validate-x86.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/inline-asm-validate-x86.c?rev=355491&r1=355490&r2=355491&view=diff
> ==============================================================================
> --- cfe/trunk/test/Sema/inline-asm-validate-x86.c (original)
> +++ cfe/trunk/test/Sema/inline-asm-validate-x86.c Wed Mar 6 02:26:19 2019
> @@ -1,5 +1,5 @@
> // RUN: %clang_cc1 -triple i686 -fsyntax-only -verify %s
> -// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify %s
> +// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify -DAMD64 %s
>
> void I(int i, int j) {
> static const int BelowMin = -1;
> @@ -137,3 +137,21 @@ void O(int i, int j) {
> : "0"(i), "O"(64)); // expected-no-error
> }
>
> +void pr40890(void) {
> + struct s {
> + int a, b;
> + };
> + static struct s s;
> + // This null pointer can be used as an integer constant expression.
> + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a));
> + // This offset-from-null pointer can be used as an integer constant expression.
> + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b));
> + // This pointer cannot be used as an integer constant expression.
> + __asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}}
> + // Floating-point is also not okay.
> + __asm__ __volatile__("\n#define PI abcd%0\n" : : "n"(3.14f)); // expected-error{{constraint 'n' expects an integer constant expression}}
> +#ifdef AMD64
> + // This arbitrary pointer is fine.
> + __asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));
> +#endif
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list