@@ -25,6 +25,147 @@ using namespace clang;
2525using namespace clang ::CIRGen;
2626using namespace cir ;
2727
28+ // / Given an expression of pointer type, try to
29+ // / derive a more accurate bound on the alignment of the pointer.
30+ Address CIRGenFunction::emitPointerWithAlignment (const Expr *expr) {
31+ // We allow this with ObjC object pointers because of fragile ABIs.
32+ assert (expr->getType ()->isPointerType () ||
33+ expr->getType ()->isObjCObjectPointerType ());
34+ expr = expr->IgnoreParens ();
35+
36+ // Casts:
37+ if (auto const *ce = dyn_cast<CastExpr>(expr)) {
38+ if (auto const *ece = dyn_cast<ExplicitCastExpr>(ce)) {
39+ cgm.errorNYI (expr->getSourceRange (),
40+ " emitPointerWithAlignment: explicit cast" );
41+ return Address::invalid ();
42+ }
43+
44+ switch (ce->getCastKind ()) {
45+ // Non-converting casts (but not C's implicit conversion from void*).
46+ case CK_BitCast:
47+ case CK_NoOp:
48+ case CK_AddressSpaceConversion: {
49+ cgm.errorNYI (expr->getSourceRange (),
50+ " emitPointerWithAlignment: noop cast" );
51+ return Address::invalid ();
52+ } break ;
53+
54+ // Array-to-pointer decay. TODO(cir): BaseInfo and TBAAInfo.
55+ case CK_ArrayToPointerDecay: {
56+ cgm.errorNYI (expr->getSourceRange (),
57+ " emitPointerWithAlignment: array-to-pointer decay" );
58+ return Address::invalid ();
59+ }
60+
61+ case CK_UncheckedDerivedToBase:
62+ case CK_DerivedToBase: {
63+ cgm.errorNYI (expr->getSourceRange (),
64+ " emitPointerWithAlignment: derived-to-base cast" );
65+ return Address::invalid ();
66+ }
67+
68+ case CK_AnyPointerToBlockPointerCast:
69+ case CK_BaseToDerived:
70+ case CK_BaseToDerivedMemberPointer:
71+ case CK_BlockPointerToObjCPointerCast:
72+ case CK_BuiltinFnToFnPtr:
73+ case CK_CPointerToObjCPointerCast:
74+ case CK_DerivedToBaseMemberPointer:
75+ case CK_Dynamic:
76+ case CK_FunctionToPointerDecay:
77+ case CK_IntegralToPointer:
78+ case CK_LValueToRValue:
79+ case CK_LValueToRValueBitCast:
80+ case CK_NullToMemberPointer:
81+ case CK_NullToPointer:
82+ case CK_ReinterpretMemberPointer:
83+ // Common pointer conversions, nothing to do here.
84+ // TODO: Is there any reason to treat base-to-derived conversions
85+ // specially?
86+ break ;
87+
88+ case CK_ARCConsumeObject:
89+ case CK_ARCExtendBlockObject:
90+ case CK_ARCProduceObject:
91+ case CK_ARCReclaimReturnedObject:
92+ case CK_AtomicToNonAtomic:
93+ case CK_BooleanToSignedIntegral:
94+ case CK_ConstructorConversion:
95+ case CK_CopyAndAutoreleaseBlockObject:
96+ case CK_Dependent:
97+ case CK_FixedPointCast:
98+ case CK_FixedPointToBoolean:
99+ case CK_FixedPointToFloating:
100+ case CK_FixedPointToIntegral:
101+ case CK_FloatingCast:
102+ case CK_FloatingComplexCast:
103+ case CK_FloatingComplexToBoolean:
104+ case CK_FloatingComplexToIntegralComplex:
105+ case CK_FloatingComplexToReal:
106+ case CK_FloatingRealToComplex:
107+ case CK_FloatingToBoolean:
108+ case CK_FloatingToFixedPoint:
109+ case CK_FloatingToIntegral:
110+ case CK_HLSLAggregateSplatCast:
111+ case CK_HLSLArrayRValue:
112+ case CK_HLSLElementwiseCast:
113+ case CK_HLSLVectorTruncation:
114+ case CK_IntToOCLSampler:
115+ case CK_IntegralCast:
116+ case CK_IntegralComplexCast:
117+ case CK_IntegralComplexToBoolean:
118+ case CK_IntegralComplexToFloatingComplex:
119+ case CK_IntegralComplexToReal:
120+ case CK_IntegralRealToComplex:
121+ case CK_IntegralToBoolean:
122+ case CK_IntegralToFixedPoint:
123+ case CK_IntegralToFloating:
124+ case CK_LValueBitCast:
125+ case CK_MatrixCast:
126+ case CK_MemberPointerToBoolean:
127+ case CK_NonAtomicToAtomic:
128+ case CK_ObjCObjectLValueCast:
129+ case CK_PointerToBoolean:
130+ case CK_PointerToIntegral:
131+ case CK_ToUnion:
132+ case CK_ToVoid:
133+ case CK_UserDefinedConversion:
134+ case CK_VectorSplat:
135+ case CK_ZeroToOCLOpaqueType:
136+ llvm_unreachable (" unexpected cast for emitPointerWithAlignment" );
137+ }
138+ }
139+
140+ // Unary &
141+ if (const UnaryOperator *uo = dyn_cast<UnaryOperator>(expr)) {
142+ // TODO(cir): maybe we should use cir.unary for pointers here instead.
143+ if (uo->getOpcode () == UO_AddrOf) {
144+ cgm.errorNYI (expr->getSourceRange (), " emitPointerWithAlignment: unary &" );
145+ return Address::invalid ();
146+ }
147+ }
148+
149+ // std::addressof and variants.
150+ if (auto const *call = dyn_cast<CallExpr>(expr)) {
151+ switch (call->getBuiltinCallee ()) {
152+ default :
153+ break ;
154+ case Builtin::BIaddressof:
155+ case Builtin::BI__addressof:
156+ case Builtin::BI__builtin_addressof: {
157+ cgm.errorNYI (expr->getSourceRange (),
158+ " emitPointerWithAlignment: builtin addressof" );
159+ return Address::invalid ();
160+ }
161+ }
162+ }
163+
164+ // Otherwise, use the alignment of the type.
165+ return makeNaturalAddressForPointer (
166+ emitScalarExpr (expr), expr->getType ()->getPointeeType (), CharUnits ());
167+ }
168+
28169void CIRGenFunction::emitStoreThroughLValue (RValue src, LValue dst,
29170 bool isInit) {
30171 if (!dst.isSimple ()) {
@@ -193,8 +334,25 @@ LValue CIRGenFunction::emitUnaryOpLValue(const UnaryOperator *e) {
193334
194335 switch (op) {
195336 case UO_Deref: {
196- cgm.errorNYI (e->getSourceRange (), " UnaryOp dereference" );
197- return LValue ();
337+ QualType t = e->getSubExpr ()->getType ()->getPointeeType ();
338+ assert (!t.isNull () && " CodeGenFunction::EmitUnaryOpLValue: Illegal type" );
339+
340+ assert (!cir::MissingFeatures::lvalueBaseInfo ());
341+ assert (!cir::MissingFeatures::opTBAA ());
342+ Address addr = emitPointerWithAlignment (e->getSubExpr ());
343+
344+ // Tag 'load' with deref attribute.
345+ // FIXME: This misses some derefence cases and has problematic interactions
346+ // with other operators.
347+ if (auto loadOp =
348+ dyn_cast<cir::LoadOp>(addr.getPointer ().getDefiningOp ())) {
349+ loadOp.setIsDerefAttr (mlir::UnitAttr::get (&getMLIRContext ()));
350+ }
351+
352+ LValue lv = LValue::makeAddr (addr, t);
353+ assert (!cir::MissingFeatures::addressSpace ());
354+ assert (!cir::MissingFeatures::setNonGC ());
355+ return lv;
198356 }
199357 case UO_Real:
200358 case UO_Imag: {
0 commit comments