Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/chapel-lang/chapel into rep…
Browse files Browse the repository at this point in the history
…licateddist

Fix some merges with Michael's removal of '(?)' from Replicated distributions
  • Loading branch information
bradcray committed Sep 13, 2023
2 parents 3dc870c + 6eb2f16 commit c6bb384
Show file tree
Hide file tree
Showing 268 changed files with 2,547 additions and 767 deletions.
9 changes: 4 additions & 5 deletions compiler/llvm/clangUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2666,6 +2666,10 @@ static std::string generateClangGpuLangArgs() {
args += " -lstdc++";
break;
}

if (gpuArches.size() >= 1) {
args += " " + std::string("--offload-arch=") + *gpuArches.begin();
}
}
return args;
}
Expand Down Expand Up @@ -2911,11 +2915,6 @@ void runClang(const char* just_parse_filename) {
// Need to select CUDA/AMD mode in embedded clang to
// activate the GPU target
splitStringWhitespace(generateClangGpuLangArgs(), clangOtherArgs);

if (gpuArches.size() >= 1) {
std::string archFlag = std::string("--offload-arch=") + *gpuArches.begin();
clangOtherArgs.push_back(archFlag);
}
}

// Always include sys_basic because it might change the
Expand Down
58 changes: 52 additions & 6 deletions compiler/passes/buildDefaultFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,9 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {
bool makeReadThisAndWriteThis = true;

bool hasSerialize = false;
bool hasDeserialize = false;
bool AnySerialize = false;
FnSymbol* readerInit = nullptr;

// Always build for 'object' to satisfy 'override' keyword in some cases.
bool makeSerialize = ct == dtObject || !fNoIOGenSerialization;
Expand All @@ -1889,16 +1892,49 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {
if (isArrayImplType(ct))
return;

if (functionExists("writeThis", dtMethodToken, ct, dtAny)) {
if (functionExists("deserialize", dtMethodToken, ct, dtAny, dtAny)) {
hasDeserialize = true;
}

if (functionExists("serialize", dtMethodToken, ct, dtAny, dtAny)) {
hasSerialize = true;
}

// TODO: should these say something about the type declared on?
if (FnSymbol* fn = functionExists("writeThis", dtMethodToken, ct, dtAny)) {
if (hasSerialize == false) {
USR_WARN(fn, "'writeThis' is deprecated. Please use 'serialize' methods instead.");
}
hasWriteThis = true;
}

if (functionExists("readThis", dtMethodToken, ct, dtAny)) {
if (FnSymbol* fn = functionExists("readThis", dtMethodToken, ct, dtAny)) {
if (hasDeserialize == false) {
USR_WARN(fn, "'readThis' is deprecated. Please use 'deserialize' methods instead.");
}
hasReadThis = true;
}

if (functionExists("serialize", dtMethodToken, ct, dtAny, dtAny)) {
hasSerialize = true;
forv_Vec(FnSymbol, method, ct->methods) {
if (method != nullptr &&
method->isInitializer() &&
method->numFormals() == 4 &&
strcmp(method->getFormal(3)->name, "reader") == 0 &&
strcmp(method->getFormal(4)->name, "deserializer") == 0) {
readerInit = method;
break;
}
}

if (hasSerialize || hasDeserialize ||
(readerInit != nullptr &&
readerInit->hasFlag(FLAG_COMPILER_GENERATED) == false &&
ct->getModule()->modTag != MOD_INTERNAL)) {
// If there's a user-defined 'serialize' method...
// Or a user-defined 'deserialize' method...
// Or a user-defined 'init'-deserializing method...
// Then do not generate anything (except for hinting compiler errors)
AnySerialize = true;
}

// We'll make a writeThis and a readThis if neither exist.
Expand Down Expand Up @@ -1944,6 +1980,9 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {
// TODO: we probably want to have a warning here to help users migrate
// their code to use formatters.
fn->insertAtTail(new CallExpr("writeThis", gMethodToken, fn->_this, fileArg));
} else if (AnySerialize) {
auto msg = new_StringSymbol("'serialize' methods are not compiler-generated when a type has a user-defined 'deserialize' method.");
fn->insertAtTail(new CallExpr("compilerError", msg));
} else {
fn->insertAtTail(new CallExpr("serializeDefaultImpl",
fileArg,
Expand Down Expand Up @@ -1971,8 +2010,7 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {
}

bool makeDeserialize = ct == dtObject || !fNoIOGenSerialization;
if (makeDeserialize &&
!functionExists("deserialize", dtMethodToken, ct, dtAny, dtAny)) {
if (makeDeserialize && !hasDeserialize) {
ArgSymbol* fileArg = NULL;
FnSymbol* fn = buildReadThisFnSymbol(ct, &fileArg, "deserialize");

Expand All @@ -1987,6 +2025,9 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {
gMethodToken,
fn->_this,
fileArg));
} else if (AnySerialize) {
auto msg = new_StringSymbol("'deserialize' methods are not compiler-generated when a type has a user-defined 'serialize' method.");
fn->insertAtTail(new CallExpr("compilerError", msg));
} else {
VarSymbol* temp = newTemp("_deser_temp");
fn->insertAtTail(new DefExpr(temp));
Expand All @@ -1999,6 +2040,11 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {

normalize(fn);
}

if (ct->builtReaderInit && AnySerialize && readerInit != nullptr) {
auto msg = new_StringSymbol("Initializers called by IO for deserialization are not compiler-generated when a user-defined 'serialize' or 'deserialize' method exists");
readerInit->insertAtHead(new CallExpr("compilerError", msg));
}
}


Expand Down
52 changes: 49 additions & 3 deletions compiler/passes/normalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static void normalizeCallToTypeConstructor(CallExpr* call);
static void applyGetterTransform(CallExpr* call);
static void transformIfVar(CallExpr* call);
static void insertCallTemps(CallExpr* call);
static void propagateMarkedGeneric(Symbol* var, Expr* typeExpr);
static Symbol* insertCallTempsWithStmt(CallExpr* call, Expr* stmt);

static void errorIfSplitInitializationRequired(DefExpr* def, Expr* cur);
Expand Down Expand Up @@ -1725,6 +1726,7 @@ static void addTypeBlocksForParentTypeOf(CallExpr* call) {
************************************** | *************************************/

static void fixupExportedArrayReturns(FnSymbol* fn);
static void fixupGenericReturnTypes(FnSymbol* fn);
static bool isVoidReturn(CallExpr* call);
static bool hasGenericArrayReturn(FnSymbol* fn);
static void insertRetMove(FnSymbol* fn, VarSymbol* retval, CallExpr* ret,
Expand All @@ -1736,6 +1738,7 @@ static void normalizeReturns(FnSymbol* fn) {
SET_LINENO(fn);

fixupExportedArrayReturns(fn);
fixupGenericReturnTypes(fn);

std::vector<CallExpr*> rets;
std::vector<CallExpr*> calls;
Expand Down Expand Up @@ -1911,6 +1914,32 @@ static void fixupExportedArrayReturns(FnSymbol* fn) {
}
}

// If the return type was declared generic e.g. as R(?), then
// mark the function with FLAG_RET_TYPE_MARKED_GENERIC.
// Also simplifies the simplest case to help with problems with
// proc f(): domain(?) { ... }
static void fixupGenericReturnTypes(FnSymbol* fn) {
if (fn->retExprType) {
// handle nested cases, e.g. (GenericRecord(?), ) or borrowed GenCls(?)
propagateMarkedGeneric(fn, fn->retExprType);

// simpify the simple case
Expr* tail = fn->retExprType->body.tail;
if (CallExpr* call = toCallExpr(tail)) {
if (call->numActuals() == 1) {
if (SymExpr* se = toSymExpr(call->get(1))) {
if (call->baseExpr && se->symbol() == gUninstantiated) {
Expr* type = call->baseExpr->remove();
tail->replace(type);
// flag should have been added in propagateMarkedGeneric
INT_ASSERT(fn->hasFlag(FLAG_RET_TYPE_MARKED_GENERIC));
}
}
}
}
}
}

static void normalizeYields(FnSymbol* fn) {
INT_ASSERT(fn->isIterator());
SET_LINENO(fn);
Expand Down Expand Up @@ -2485,15 +2514,18 @@ static void insertCallTemps(CallExpr* call) {
}
}

// adds FLAG_MARKED_GENERIC to 'var' if the type contains a ?
// adds FLAG_MARKED_GENERIC/FLAG_RET_TYPE_MARKED_GENERIC
// to 'var' if the type contains a ?
// actual or an actual that is a temp marked with that flag.
static void propagateMarkedGeneric(Symbol* var, Expr* typeExpr) {
if (SymExpr* se = toSymExpr(typeExpr)) {
Symbol* sym = se->symbol();
if (sym == gUninstantiated ||
(sym->hasFlag(FLAG_MARKED_GENERIC) && sym->hasFlag(FLAG_TEMP))) {
var->addFlag(FLAG_MARKED_GENERIC);
// printf("(A) Adding FLAG_MARKED_GENERIC to %s\n", sym->name);
if (isFnSymbol(var))
var->addFlag(FLAG_RET_TYPE_MARKED_GENERIC);
else
var->addFlag(FLAG_MARKED_GENERIC);
}
} else if (CallExpr* call = toCallExpr(typeExpr)) {
if (call->baseExpr)
Expand All @@ -2502,6 +2534,11 @@ static void propagateMarkedGeneric(Symbol* var, Expr* typeExpr) {
for_actuals(actual, call) {
propagateMarkedGeneric(var, actual);
}
} else if (BlockStmt* blk = toBlockStmt(typeExpr)) {
// handle blocks since they are used for return type exprs
for_alist(expr, blk->body) {
propagateMarkedGeneric(var, expr);
}
}
}

Expand Down Expand Up @@ -3476,6 +3513,15 @@ void warnIfGenericFormalMissingQ(ArgSymbol* arg, Type* type, Expr* typeExpr) {
}
}
}

// error for CR(?) where CR is a concrete record or class type
if (!type->symbol->hasFlag(FLAG_GENERIC) &&
arg->hasFlag(FLAG_MARKED_GENERIC)) {
USR_FATAL(arg,
"the formal argument '%s' is marked generic with (?) "
"but the type '%s' is not generic",
arg->name, toString(type, /*decorators*/ false));
}
}

static void hack_resolve_types(ArgSymbol* arg) {
Expand Down
3 changes: 3 additions & 0 deletions compiler/resolution/callInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ const char* CallInfo::toString() {
ii->iterator->hasFlag(FLAG_PROMOTION_WRAPPER) == true) {
retval = astr(retval, "promoted expression");

} else if (sym == gUninstantiated) {
retval = astr(retval, "?");

} else if (sym->hasFlag(FLAG_TYPE_VARIABLE) == true) {
retval = astr(retval, "type ", ::toString(type));

Expand Down
109 changes: 79 additions & 30 deletions compiler/resolution/functionResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13883,6 +13883,42 @@ void checkDuplicateDecorators(Type* decorator, Type* decorated, Expr* ctx) {
std::set<Symbol*> gAlreadyWarnedSurprisingGenericSyms;
std::set<Symbol*> gAlreadyWarnedSurprisingGenericManagementSyms;

static bool computeIsField(Symbol*& sym, AggregateType* forFieldInHere) {
// is it a field? check to see if it's a temp within an initializer
// initializing field (in which case, we should think about
// this as a field). If it's a field, replaces 'sym' with the
// field to use for error reporting.
bool isField = false;

if (forFieldInHere) {
AggregateType* ct = forFieldInHere->getRootInstantiation();
Symbol* field = ct->getField(sym->name);
isField = true;
sym = field;
} else if (sym->hasFlag(FLAG_TEMP)) {
for_SymbolSymExprs(se, sym) {
if (CallExpr* c = toCallExpr(se->parentExpr)) {
if ((c->isPrimitive(PRIM_SET_MEMBER) ||
c->isPrimitive(PRIM_INIT_FIELD)) && se == c->get(3)) {
isField = true;

// replace 'sym' with the field for the error location
AggregateType* ct = toAggregateType(c->get(1)->getValType());
ct = ct->getRootInstantiation();
SymExpr* nameSe = toSymExpr(c->get(2));
VarSymbol* nameVar = toVarSymbol(nameSe->symbol());
const char* name = astr(nameVar->immediate->v_string.c_str());
Symbol* field = ct->getField(name);
sym = field;
break;
}
}
}
}

return isField;
}

void checkSurprisingGenericDecls(Symbol* sym, Expr* typeExpr,
AggregateType* forFieldInHere) {
if (sym == nullptr || typeExpr == nullptr) {
Expand All @@ -13897,40 +13933,22 @@ void checkSurprisingGenericDecls(Symbol* sym, Expr* typeExpr,
declType = typeExpr->typeInfo();
}

bool genericWithDefaults = false;
if (AggregateType* at = toAggregateType(declType))
genericWithDefaults = at->isGenericWithDefaults();

if (declType->symbol->hasFlag(FLAG_GENERIC) &&
declType != dtAny && // workaround for interfaces
!genericWithDefaults &&
!sym->hasFlag(FLAG_MARKED_GENERIC) &&
!sym->hasFlag(FLAG_RET_TYPE_MARKED_GENERIC) &&
!sym->hasFlag(FLAG_TYPE_VARIABLE)) {

// is it a field? check to see if it's a temp within an initializer
// initializing field (in which case, we should think about
// this as a field).
bool isField = false;

if (forFieldInHere) {
AggregateType* ct = forFieldInHere->getRootInstantiation();
Symbol* field = ct->getField(sym->name);
isField = true;
sym = field;
} else if (sym->hasFlag(FLAG_TEMP)) {
for_SymbolSymExprs(se, sym) {
if (CallExpr* c = toCallExpr(se->parentExpr)) {
if ((c->isPrimitive(PRIM_SET_MEMBER) ||
c->isPrimitive(PRIM_INIT_FIELD)) && se == c->get(3)) {
isField = true;

// replace 'sym' with the field for the error location
AggregateType* ct = toAggregateType(c->get(1)->getValType());
ct = ct->getRootInstantiation();
SymExpr* nameSe = toSymExpr(c->get(2));
VarSymbol* nameVar = toVarSymbol(nameSe->symbol());
const char* name = astr(nameVar->immediate->v_string.c_str());
Symbol* field = ct->getField(name);
sym = field;
break;
}
}
}
}
// Note: this can change 'sym' to a field rather than a tmp.
bool isField = computeIsField(sym, forFieldInHere);

if (isClassLikeOrManaged(declType)) {
auto dec = classTypeDecorator(declType);
Expand Down Expand Up @@ -14031,16 +14049,47 @@ void checkSurprisingGenericDecls(Symbol* sym, Expr* typeExpr,
s.append("(?)");
}

const char* fieldOrVar = isField?"field":"variable";
USR_WARN(sym, "please use '?' when declaring a %s with generic type",
fieldOrVar);
if (isFnSymbol(sym)) {
USR_WARN(sym, "please use '?' when declaring a routine "
"with a generic return type");

} else {
const char* fieldOrVar = isField?"field":"variable";
USR_WARN(sym,
"please use '?' when declaring a %s with generic type",
fieldOrVar);
}
USR_PRINT(sym, "for example with '%s'", s.c_str());
}
if (fWarnUnstable) {
USR_PRINT("this warning may be an error in the future");
}
}
}

// if it was marked generic, but it's not generic (or an instantiation)
// then have a fatal error
if (sym->hasFlag(FLAG_MARKED_GENERIC) ||
sym->hasFlag(FLAG_RET_TYPE_MARKED_GENERIC)) {
if (!declType->symbol->hasFlag(FLAG_GENERIC) &&
!genericWithDefaults) {
bool isField = computeIsField(sym, forFieldInHere);

const char* thing = "";
if (isFnSymbol(sym)) {
thing = astr("return type of the routine ", sym->name);
} else if (isField) {
thing = astr("field ", sym->name);
} else {
thing = astr("variable ", sym->name);
}

USR_FATAL(sym,
"the %s is marked generic with (?) "
"but the type '%s' is not generic",
thing, toString(declType, /*decorators*/ false));
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/resolution/resolveFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ void resolveSpecifiedReturnType(FnSymbol* fn) {

resolveBlockStmt(fn->retExprType);

checkSurprisingGenericDecls(fn, fn->retExprType->body.tail, nullptr);

retType = fn->retExprType->body.tail->typeInfo();

if (SymExpr* se = toSymExpr(fn->retExprType->body.tail)) {
Expand Down
Loading

0 comments on commit c6bb384

Please sign in to comment.