[clang] [CIR] Add binary operators (PR #132420)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 21 14:50:36 PDT 2025
================
@@ -558,8 +624,225 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return res;
}
+
+ BinOpInfo emitBinOps(const BinaryOperator *e,
+ QualType promotionType = QualType()) {
+ BinOpInfo result;
+ result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
+ result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
+ if (!promotionType.isNull())
+ result.fullType = promotionType;
+ else
+ result.fullType = e->getType();
+ result.compType = result.fullType;
+ if (const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
+ result.compType = vecType->getElementType();
+ }
+ result.opcode = e->getOpcode();
+ result.loc = e->getSourceRange();
+ // TODO(cir): Result.FPFeatures
+ assert(!cir::MissingFeatures::getFPFeaturesInEffect());
+ result.e = e;
+ return result;
+ }
+
+ mlir::Value emitMul(const BinOpInfo &ops);
+ mlir::Value emitDiv(const BinOpInfo &ops);
+ mlir::Value emitRem(const BinOpInfo &ops);
+ mlir::Value emitAdd(const BinOpInfo &ops);
+ mlir::Value emitSub(const BinOpInfo &ops);
+ mlir::Value emitShl(const BinOpInfo &ops);
+ mlir::Value emitShr(const BinOpInfo &ops);
+ mlir::Value emitAnd(const BinOpInfo &ops);
+ mlir::Value emitXor(const BinOpInfo &ops);
+ mlir::Value emitOr(const BinOpInfo &ops);
+
+ LValue emitCompoundAssignLValue(
+ const CompoundAssignOperator *e,
+ mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
+ mlir::Value &result);
+ mlir::Value
+ emitCompoundAssign(const CompoundAssignOperator *e,
+ mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
+
+ // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
+ // codegen.
+ QualType getPromotionType(QualType ty) {
+ if (ty->getAs<ComplexType>()) {
+ assert(!cir::MissingFeatures::complexType());
+ cgf.cgm.errorNYI("promotion to complex type");
+ return QualType();
+ }
+ if (ty.UseExcessPrecision(cgf.getContext())) {
+ if (ty->getAs<VectorType>()) {
+ assert(!cir::MissingFeatures::vectorType());
+ cgf.cgm.errorNYI("promotion to vector type");
+ return QualType();
+ }
+ return cgf.getContext().FloatTy;
+ }
+ return QualType();
+ }
+
+// Binary operators and binary compound assignment operators.
+#define HANDLEBINOP(OP) \
+ mlir::Value VisitBin##OP(const BinaryOperator *e) { \
+ QualType promotionTy = getPromotionType(e->getType()); \
+ auto result = emit##OP(emitBinOps(e, promotionTy)); \
+ if (result && !promotionTy.isNull()) \
+ result = emitUnPromotedValue(result, e->getType()); \
+ return result; \
+ } \
+ mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
+ return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
+ }
+
+ HANDLEBINOP(Mul)
+ HANDLEBINOP(Div)
+ HANDLEBINOP(Rem)
+ HANDLEBINOP(Add)
+ HANDLEBINOP(Sub)
+ HANDLEBINOP(Shl)
+ HANDLEBINOP(Shr)
+ HANDLEBINOP(And)
+ HANDLEBINOP(Xor)
+ HANDLEBINOP(Or)
+#undef HANDLEBINOP
};
+LValue ScalarExprEmitter::emitCompoundAssignLValue(
+ const CompoundAssignOperator *e,
+ mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &),
+ mlir::Value &result) {
+ QualType lhsTy = e->getLHS()->getType();
+ BinOpInfo opInfo;
+
+ if (e->getComputationResultType()->isAnyComplexType()) {
+ cgf.cgm.errorNYI(result.getLoc(), "complex lvalue assign");
+ return LValue();
+ }
+
+ // Emit the RHS first. __block variables need to have the rhs evaluated
+ // first, plus this should improve codegen a little.
+
+ QualType promotionTypeCR = getPromotionType(e->getComputationResultType());
+ if (promotionTypeCR.isNull())
+ promotionTypeCR = e->getComputationResultType();
+
+ QualType promotionTypeLHS = getPromotionType(e->getComputationLHSType());
+ QualType promotionTypeRHS = getPromotionType(e->getRHS()->getType());
+
+ if (!promotionTypeRHS.isNull())
+ opInfo.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionTypeRHS);
+ else
+ opInfo.rhs = Visit(e->getRHS());
+
+ opInfo.fullType = promotionTypeCR;
+ opInfo.compType = opInfo.fullType;
+ if (const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType)) {
+ opInfo.compType = vecType->getElementType();
+ }
+ opInfo.opcode = e->getOpcode();
+ opInfo.fpfeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());
+ opInfo.e = e;
+ opInfo.loc = e->getSourceRange();
+
+ // Load/convert the LHS
+ LValue lhsLV = cgf.emitLValue(e->getLHS());
+
+ if (lhsTy->getAs<AtomicType>()) {
+ cgf.cgm.errorNYI(result.getLoc(), "atomic lvalue assign");
+ return LValue();
+ }
+
+ opInfo.lhs = emitLoadOfLValue(lhsLV, e->getExprLoc());
+
+ CIRGenFunction::SourceLocRAIIObject sourceloc{
+ cgf, cgf.getLoc(e->getSourceRange())};
+ SourceLocation loc = e->getExprLoc();
+ if (!promotionTypeLHS.isNull())
+ opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS,
+ e->getExprLoc());
+ else
+ opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
+ e->getComputationLHSType(), loc);
+
+ // Expand the binary operator.
+ result = (this->*func)(opInfo);
+
+ // Convert the result back to the LHS type,
+ // potentially with Implicit Conversion sanitizer check.
+ result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc);
+ // ScalarConversionOpts(cgf.sanOpts));
+
+ // Store the result value into the LHS lvalue. Bit-fields are handled
+ // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
+ // 'An assignment expression has the value of the left operand after the
+ // assignment...'.
+ if (lhsLV.isBitField())
+ cgf.cgm.errorNYI(e->getSourceRange(), "store through bitfield lvalue");
+ else
+ cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
+
+ if (cgf.getLangOpts().OpenMP)
+ cgf.cgm.errorNYI(e->getSourceRange(), "openmp");
+
+ return lhsLV;
+}
+
+mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
+ QualType promotionType) {
+ e = e->IgnoreParens();
+ if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
+ switch (bo->getOpcode()) {
+#define HANDLE_BINOP(OP) \
+ case BO_##OP: \
+ return emit##OP(emitBinOps(bo, promotionType));
+ HANDLE_BINOP(Add)
+ HANDLE_BINOP(Sub)
+ HANDLE_BINOP(Mul)
+ HANDLE_BINOP(Div)
+#undef HANDLE_BINOP
+ default:
+ break;
+ }
+ } else if (isa<UnaryOperator>(e)) {
+ cgf.cgm.errorNYI(e->getSourceRange(), "unary operators");
+ return {};
+ }
+ mlir::Value result = Visit(const_cast<Expr *>(e));
+ if (result) {
+ if (!promotionType.isNull())
+ return emitPromotedValue(result, promotionType);
+ return emitUnPromotedValue(result, e->getType());
+ }
+ return result;
+}
+
+mlir::Value ScalarExprEmitter::emitCompoundAssign(
+ const CompoundAssignOperator *e,
+ mlir::Value (ScalarExprEmitter::*func)(const BinOpInfo &)) {
+
+ bool ignore = std::exchange(ignoreResultAssign, false);
----------------
andykaylor wrote:
Nice!
https://github.com/llvm/llvm-project/pull/132420
More information about the cfe-commits
mailing list