2121#include " clang/AST/GlobalDecl.h"
2222#include " clang/Basic/Builtins.h"
2323#include " clang/CIR/Dialect/IR/CIRDialect.h"
24+ #include " clang/CIR/Dialect/IR/CIROpsEnums.h"
2425#include " clang/CIR/Dialect/IR/CIRTypes.h"
2526#include " llvm/Support/Casting.h"
2627#include " llvm/Support/ErrorHandling.h"
@@ -128,6 +129,7 @@ static Address buildPointerWithAlignment(const Expr *E,
128129 if (PtrTy->getPointeeType ()->isVoidType ())
129130 break ;
130131 assert (!UnimplementedFeature::tbaa ());
132+
131133 LValueBaseInfo InnerBaseInfo;
132134 Address Addr = CGF.buildPointerWithAlignment (
133135 CE->getSubExpr (), &InnerBaseInfo, IsKnownNonNull);
@@ -211,13 +213,78 @@ static Address buildPointerWithAlignment(const Expr *E,
211213 return Address (CGF.buildScalarExpr (E), Align);
212214}
213215
216+ // / Helper method to check if the underlying ABI is AAPCS
217+ static bool isAAPCS (const TargetInfo &TargetInfo) {
218+ return TargetInfo.getABI ().starts_with (" aapcs" );
219+ }
220+
221+ Address CIRGenFunction::getAddrOfField (LValue base, const FieldDecl *field,
222+ unsigned index) {
223+ if (index == 0 )
224+ return base.getAddress ();
225+
226+ auto loc = getLoc (field->getLocation ());
227+ auto fieldType = convertType (field->getType ());
228+ auto fieldPtr =
229+ mlir::cir::PointerType::get (getBuilder ().getContext (), fieldType);
230+ auto sea = getBuilder ().createGetMember (
231+ loc, fieldPtr, base.getPointer (), field->getName (), index);
232+
233+ return Address (sea, CharUnits::One ());
234+ }
235+
236+ static bool useVolatileForBitField (const CIRGenModule &cgm, LValue base,
237+ const CIRGenBitFieldInfo &info,
238+ const FieldDecl *field) {
239+ return isAAPCS (cgm.getTarget ()) && cgm.getCodeGenOpts ().AAPCSBitfieldWidth &&
240+ info.VolatileStorageSize != 0 &&
241+ field->getType ()
242+ .withCVRQualifiers (base.getVRQualifiers ())
243+ .isVolatileQualified ();
244+ }
245+
246+ LValue CIRGenFunction::buildLValueForBitField (LValue base,
247+ const FieldDecl *field) {
248+
249+ LValueBaseInfo BaseInfo = base.getBaseInfo ();
250+ const RecordDecl *rec = field->getParent ();
251+ auto &layout = CGM.getTypes ().getCIRGenRecordLayout (field->getParent ());
252+ auto &info = layout.getBitFieldInfo (field);
253+ auto useVolatile = useVolatileForBitField (CGM, base, info, field);
254+ unsigned Idx = layout.getCIRFieldNo (field);
255+
256+ if (useVolatile ||
257+ (IsInPreservedAIRegion ||
258+ (getDebugInfo () && rec->hasAttr <BPFPreserveAccessIndexAttr>()))) {
259+ llvm_unreachable (" NYI" );
260+ }
261+
262+ Address Addr = getAddrOfField (base, field, Idx);
263+
264+ const unsigned SS = useVolatile ? info.VolatileStorageSize : info.StorageSize ;
265+
266+ // Get the access type.
267+ mlir::Type FieldIntTy = builder.getUIntNTy (SS);
268+
269+ auto loc = getLoc (field->getLocation ());
270+ if (Addr.getElementType () != FieldIntTy)
271+ Addr = builder.createElementBitCast (loc, Addr, FieldIntTy);
272+
273+ QualType fieldType =
274+ field->getType ().withCVRQualifiers (base.getVRQualifiers ());
275+
276+ assert (!UnimplementedFeature::tbaa () && " NYI TBAA for bit fields" );
277+ LValueBaseInfo FieldBaseInfo (BaseInfo.getAlignmentSource ());
278+ return LValue::MakeBitfield (Addr, info, fieldType, FieldBaseInfo);
279+ }
280+
214281LValue CIRGenFunction::buildLValueForField (LValue base,
215282 const FieldDecl *field) {
283+
216284 LValueBaseInfo BaseInfo = base.getBaseInfo ();
217285
218- if (field->isBitField ()) {
219- llvm_unreachable (" NYI" );
220- }
286+ if (field->isBitField ())
287+ return buildLValueForBitField (base, field);
221288
222289 // Fields of may-alias structures are may-alais themselves.
223290 // FIXME: this hould get propagated down through anonymous structs and unions.
@@ -516,12 +583,55 @@ void CIRGenFunction::buildStoreOfScalar(mlir::Value value, LValue lvalue,
516583// / method emits the address of the lvalue, then loads the result as an rvalue,
517584// / returning the rvalue.
518585RValue CIRGenFunction::buildLoadOfLValue (LValue LV, SourceLocation Loc) {
519- assert (LV.isSimple () && " not implemented" );
520586 assert (!LV.getType ()->isFunctionType ());
521587 assert (!(LV.getType ()->isConstantMatrixType ()) && " not implemented" );
522588
523- // Everything needs a load.
524- return RValue::get (buildLoadOfScalar (LV, Loc));
589+ if (LV.isBitField ())
590+ return buildLoadOfBitfieldLValue (LV, Loc);
591+
592+ if (LV.isSimple ())
593+ return RValue::get (buildLoadOfScalar (LV, Loc));
594+ llvm_unreachable (" NYI" );
595+ }
596+
597+ RValue CIRGenFunction::buildLoadOfBitfieldLValue (LValue LV,
598+ SourceLocation Loc) {
599+ const CIRGenBitFieldInfo &Info = LV.getBitFieldInfo ();
600+
601+ // Get the output type.
602+ mlir::Type ResLTy = convertType (LV.getType ());
603+ Address Ptr = LV.getBitFieldAddress ();
604+ mlir::Value Val = builder.createLoad (getLoc (Loc), Ptr);
605+ auto ValWidth = Val.getType ().cast <IntType>().getWidth ();
606+
607+ bool UseVolatile = LV.isVolatileQualified () &&
608+ Info.VolatileStorageSize != 0 && isAAPCS (CGM.getTarget ());
609+ const unsigned Offset = UseVolatile ? Info.VolatileOffset : Info.Offset ;
610+ const unsigned StorageSize =
611+ UseVolatile ? Info.VolatileStorageSize : Info.StorageSize ;
612+
613+ if (Info.IsSigned ) {
614+ assert (static_cast <unsigned >(Offset + Info.Size ) <= StorageSize);
615+
616+ mlir::Type typ = builder.getSIntNTy (ValWidth);
617+ Val = builder.createIntCast (Val, typ);
618+
619+ unsigned HighBits = StorageSize - Offset - Info.Size ;
620+ if (HighBits)
621+ Val = builder.createShiftLeft (Val, HighBits);
622+ if (Offset + HighBits)
623+ Val = builder.createShiftRight (Val, Offset + HighBits);
624+ } else {
625+ if (Offset)
626+ Val = builder.createShiftRight (Val, Offset);
627+
628+ if (static_cast <unsigned >(Offset) + Info.Size < StorageSize)
629+ Val = builder.createAnd (Val,
630+ llvm::APInt::getLowBitsSet (ValWidth, Info.Size ));
631+ }
632+ Val = builder.createIntCast (Val, ResLTy);
633+ assert (!UnimplementedFeature::emitScalarRangeCheck () && " NYI" );
634+ return RValue::get (Val);
525635}
526636
527637void CIRGenFunction::buildStoreThroughLValue (RValue Src, LValue Dst) {
@@ -544,6 +654,81 @@ void CIRGenFunction::buildStoreThroughLValue(RValue Src, LValue Dst) {
544654 buildStoreOfScalar (Src.getScalarVal (), Dst);
545655}
546656
657+ void CIRGenFunction::buildStoreThroughBitfieldLValue (RValue Src, LValue Dst,
658+ mlir::Value &Result) {
659+ const CIRGenBitFieldInfo &Info = Dst.getBitFieldInfo ();
660+ mlir::Type ResLTy = getTypes ().convertTypeForMem (Dst.getType ());
661+ Address Ptr = Dst.getBitFieldAddress ();
662+
663+ // Get the source value, truncated to the width of the bit-field.
664+ mlir::Value SrcVal = Src.getScalarVal ();
665+
666+ // Cast the source to the storage type and shift it into place.
667+ SrcVal = builder.createIntCast (SrcVal, Ptr.getElementType ());
668+ auto SrcWidth = SrcVal.getType ().cast <IntType>().getWidth ();
669+ mlir::Value MaskedVal = SrcVal;
670+
671+ const bool UseVolatile =
672+ CGM.getCodeGenOpts ().AAPCSBitfieldWidth && Dst.isVolatileQualified () &&
673+ Info.VolatileStorageSize != 0 && isAAPCS (CGM.getTarget ());
674+ const unsigned StorageSize =
675+ UseVolatile ? Info.VolatileStorageSize : Info.StorageSize ;
676+ const unsigned Offset = UseVolatile ? Info.VolatileOffset : Info.Offset ;
677+ // See if there are other bits in the bitfield's storage we'll need to load
678+ // and mask together with source before storing.
679+ if (StorageSize != Info.Size ) {
680+ assert (StorageSize > Info.Size && " Invalid bitfield size." );
681+
682+ mlir::Value Val = buildLoadOfScalar (Dst, Dst.getPointer ().getLoc ());
683+
684+ // Mask the source value as needed.
685+ if (!hasBooleanRepresentation (Dst.getType ()))
686+ SrcVal = builder.createAnd (
687+ SrcVal, llvm::APInt::getLowBitsSet (SrcWidth, Info.Size ));
688+
689+ MaskedVal = SrcVal;
690+ if (Offset)
691+ SrcVal = builder.createShiftLeft (SrcVal, Offset);
692+
693+ // Mask out the original value.
694+ Val = builder.createAnd (
695+ Val, ~llvm::APInt::getBitsSet (SrcWidth, Offset, Offset + Info.Size ));
696+
697+ // Or together the unchanged values and the source value.
698+ SrcVal = builder.createOr (Val, SrcVal);
699+
700+ } else {
701+ // According to the AACPS:
702+ // When a volatile bit-field is written, and its container does not overlap
703+ // with any non-bit-field member, its container must be read exactly once
704+ // and written exactly once using the access width appropriate to the type
705+ // of the container. The two accesses are not atomic.
706+ llvm_unreachable (" volatile bit-field is not implemented for the AACPS" );
707+ }
708+
709+ // Write the new value back out.
710+ // TODO: constant matrix type, volatile, no init, non temporal, TBAA
711+ buildStoreOfScalar (SrcVal, Ptr, Dst.isVolatileQualified (), Dst.getType (),
712+ Dst.getBaseInfo (), false , false );
713+
714+ // Return the new value of the bit-field.
715+ mlir::Value ResultVal = MaskedVal;
716+ ResultVal = builder.createIntCast (ResultVal, ResLTy);
717+
718+ // Sign extend the value if needed.
719+ if (Info.IsSigned ) {
720+ assert (Info.Size <= StorageSize);
721+ unsigned HighBits = StorageSize - Info.Size ;
722+
723+ if (HighBits) {
724+ ResultVal = builder.createShiftLeft (ResultVal, HighBits);
725+ ResultVal = builder.createShiftRight (ResultVal, HighBits);
726+ }
727+ }
728+
729+ Result = buildFromMemory (ResultVal, Dst.getType ());
730+ }
731+
547732static LValue buildGlobalVarDeclLValue (CIRGenFunction &CGF, const Expr *E,
548733 const VarDecl *VD) {
549734 QualType T = E->getType ();
@@ -767,7 +952,13 @@ LValue CIRGenFunction::buildBinaryOperatorLValue(const BinaryOperator *E) {
767952 LValue LV = buildLValue (E->getLHS ());
768953
769954 SourceLocRAIIObject Loc{*this , getLoc (E->getSourceRange ())};
770- buildStoreThroughLValue (RV, LV);
955+ if (LV.isBitField ()) {
956+ mlir::Value result;
957+ buildStoreThroughBitfieldLValue (RV, LV, result);
958+ } else {
959+ buildStoreThroughLValue (RV, LV);
960+ }
961+
771962 assert (!getContext ().getLangOpts ().OpenMP &&
772963 " last priv cond not implemented" );
773964 return LV;
@@ -2203,6 +2394,13 @@ mlir::Value CIRGenFunction::buildAlloca(StringRef name, QualType ty,
22032394
22042395mlir::Value CIRGenFunction::buildLoadOfScalar (LValue lvalue,
22052396 SourceLocation Loc) {
2397+ return buildLoadOfScalar (lvalue.getAddress (), lvalue.isVolatile (),
2398+ lvalue.getType (), getLoc (Loc), lvalue.getBaseInfo (),
2399+ lvalue.isNontemporal ());
2400+ }
2401+
2402+ mlir::Value CIRGenFunction::buildLoadOfScalar (LValue lvalue,
2403+ mlir::Location Loc) {
22062404 return buildLoadOfScalar (lvalue.getAddress (), lvalue.isVolatile (),
22072405 lvalue.getType (), Loc, lvalue.getBaseInfo (),
22082406 lvalue.isNontemporal ());
@@ -2220,6 +2418,14 @@ mlir::Value CIRGenFunction::buildLoadOfScalar(Address Addr, bool Volatile,
22202418 QualType Ty, SourceLocation Loc,
22212419 LValueBaseInfo BaseInfo,
22222420 bool isNontemporal) {
2421+ return buildLoadOfScalar (Addr, Volatile, Ty, getLoc (Loc), BaseInfo,
2422+ isNontemporal);
2423+ }
2424+
2425+ mlir::Value CIRGenFunction::buildLoadOfScalar (Address Addr, bool Volatile,
2426+ QualType Ty, mlir::Location Loc,
2427+ LValueBaseInfo BaseInfo,
2428+ bool isNontemporal) {
22232429 // TODO(CIR): this has fallen out of sync with codegen
22242430
22252431 // Atomic operations have to be done on integral types
@@ -2229,15 +2435,14 @@ mlir::Value CIRGenFunction::buildLoadOfScalar(Address Addr, bool Volatile,
22292435 }
22302436
22312437 mlir::cir::LoadOp Load = builder.create <mlir::cir::LoadOp>(
2232- getLoc ( Loc) , Addr.getElementType (), Addr.getPointer ());
2438+ Loc, Addr.getElementType (), Addr.getPointer ());
22332439
22342440 if (isNontemporal) {
22352441 llvm_unreachable (" NYI" );
22362442 }
2237-
2238- // TODO: TBAA
2239-
2240- // TODO: buildScalarRangeCheck
2443+
2444+ assert (!UnimplementedFeature::tbaa () && " NYI" );
2445+ assert (!UnimplementedFeature::emitScalarRangeCheck () && " NYI" );
22412446
22422447 return buildFromMemory (Load, Ty);
22432448}
0 commit comments