Commit 2cc470aa authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r355491:

------------------------------------------------------------------------
r355491 | hans | 2019-03-06 11:26:19 +0100 (Wed, 06 Mar 2019) | 9 lines

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
------------------------------------------------------------------------

llvm-svn: 355674
parent 76819754
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -257,6 +257,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;
+20 −0
Original line number Diff line number Diff line
@@ -600,6 +600,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
  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;
+5 −6
Original line number Diff line number Diff line
@@ -9821,13 +9821,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
      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);
  }

+9 −2
Original line number Diff line number Diff line
@@ -1821,8 +1821,15 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
  // (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;
+12 −3
Original line number Diff line number Diff line
@@ -383,11 +383,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
          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());
      }

Loading