Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dyno: implement opaque extern types #22707

Merged
merged 7 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler/passes/convert-uast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ struct Converter {
Type* convertClassType(const types::QualifiedType qt);
Type* convertCPtrType(const types::QualifiedType qt);
Type* convertEnumType(const types::QualifiedType qt);
Type* convertExternType(const types::QualifiedType qt);
Type* convertFunctionType(const types::QualifiedType qt);
Type* convertBasicClassType(const types::QualifiedType qt);
Type* convertRecordType(const types::QualifiedType qt);
Expand Down Expand Up @@ -3971,6 +3972,7 @@ Type* Converter::convertType(const types::QualifiedType qt) {
// declared types
case typetags::ClassType: return convertClassType(qt);
case typetags::EnumType: return convertEnumType(qt);
case typetags::ExternType: return convertExternType(qt);
case typetags::FunctionType: return convertFunctionType(qt);

case typetags::ArrayType: return dtUnknown;
Expand Down Expand Up @@ -4027,6 +4029,11 @@ Type* Converter::convertEnumType(const types::QualifiedType qt) {
return nullptr;
}

Type* Converter::convertExternType(const types::QualifiedType qt) {
INT_FATAL("not implemented yet");
return nullptr;
}

Type* Converter::convertFunctionType(const types::QualifiedType qt) {
INT_FATAL("not implemented yet");
return nullptr;
Expand Down
64 changes: 64 additions & 0 deletions frontend/include/chpl/types/ExternType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2021-2023 Hewlett Packard Enterprise Development LP
* Other additional copyright holders may be indicated within.
*
* The entirety of this work is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CHPL_TYPES_EXTERN_TYPE_H
#define CHPL_TYPES_EXTERN_TYPE_H

#include "chpl/types/Type.h"
#include "chpl/types/QualifiedType.h"

namespace chpl {
namespace types {

class ExternType final : public Type {
private:
UniqueString linkageName_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need to preserve both the linkage name and the Chapel name. If a user writes:

extern "helper_t" type helper;
writeln(helper:string);

Then I believe it should print "helper" (and does in production, fwiw).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a test that checks the stringify'd name of extern types would also be useful.

Copy link
Contributor Author

@DanilaFe DanilaFe Jul 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed this out of band, and Ben and I agreed that we can merge the PR as-is for the time being, and figure out how to keep the original name as part of the type later.

We don't want to show linkage names to the user instead of the Chapel type name, so this feature is important in the long term.

The reason this doesn't immediately work is that our type comparisons in canPass are based on pointer equality; however, if we were to store the ID or name of the variable that declared an opaque type in addition to the linkage name, two variables with distinct Chapel names but identical linkage names would not be the exact same type, and thus become incompatible. We don't want that. To address the issue, we probably want to do a deep comparison on types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also tracked here: #22711


ExternType(UniqueString linkageName)
: Type(typetags::ExternType), linkageName_(linkageName) {}

bool contentsMatchInner(const Type* other) const override {
const ExternType* rhs = (const ExternType*) other;
return linkageName_ == rhs->linkageName_;
}

void markUniqueStringsInner(Context* context) const override {
linkageName_.mark(context);
}

Genericity genericity() const override {
return CONCRETE;
}

static const owned<ExternType>& getExternType(Context* context,
UniqueString linkageName);

public:
virtual void stringify(std::ostream& ss,
chpl::StringifyKind stringKind) const override;

inline UniqueString linkageName() const { return linkageName_; }

static const ExternType* get(Context* context, UniqueString linkageName);
};

} // end namespace types
} // end namespace chpl

#endif
1 change: 1 addition & 0 deletions frontend/include/chpl/types/all-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "chpl/types/DomainType.h"
#include "chpl/types/EnumType.h"
#include "chpl/types/ErroneousType.h"
#include "chpl/types/ExternType.h"
#include "chpl/types/ImagType.h"
#include "chpl/types/IntType.h"
#include "chpl/types/NilType.h"
Expand Down
1 change: 1 addition & 0 deletions frontend/include/chpl/types/type-classes-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ TYPE_END_SUBCLASSES(BuiltinType)
TYPE_BEGIN_SUBCLASSES(DeclaredType)
TYPE_NODE(ClassType)
TYPE_NODE(EnumType)
TYPE_NODE(ExternType)
TYPE_NODE(FunctionType)

TYPE_BEGIN_SUBCLASSES(CompositeType)
Expand Down
19 changes: 18 additions & 1 deletion frontend/lib/resolution/Resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,23 @@ void Resolver::resolveNamedDecl(const NamedDecl* decl, const Type* useType) {
initExprT = r.type();
}

if (!typeExprT.hasTypePtr() && useType != nullptr) {
if (typeExpr == nullptr && initExpr == nullptr &&
var->linkage() == uast::Decl::EXTERN &&
var->storageKind() == QualifiedType::TYPE) {
// creating an opaque external type.

CHPL_ASSERT(var->isVariable());
auto linkageNameNode = var->linkageName();
CHPL_ASSERT(linkageNameNode == nullptr || linkageNameNode->isStringLiteral());

UniqueString linkageName = var->name();
if (linkageNameNode) {
linkageName = linkageNameNode->toStringLiteral()->value();
}
qtKind = QualifiedType::TYPE;
typePtr = ExternType::get(context, linkageName);
paramPtr = nullptr;
} else if (!typeExprT.hasTypePtr() && useType != nullptr) {
// use type from argument to resolveNamedDecl
typeExprT = QualifiedType(QualifiedType::TYPE, useType);
typePtr = typeExprT.type();
Expand All @@ -1258,6 +1274,7 @@ void Resolver::resolveNamedDecl(const NamedDecl* decl, const Type* useType) {
// However, a `this` formal lacks a type expression if it belongs to a
// primary method. This does not, however, mean that its type should be
// AnyType; it is not adjusted here.

typeExprT = QualifiedType(QualifiedType::TYPE, AnyType::get(context));
} else if (isFieldOrFormal) {
// figure out if we should potentially infer the type from the init expr
Expand Down
8 changes: 4 additions & 4 deletions frontend/lib/resolution/intents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ static QualifiedType::Kind constIntentForType(const Type* t) {
if (t == nullptr || t->isUnknownType() || t->isErroneousType())
return QualifiedType::UNKNOWN;

if (t->isPrimitiveType() || t->isEnumType() || t->isOpaqueType() ||
t->isTaskIdType() || t->isNilType() ||
if (t->isPrimitiveType() || t->isEnumType() || t->isExternType() ||
t->isOpaqueType() || t->isTaskIdType() || t->isNilType() ||
t->isCStringType() || t->isCVoidPtrType() || t->isCFnPtrType() ||
t->isNothingType() || t->isVoidType())
return QualifiedType::CONST_IN;
Expand Down Expand Up @@ -70,8 +70,8 @@ static QualifiedType::Kind defaultIntentForType(const Type* t,
if (t == nullptr || t->isUnknownType() || t->isErroneousType())
return QualifiedType::UNKNOWN;

if (t->isPrimitiveType() || t->isEnumType() || t->isOpaqueType() ||
t->isTaskIdType() || t->isNilType() ||
if (t->isPrimitiveType() || t->isEnumType() || t->isExternType() ||
t->isOpaqueType() || t->isTaskIdType() || t->isNilType() ||
t->isCStringType() || t->isCVoidPtrType() || t->isCPtrType() ||
t->isCFnPtrType() || t->isNothingType() || t->isVoidType())
return QualifiedType::CONST_IN;
Expand Down
1 change: 1 addition & 0 deletions frontend/lib/types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ target_sources(ChplFrontend-obj
DomainType.cpp
EnumType.cpp
ErroneousType.cpp
ExternType.cpp
ImagType.cpp
IntType.cpp
NilType.cpp
Expand Down
25 changes: 25 additions & 0 deletions frontend/lib/types/ExternType.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "chpl/types/ExternType.h"
#include "chpl/framework/query-impl.h"

namespace chpl {
namespace types {

const owned<ExternType>& ExternType::getExternType(Context* context,
UniqueString name) {
QUERY_BEGIN(getExternType, context, name);
auto result = toOwned(new ExternType(name));
return QUERY_END(result);
}

void ExternType::stringify(std::ostream& ss,
chpl::StringifyKind stringKind) const {
ss << "extern type ";
linkageName().stringify(ss, stringKind);
}

const ExternType* ExternType::get(Context* context, UniqueString linkageName) {
return getExternType(context, linkageName).get();
}

} // end namespace types
} // end namespace chpl
1 change: 1 addition & 0 deletions frontend/test/resolution/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ comp_unit_test(testMethodFieldAccess)
comp_unit_test(testModuleInitOrder)
comp_unit_test(testMultiDecl)
comp_unit_test(testNew)
comp_unit_test(testOpaqueExternTypes)
comp_unit_test(testOperatorOverloads)
comp_unit_test(testParamFolding)
comp_unit_test(testParamIf)
Expand Down
Loading