@@ -634,6 +634,14 @@ CIRGenCallee CIRGenFunction::emitCallee(const clang::Expr *E) {
634634
635635mlir::Value CIRGenFunction::emitToMemory (mlir::Value Value, QualType Ty) {
636636 // Bool has a different representation in memory than in registers.
637+
638+ // ExtVectorBoolType: In ClangIR, ExtVectorBoolType is always represented
639+ // as an integer type (!cir.int<u, N>) throughout the IR, including both
640+ // in registers and in memory. This differs from traditional CodeGen where
641+ // it may exist as a vector type that needs conversion to integer for storage.
642+ // Since we use integer representation consistently, no conversion is needed.
643+ // See CIRGenTypes.cpp:675-683 for the type conversion logic.
644+
637645 return Value;
638646}
639647
@@ -653,18 +661,21 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr,
653661
654662 auto eltTy = addr.getElementType ();
655663 if (const auto *clangVecTy = ty->getAs <clang::VectorType>()) {
656- // Boolean vectors use `iN` as storage type.
664+ // Boolean vectors use `iN` as storage type. The type conversion in
665+ // CIRGenTypes::convertType (lines 675-683) returns an integer type for
666+ // ExtVectorBoolType, so eltTy is already an integer. Skip vector
667+ // optimizations for bool vectors since they're not actually vectors in CIR.
657668 if (clangVecTy->isExtVectorBoolType ()) {
658- llvm_unreachable (" isExtVectorBoolType NYI" );
659- }
660-
661- // Handle vectors of size 3 like size 4 for better performance.
662- const auto vTy = cast<cir::VectorType>(eltTy);
663- auto newVecTy =
664- CGM.getABIInfo ().getOptimalVectorMemoryType (vTy, getLangOpts ());
669+ // Storage is already an integer type, nothing special needed
670+ } else {
671+ // Handle vectors of size 3 like size 4 for better performance.
672+ const auto vTy = cast<cir::VectorType>(eltTy);
673+ auto newVecTy =
674+ CGM.getABIInfo ().getOptimalVectorMemoryType (vTy, getLangOpts ());
665675
666- if (vTy != newVecTy) {
667- llvm_unreachable (" NYI" );
676+ if (vTy != newVecTy) {
677+ llvm_unreachable (" NYI" );
678+ }
668679 }
669680 }
670681
@@ -868,6 +879,16 @@ void CIRGenFunction::emitStoreThroughLValue(RValue Src, LValue Dst,
868879 bool isInit) {
869880 if (!Dst.isSimple ()) {
870881 if (Dst.isVectorElt ()) {
882+ // Check if this is an ExtVectorBoolType element assignment
883+ QualType vectorType = Dst.getType ();
884+ if (const auto *vecTy = vectorType->getAs <clang::VectorType>()) {
885+ if (vecTy->isExtVectorBoolType ()) {
886+ llvm_unreachable (
887+ " NYI: ExtVectorBoolType element assignment (requires bit "
888+ " manipulation to set/clear individual bits in integer storage)" );
889+ }
890+ }
891+
871892 // Read/modify/write the vector, inserting the new element
872893 mlir::Location loc = Dst.getVectorPointer ().getLoc ();
873894 mlir::Value Vector = builder.createLoad (loc, Dst.getVectorAddress ());
@@ -2735,6 +2756,8 @@ LValue CIRGenFunction::emitLValue(const Expr *E) {
27352756 return emitStmtExprLValue (cast<StmtExpr>(E));
27362757 case Expr::ChooseExprClass:
27372758 return emitLValue (cast<ChooseExpr>(E)->getChosenSubExpr ());
2759+ case Expr::CXXTypeidExprClass:
2760+ return emitCXXTypeidLValue (cast<CXXTypeidExpr>(E));
27382761 }
27392762
27402763 llvm_unreachable (" NYI" );
@@ -2956,6 +2979,13 @@ mlir::Value CIRGenFunction::emitFromMemory(mlir::Value Value, QualType Ty) {
29562979 llvm_unreachable (" NIY" );
29572980 }
29582981
2982+ // ExtVectorBoolType: In ClangIR, ExtVectorBoolType is always represented
2983+ // as an integer type (!cir.int<u, N>) throughout the IR, including both
2984+ // in registers and in memory. This differs from traditional CodeGen where
2985+ // it may need truncation from storage type to value type. Since we use
2986+ // integer representation consistently, no conversion is needed.
2987+ // See CIRGenTypes.cpp:675-683 for the type conversion logic.
2988+
29592989 return Value;
29602990}
29612991
@@ -2977,24 +3007,27 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, bool isVolatile,
29773007 auto eltTy = addr.getElementType ();
29783008
29793009 if (const auto *clangVecTy = ty->getAs <clang::VectorType>()) {
2980- // Boolean vectors use `iN` as storage type.
3010+ // Boolean vectors use `iN` as storage type. The type conversion in
3011+ // CIRGenTypes::convertType (lines 675-683) returns an integer type for
3012+ // ExtVectorBoolType, so eltTy is already an integer. Skip vector
3013+ // optimizations for bool vectors since they're not actually vectors in CIR.
29813014 if (clangVecTy->isExtVectorBoolType ()) {
2982- llvm_unreachable ( " NYI " );
2983- }
2984-
2985- // Handle vectors of size 3 like size 4 for better performance.
2986- const auto vTy = cast<cir::VectorType>(eltTy);
2987- auto newVecTy =
2988- CGM. getABIInfo (). getOptimalVectorMemoryType (vTy, getLangOpts ());
2989-
2990- if (vTy != newVecTy) {
2991- const Address cast = addr. withElementType (builder, newVecTy );
2992- mlir::Value v = builder. createLoad (loc, cast, isVolatile );
2993- const uint64_t oldNumElements = vTy. getSize ( );
2994- SmallVector< int64_t , 16 > mask (oldNumElements );
2995- std::iota (mask. begin (), mask. end (), 0 );
2996- v = builder. createVecShuffle (loc, v, mask );
2997- return emitFromMemory (v, ty);
3015+ // Storage is already an integer type, nothing special needed
3016+ } else {
3017+ // Handle vectors of size 3 like size 4 for better performance.
3018+ const auto vTy = cast<cir::VectorType>(eltTy);
3019+ auto newVecTy =
3020+ CGM. getABIInfo (). getOptimalVectorMemoryType (vTy, getLangOpts ());
3021+
3022+ if (vTy != newVecTy) {
3023+ const Address cast = addr. withElementType (builder, newVecTy);
3024+ mlir::Value v = builder. createLoad (loc, cast, isVolatile );
3025+ const uint64_t oldNumElements = vTy. getSize ( );
3026+ SmallVector< int64_t , 16 > mask (oldNumElements );
3027+ std::iota ( mask. begin (), mask. end (), 0 );
3028+ v = builder. createVecShuffle (loc, v, mask );
3029+ return emitFromMemory ( v, ty );
3030+ }
29983031 }
29993032 }
30003033
@@ -3445,3 +3478,22 @@ RValue CIRGenFunction::emitPseudoObjectRValue(const PseudoObjectExpr *expr,
34453478LValue CIRGenFunction::emitPseudoObjectLValue (const PseudoObjectExpr *expr) {
34463479 return emitPseudoObjectExpr (*this , expr, true , AggValueSlot::ignored ()).lv ;
34473480}
3481+
3482+ LValue CIRGenFunction::emitCXXTypeidLValue (const CXXTypeidExpr *E) {
3483+ // Emit the typeid expression, which returns a pointer to the RTTI descriptor.
3484+ mlir::Value typeInfoPtr = emitCXXTypeidExpr (E);
3485+
3486+ // Cast the pointer to the actual type_info type for proper type safety.
3487+ auto typeInfoTy = convertTypeForMem (E->getType ());
3488+ auto typeInfoPtrTy = builder.getPointerTo (typeInfoTy);
3489+ typeInfoPtr = builder.createBitcast (getLoc (E->getSourceRange ()), typeInfoPtr,
3490+ typeInfoPtrTy);
3491+
3492+ // Create an LValue from the pointer with natural alignment.
3493+ // We use getTypeAlignInChars() which returns the natural alignment for the
3494+ // type_info type, matching traditional CodeGen's getNaturalTypeAlignment().
3495+ Address addr (typeInfoPtr, typeInfoTy,
3496+ getContext ().getTypeAlignInChars (E->getType ()));
3497+
3498+ return makeAddrLValue (addr, E->getType (), AlignmentSource::Decl);
3499+ }
0 commit comments