summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2022-08-04 14:05:02 -0700
committerGitHub <noreply@github.com>2022-08-04 14:05:02 -0700
commit11b29eff99910d55a54658b8a1d053cc4ec076fc (patch)
treeac82bef698df94f74a788cdc160dfd30472fb601 /source
parente43ef82e288afe486f45ef2736d378e88f40cc90 (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')
-rw-r--r--source/slang/core.meta.slang28
-rw-r--r--source/slang/slang-ast-support-types.h1
-rw-r--r--source/slang/slang-check-expr.cpp12
-rw-r--r--source/slang/slang-check-impl.h4
-rw-r--r--source/slang/slang-check-overload.cpp4
-rw-r--r--source/slang/slang-check-type.cpp13
-rw-r--r--source/slang/slang-emit-c-like.cpp31
-rw-r--r--source/slang/slang-lookup.cpp27
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