From bbdf473ef0599cb238029d79aec10d8d754aa516 Mon Sep 17 00:00:00 2001 From: kai Date: Thu, 11 Apr 2013 08:23:33 +0200 Subject: [PATCH] Fix for issue #326. For a foreach (int i, dchar c; str) loop the compiler generates a delegate with a different type signature then the runtime uses. The runtime declares the parameters as void* and passes a pointer to a size_t variable for the index. The code generated by the compiler expects a ref int. This works on a little endian architecture, but on a big endian architecture the index is always 0. This fix changes the parameter type of the passed index to size_t and generates a cast to the type specified by the user. --- dmd2/statement.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/dmd2/statement.c b/dmd2/statement.c index 50cfe59e..463363ca 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -2156,6 +2156,10 @@ Lagain: arg->type = arg->type->semantic(loc, sc); arg->type = arg->type->addStorageClass(arg->storageClass); +#if IN_LLVM + // Type of parameter may be different; see below + Type *para_type = arg->type; +#endif if (tfld) { Parameter *prm = Parameter::getNth(tfld->parameters, i); //printf("\tprm = %s%s\n", (prm->storageClass&STCref?"ref ":""), prm->ident->toChars()); @@ -2178,12 +2182,35 @@ Lagain: LcopyArg: id = Lexer::uniqueId("__applyArg", (int)i); +#if IN_LLVM + // In case of a foreach loop on an array the index passed + // to the delegate is always of type size_t. The type of + // the parameter must be changed to size_t and a cast to + // the type used must be inserted. Otherwise the index is + // always 0 on a big endian architecture. This fixes + // issue #326. + Initializer *ie; + if (dim == 2 && i == 0 && (tab->ty == Tarray || tab->ty == Tsarray)) + { + para_type = Type::tsize_t; + ie = new ExpInitializer(0, + new CastExp(0, + new IdentifierExp(0, id), arg->type)); + } + else + ie = new ExpInitializer(0, new IdentifierExp(0, id)); +#else Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); +#endif VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); s = new ExpStatement(0, v); body = new CompoundStatement(loc, s, body); } +#if IN_LLVM + args->push(new Parameter(stc, para_type, id, NULL)); +#else args->push(new Parameter(stc, arg->type, id, NULL)); +#endif } tfld = new TypeFunction(args, Type::tint32, 0, LINKd); cases = new Statements();