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