Path: blob/main/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
213799 views
#include "CIRGenBuilder.h"1#include "CIRGenFunction.h"23#include "clang/AST/StmtVisitor.h"45using namespace clang;6using namespace clang::CIRGen;78namespace {9class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {10CIRGenFunction &cgf;11CIRGenBuilderTy &builder;1213public:14explicit ComplexExprEmitter(CIRGenFunction &cgf)15: cgf(cgf), builder(cgf.getBuilder()) {}1617//===--------------------------------------------------------------------===//18// Utilities19//===--------------------------------------------------------------------===//2021LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val);2223mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy);2425mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant,26Expr *e);2728/// Given an expression with complex type that represents a value l-value,29/// this method emits the address of the l-value, then loads and returns the30/// result.31mlir::Value emitLoadOfLValue(const Expr *e) {32return emitLoadOfLValue(cgf.emitLValue(e), e->getExprLoc());33}3435mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);36/// Store the specified real/imag parts into the37/// specified value pointer.38void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,39bool isInit);4041mlir::Value42VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);43mlir::Value VisitArraySubscriptExpr(Expr *e);44mlir::Value VisitBinAssign(const BinaryOperator *e);45mlir::Value VisitBinComma(const BinaryOperator *e);46mlir::Value VisitCallExpr(const CallExpr *e);47mlir::Value VisitCastExpr(CastExpr *e);48mlir::Value VisitChooseExpr(ChooseExpr *e);49mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e);50mlir::Value VisitDeclRefExpr(DeclRefExpr *e);51mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e);52mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);53mlir::Value VisitInitListExpr(const InitListExpr *e);54mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);55mlir::Value VisitParenExpr(ParenExpr *e);56mlir::Value57VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e);58mlir::Value VisitUnaryDeref(const Expr *e);5960struct BinOpInfo {61mlir::Location loc;62mlir::Value lhs{};63mlir::Value rhs{};64QualType ty{}; // Computation Type.65FPOptions fpFeatures{};66};6768BinOpInfo emitBinOps(const BinaryOperator *e,69QualType promotionTy = QualType());7071mlir::Value emitPromoted(const Expr *e, QualType promotionTy);7273mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy);7475mlir::Value emitBinAdd(const BinOpInfo &op);76mlir::Value emitBinSub(const BinOpInfo &op);7778QualType getPromotionType(QualType ty, bool isDivOpCode = false) {79if (auto *complexTy = ty->getAs<ComplexType>()) {80QualType elementTy = complexTy->getElementType();81if (isDivOpCode && elementTy->isFloatingType() &&82cgf.getLangOpts().getComplexRange() ==83LangOptions::ComplexRangeKind::CX_Promoted) {84cgf.cgm.errorNYI("HigherPrecisionTypeForComplexArithmetic");85return QualType();86}8788if (elementTy.UseExcessPrecision(cgf.getContext()))89return cgf.getContext().getComplexType(cgf.getContext().FloatTy);90}9192if (ty.UseExcessPrecision(cgf.getContext()))93return cgf.getContext().FloatTy;94return QualType();95}9697#define HANDLEBINOP(OP) \98mlir::Value VisitBin##OP(const BinaryOperator *e) { \99QualType promotionTy = getPromotionType( \100e->getType(), e->getOpcode() == BinaryOperatorKind::BO_Div); \101mlir::Value result = emitBin##OP(emitBinOps(e, promotionTy)); \102if (!promotionTy.isNull()) \103cgf.cgm.errorNYI("Binop emitUnPromotedValue"); \104return result; \105}106107HANDLEBINOP(Add)108HANDLEBINOP(Sub)109#undef HANDLEBINOP110};111} // namespace112113static const ComplexType *getComplexType(QualType type) {114type = type.getCanonicalType();115if (const ComplexType *comp = dyn_cast<ComplexType>(type))116return comp;117return cast<ComplexType>(cast<AtomicType>(type)->getValueType());118}119120LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,121mlir::Value &value) {122assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),123e->getRHS()->getType()) &&124"Invalid assignment");125126// Emit the RHS. __block variables need the RHS evaluated first.127value = Visit(e->getRHS());128129// Compute the address to store into.130LValue lhs = cgf.emitLValue(e->getLHS());131132// Store the result value into the LHS lvalue.133emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false);134return lhs;135}136137mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,138QualType destTy) {139switch (ck) {140case CK_NoOp:141case CK_LValueToRValue:142return Visit(op);143default:144break;145}146cgf.cgm.errorNYI("ComplexType Cast");147return {};148}149150mlir::Value ComplexExprEmitter::emitConstant(151const CIRGenFunction::ConstantEmission &constant, Expr *e) {152assert(constant && "not a constant");153if (constant.isReference())154return emitLoadOfLValue(constant.getReferenceLValue(cgf, e),155e->getExprLoc());156157mlir::TypedAttr valueAttr = constant.getValue();158return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr);159}160161mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv,162SourceLocation loc) {163assert(lv.isSimple() && "non-simple complex l-value?");164if (lv.getType()->isAtomicType())165cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV");166167const Address srcAddr = lv.getAddress();168return builder.createLoad(cgf.getLoc(loc), srcAddr);169}170171void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,172LValue lv, bool isInit) {173if (lv.getType()->isAtomicType() ||174(!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) {175cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV");176return;177}178179const Address destAddr = lv.getAddress();180builder.createStore(loc, val, destAddr);181}182183mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(184const AbstractConditionalOperator *e) {185mlir::Value condValue = Visit(e->getCond());186mlir::Location loc = cgf.getLoc(e->getSourceRange());187188return builder189.create<cir::TernaryOp>(190loc, condValue,191/*thenBuilder=*/192[&](mlir::OpBuilder &b, mlir::Location loc) {193mlir::Value trueValue = Visit(e->getTrueExpr());194b.create<cir::YieldOp>(loc, trueValue);195},196/*elseBuilder=*/197[&](mlir::OpBuilder &b, mlir::Location loc) {198mlir::Value falseValue = Visit(e->getFalseExpr());199b.create<cir::YieldOp>(loc, falseValue);200})201.getResult();202}203204mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) {205return emitLoadOfLValue(e);206}207208mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) {209mlir::Value value;210LValue lv = emitBinAssignLValue(e, value);211212// The result of an assignment in C is the assigned r-value.213if (!cgf.getLangOpts().CPlusPlus)214return value;215216// If the lvalue is non-volatile, return the computed value of the217// assignment.218if (!lv.isVolatile())219return value;220221return emitLoadOfLValue(lv, e->getExprLoc());222}223224mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) {225cgf.emitIgnoredExpr(e->getLHS());226return Visit(e->getRHS());227}228229mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {230if (e->getCallReturnType(cgf.getContext())->isReferenceType())231return emitLoadOfLValue(e);232233return cgf.emitCallExpr(e).getValue();234}235236mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) {237if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) {238// Bind VLAs in the cast type.239if (ece->getType()->isVariablyModifiedType()) {240cgf.cgm.errorNYI("VisitCastExpr Bind VLAs in the cast type");241return {};242}243}244245if (e->changesVolatileQualification())246return emitLoadOfLValue(e);247248return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());249}250251mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) {252return Visit(e->getChosenSubExpr());253}254255mlir::Value256ComplexExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {257mlir::Location loc = cgf.getLoc(e->getExprLoc());258mlir::Type complexTy = cgf.convertType(e->getType());259return builder.getNullValue(complexTy, loc);260}261262mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {263if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))264return emitConstant(constant, e);265return emitLoadOfLValue(e);266}267268mlir::Value269ComplexExprEmitter::VisitGenericSelectionExpr(GenericSelectionExpr *e) {270return Visit(e->getResultExpr());271}272273mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) {274// Unlike for scalars, we don't have to worry about function->ptr demotion275// here.276if (e->changesVolatileQualification())277return emitLoadOfLValue(e);278return emitCast(e->getCastKind(), e->getSubExpr(), e->getType());279}280281mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {282mlir::Location loc = cgf.getLoc(e->getExprLoc());283if (e->getNumInits() == 2) {284mlir::Value real = cgf.emitScalarExpr(e->getInit(0));285mlir::Value imag = cgf.emitScalarExpr(e->getInit(1));286return builder.createComplexCreate(loc, real, imag);287}288289if (e->getNumInits() == 1) {290cgf.cgm.errorNYI("Create Complex with InitList with size 1");291return {};292}293294assert(e->getNumInits() == 0 && "Unexpected number of inits");295mlir::Type complexTy = cgf.convertType(e->getType());296return builder.getNullValue(complexTy, loc);297}298299mlir::Value300ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) {301auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType()));302mlir::Type elementTy = ty.getElementType();303mlir::Location loc = cgf.getLoc(il->getExprLoc());304305mlir::TypedAttr realValueAttr;306mlir::TypedAttr imagValueAttr;307308if (mlir::isa<cir::IntType>(elementTy)) {309llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue();310realValueAttr = cir::IntAttr::get(elementTy, 0);311imagValueAttr = cir::IntAttr::get(elementTy, imagValue);312} else {313assert(mlir::isa<cir::FPTypeInterface>(elementTy) &&314"Expected complex element type to be floating-point");315316llvm::APFloat imagValue =317cast<FloatingLiteral>(il->getSubExpr())->getValue();318realValueAttr = cir::FPAttr::get(319elementTy, llvm::APFloat::getZero(imagValue.getSemantics()));320imagValueAttr = cir::FPAttr::get(elementTy, imagValue);321}322323auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr);324return builder.create<cir::ConstantOp>(loc, complexAttr);325}326327mlir::Value ComplexExprEmitter::VisitParenExpr(ParenExpr *e) {328return Visit(e->getSubExpr());329}330331mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr(332SubstNonTypeTemplateParmExpr *e) {333return Visit(e->getReplacement());334}335336mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {337return emitLoadOfLValue(e);338}339340mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,341QualType promotionTy) {342e = e->IgnoreParens();343if (const auto *bo = dyn_cast<BinaryOperator>(e)) {344switch (bo->getOpcode()) {345#define HANDLE_BINOP(OP) \346case BO_##OP: \347return emitBin##OP(emitBinOps(bo, promotionTy));348HANDLE_BINOP(Add)349HANDLE_BINOP(Sub)350#undef HANDLE_BINOP351default:352break;353}354} else if (isa<UnaryOperator>(e)) {355cgf.cgm.errorNYI("emitPromoted UnaryOperator");356return {};357}358359mlir::Value result = Visit(const_cast<Expr *>(e));360if (!promotionTy.isNull())361cgf.cgm.errorNYI("emitPromoted emitPromotedValue");362363return result;364}365366mlir::Value367ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e,368QualType promotionTy) {369if (e->getType()->isAnyComplexType()) {370if (!promotionTy.isNull())371return cgf.emitPromotedComplexExpr(e, promotionTy);372return Visit(const_cast<Expr *>(e));373}374375cgf.cgm.errorNYI("emitPromotedComplexOperand non-complex type");376return {};377}378379ComplexExprEmitter::BinOpInfo380ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {381BinOpInfo binOpInfo{cgf.getLoc(e->getExprLoc())};382binOpInfo.lhs = emitPromotedComplexOperand(e->getLHS(), promotionTy);383binOpInfo.rhs = emitPromotedComplexOperand(e->getRHS(), promotionTy);384binOpInfo.ty = promotionTy.isNull() ? e->getType() : promotionTy;385binOpInfo.fpFeatures = e->getFPFeaturesInEffect(cgf.getLangOpts());386return binOpInfo;387}388389mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) {390assert(!cir::MissingFeatures::fastMathFlags());391assert(!cir::MissingFeatures::cgFPOptionsRAII());392return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs);393}394395mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) {396assert(!cir::MissingFeatures::fastMathFlags());397assert(!cir::MissingFeatures::cgFPOptionsRAII());398return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs);399}400401LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {402assert(e->getOpcode() == BO_Assign && "Expected assign op");403404mlir::Value value; // ignored405LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);406if (getLangOpts().OpenMP)407cgm.errorNYI("emitComplexAssignmentLValue OpenMP");408409return lvalue;410}411412mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {413assert(e && getComplexType(e->getType()) &&414"Invalid complex expression to emit");415416return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e));417}418419void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,420LValue dest, bool isInit) {421ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit);422}423424mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,425QualType promotionType) {426return ComplexExprEmitter(*this).emitPromoted(e, promotionType);427}428429430