diff options
| author | Yong He <yonghe@outlook.com> | 2022-08-04 14:05:02 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-04 14:05:02 -0700 |
| commit | 11b29eff99910d55a54658b8a1d053cc4ec076fc (patch) | |
| tree | ac82bef698df94f74a788cdc160dfd30472fb601 /source/slang | |
| parent | e43ef82e288afe486f45ef2736d378e88f40cc90 (diff) | |
Implicit pointer dereference when using member operator. (#2348)
* Implicit pointer dereference when using member operator.
* Add expected test result
* Fix lookup.
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/core.meta.slang | 28 | ||||
| -rw-r--r-- | source/slang/slang-ast-support-types.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 12 | ||||
| -rw-r--r-- | source/slang/slang-check-impl.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-check-overload.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-check-type.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-emit-c-like.cpp | 31 | ||||
| -rw-r--r-- | source/slang/slang-lookup.cpp | 27 |
8 files changed, 78 insertions, 42 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 1991eb583..862595b90 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -358,23 +358,6 @@ __magic_type(PtrType) __intrinsic_type($(kIROp_PtrType)) struct Ptr { - __intrinsic_op($(kIROp_Load)) - static T __load(Ptr<T> ptr); - - __intrinsic_op($(kIROp_Store)) - static void __store(Ptr<T> ptr, T val); - - __intrinsic_op($(kIROp_getElementPtr)) - static Ptr<T> __getElementPtr(Ptr<T> ptr, int index); - - __intrinsic_op($(kIROp_Neq)) - __generic<U:__BuiltinArithmeticType> - static bool __neq(Ptr<T> ptr, U val); - - __intrinsic_op($(kIROp_Eql)) - __generic<U:__BuiltinArithmeticType> - static bool __eql(Ptr<T> ptr, U val); - __generic<U> __intrinsic_op($(kIROp_BitCast)) __init(Ptr<U> ptr); @@ -404,6 +387,15 @@ struct Ptr } }; +__intrinsic_op($(kIROp_Load)) +T __load<T>(Ptr<T> ptr); + +__intrinsic_op($(kIROp_Store)) +void __store<T>(Ptr<T> ptr, T val); + +__intrinsic_op($(kIROp_getElementPtr)) +Ptr<T> __getElementPtr<T>(Ptr<T> ptr, int index); + __generic<T> __intrinsic_op($(kIROp_Less)) bool operator<(Ptr<T> p1, Ptr<T> p2); @@ -1726,7 +1718,7 @@ __generic<T> [__unsafeForceInlineEarly] Ptr<T> operator-(Ptr<T> value, int64_t offset) { - return Ptr<T>.__getElementPtr(value, -offset); + return __getElementPtr(value, -offset); } __generic<T : __BuiltinArithmeticType> diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index 3c161877c..f74abc08f 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -1121,6 +1121,7 @@ namespace Slang None = 0, IgnoreBaseInterfaces = 1 << 0, Completion = 1 << 1, ///< Lookup all applicable decls for code completion suggestions + NoDeref = 1 << 2, }; class SerialRefObject; diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index addd3a5c4..b7f99c4e7 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -382,15 +382,15 @@ namespace Slang Expr* base, SourceLoc loc) { - auto ptrLikeType = as<PointerLikeType>(base->type); - SLANG_ASSERT(ptrLikeType); + auto elementType = getPointedToTypeIfCanImplicitDeref(base->type); + SLANG_ASSERT(elementType); auto derefExpr = m_astBuilder->create<DerefExpr>(); derefExpr->loc = loc; derefExpr->base = base; - derefExpr->type = QualType(ptrLikeType->elementType); + derefExpr->type = QualType(elementType); - // TODO(tfoley): handle l-value status here + derefExpr->type.isLeftValue = base->type.isLeftValue; return derefExpr; } @@ -1258,7 +1258,9 @@ namespace Slang m_astBuilder, this, name, - baseType); + baseType, + LookupMask::Default, + LookupOptions::NoDeref); if (!lookupResult.isValid()) { goto fail; diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index c7b3f432a..ebc6e05d5 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -21,6 +21,10 @@ namespace Slang TypeExp typeExp, DiagnosticSink* sink); + /// Get the element type if `type` is Ptr or PtrLike type, otherwise returns null. + /// Note: this currently does not include PtrTypeBase. + Type* getPointedToTypeIfCanImplicitDeref(Type* type); + // A flat representation of basic types (scalars, vectors and matrices) // that can be used as lookup key in caches enum class BasicTypeKey : uint16_t diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index abb049a84..879c49da0 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -1242,7 +1242,9 @@ namespace Slang m_astBuilder, this, getName("$init"), - type); + type, + LookupMask::Default, + LookupOptions::NoDeref); AddOverloadCandidates(initializers, context); } diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp index dc0d69f04..50bc55641 100644 --- a/source/slang/slang-check-type.cpp +++ b/source/slang/slang-check-type.cpp @@ -22,6 +22,19 @@ namespace Slang return typeOut.type; } + Type* getPointedToTypeIfCanImplicitDeref(Type* type) + { + if (auto ptrLike = as<PointerLikeType>(type)) + { + return ptrLike->getElementType(); + } + else if (auto ptrType = as<PtrType>(type)) + { + return ptrType->getValueType(); + } + return nullptr; + } + Expr* SemanticsVisitor::TranslateTypeNodeImpl(Expr* node) { if (!node) return nullptr; diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index b6540b5f1..226e29764 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -1291,20 +1291,39 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst) void CLikeSourceEmitter::emitDereferenceOperand(IRInst* inst, EmitOpInfo const& outerPrec) { + EmitOpInfo newOuterPrec = outerPrec; + if (doesTargetSupportPtrTypes()) { - // If `inst` is a variable, dereferencing it is equivalent to just - // emit its name. i.e. *&var ==> var. - // We apply this peep hole optimization here to reduce the clutter of - // resulting code. - if (inst->getOp() == kIROp_Var) + switch (inst->getOp()) { + case kIROp_Var: + // If `inst` is a variable, dereferencing it is equivalent to just + // emit its name. i.e. *&var ==> var. + // We apply this peep hole optimization here to reduce the clutter of + // resulting code. m_writer->emit(getName(inst)); return; + case kIROp_FieldAddress: + { + auto innerPrec = getInfo(EmitOp::Postfix); + bool innerNeedClose = maybeEmitParens(newOuterPrec, innerPrec); + auto ii = as<IRFieldAddress>(inst); + auto base = ii->getBase(); + if (isPtrToClassType(base->getDataType())) + emitDereferenceOperand(base, leftSide(newOuterPrec, innerPrec)); + else + emitOperand(base, leftSide(newOuterPrec, innerPrec)); + m_writer->emit("->"); + m_writer->emit(getName(ii->getField())); + maybeCloseParens(innerNeedClose); + return; + } + default: + break; } auto dereferencePrec = EmitOpInfo::get(EmitOp::Prefix); - EmitOpInfo newOuterPrec = outerPrec; bool needClose = maybeEmitParens(newOuterPrec, dereferencePrec); m_writer->emit("*"); emitOperand(inst, rightSide(newOuterPrec, dereferencePrec)); diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp index 8c69e2013..85924ab30 100644 --- a/source/slang/slang-lookup.cpp +++ b/source/slang/slang-lookup.cpp @@ -607,19 +607,22 @@ static void _lookUpMembersInSuperTypeImpl( { // If the type was pointer-like, then dereference it // automatically here. - if (auto pointerLikeType = as<PointerLikeType>(superType)) + if (((uint32_t)request.options & (uint32_t)LookupOptions::NoDeref) == 0) { - // Need to leave a breadcrumb to indicate that we - // did an implicit dereference here - BreadcrumbInfo derefBreacrumb; - derefBreacrumb.kind = LookupResultItem::Breadcrumb::Kind::Deref; - derefBreacrumb.prev = inBreadcrumbs; - - // Recursively perform lookup on the result of deref - _lookUpMembersInType( - astBuilder, - name, pointerLikeType->elementType, request, ioResult, &derefBreacrumb); - return; + if (auto pointerElementType = getPointedToTypeIfCanImplicitDeref(superType)) + { + // Need to leave a breadcrumb to indicate that we + // did an implicit dereference here + BreadcrumbInfo derefBreacrumb; + derefBreacrumb.kind = LookupResultItem::Breadcrumb::Kind::Deref; + derefBreacrumb.prev = inBreadcrumbs; + + // Recursively perform lookup on the result of deref + _lookUpMembersInType( + astBuilder, + name, pointerElementType, request, ioResult, &derefBreacrumb); + return; + } } // Default case: no dereference needed |
