Bug 21879 – -betterC "undefined reference to '_memset32'"
Status
RESOLVED
Resolution
DUPLICATE
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2021-04-29T20:02:01Z
Last change time
2022-02-10T13:41:33Z
Assigned to
No Owner
Creator
thomas.bockman
Comments
Comment #0 by thomas.bockman — 2021-04-29T20:02:01Z
This (or something similar) used to work, but now fails with a linker error "undefined reference to '_memset32'":
/////////////////////////////////////////////////////////
module app;
extern(C) void main() {
int[17] stuff;
stuff[] = 7;
}
/////////////////////////////////////////////////////////
Also, the above example crashes the "All DMD compilers" option on run.dlang.io:
/////////////////////////////////////////////////////////
std.conv.ConvException@/home/travis/dlang/dmd-2.094.1/linux/bin64/../../src/phobos/std/conv.d(2225): Can't parse string: bool should be case-insensitive 'true' or 'false'
----------------
??:? pure @safe bool std.conv.parse!(bool, immutable(char)[]).parse(ref immutable(char)[]) [0x4fa101]
??:? pure @safe bool std.conv.toImpl!(bool, immutable(char)[]).toImpl(immutable(char)[]) [0x4fa160]
??:? pure @safe bool std.conv.to!(bool).to!(immutable(char)[]).to(immutable(char)[]) [0x4f9fbf]
??:? @safe bool std.getopt.handleOption!(bool*).handleOption(immutable(char)[], bool*, ref immutable(char)[][], ref std.getopt.configuration, bool) [0x4ca23c]
??:? @safe void std.getopt.getoptImpl!(immutable(char)[], bool*, immutable(char)[], immutable(char)[][]*, immutable(char)[], bool*, immutable(char)[], void delegate() pure nothrow @safe, std.getopt.config).getoptImpl(ref immutable(char)[][], ref std.getopt.configuration, ref std.getopt.GetoptResult, ref std.getopt.GetOptException, void[][immutable(char)[]], void[][immutable(char)[]], immutable(char)[], bool*, immutable(char)[], immutable(char)[][]*, immutable(char)[], bool*, immutable(char)[], void delegate() pure nothrow @safe, std.getopt.config) [0x4c9c10]
??:? @safe std.getopt.GetoptResult std.getopt.getopt!(immutable(char)[], bool*, immutable(char)[], immutable(char)[][]*, immutable(char)[], bool*, immutable(char)[], void delegate() pure nothrow @safe, std.getopt.config).getopt(ref immutable(char)[][], immutable(char)[], bool*, immutable(char)[], immutable(char)[][]*, immutable(char)[], bool*, immutable(char)[], void delegate() pure nothrow @safe, std.getopt.config) [0x4c96e4]
??:? _Dmain [0x4bc5d8]
/////////////////////////////////////////////////////////
Comment #1 by blatblatnik — 2021-04-30T08:43:23Z
I ran into this exact same problem. This is by no means an actual patch, but if you need to use this notation now, you can define this function yourself.
Somewhere in one of your .d files, you can define it like this:
// int[64] i; i[] = 42;
extern(C) void _memset32(uint* uints, uint value, size_t length)
{
for (size_t i = 0; i < length; ++i)
uints[i] = value;
}
I don't understand why you need to do it yourself, this should definitely be fixed.
Comment #2 by blatblatnik — 2021-04-30T09:13:32Z
Also, this doesn't just happen with _memset32, it also happens with
short[4] s; s[] = 42; // ERROR: Undefined reference to _memset16.
int[4] i; i[] = 42; // ERROR: Undefined reference to _memset32.
long[4] l; l[] = 42; // ERROR: Undefined reference to _memset64.
float[4] f; f[] = 42; // ERROR: Undefined reference to _memsetFloat.
double[4] d; d[] = 42; // ERROR: Undefined reference to _memsetDouble.
real[4] r; r[] = 42; // ERROR: Undefined reference to _memset80.
void[][4] a; // ERROR: Undefined reference to _memset128ii.
struct S{} S[4] s; s[] = S.init; // ERROR: Undefined reference to _memsetn.
These are all of the ones I encountered while I was messing around with -betterC. There may be more that I haven't found yet.
I looked at the assembly generated for each of these to figure out which parameters these functions are called with.
Here is a quick-and-dirty implementation for each of them that you can copy paste in some D file.
extern(C) void _memsetn(void* array, const void* value, size_t length, size_t elemSize) // Struct[64] s; s[] = Struct.init;
{
import core.stdc.string : memmove;
for (size_t i = 0; i < length; ++i)
memmove(array + i * elemSize, value, elemSize);
}
extern(C) void _memset16(ushort* ushorts, ushort value, size_t length) // short[64] s; s[] = 42;
{
for (size_t i = 0; i < length; ++i)
uints[i] = value;
}
extern(C) void _memset32(uint* uints, uint value, size_t length) // int[64] i; i[] = 42;
{
for (size_t i = 0; i < length; ++i)
uints[i] = value;
}
extern(C) void _memset64(ulong* uints, ulong value, size_t length) // long[64] l; l[] = 42;
{
for (size_t i = 0; i < length; ++i)
uints[i] = value;
}
extern(C) void _memsetFloat(float* floats, float value, size_t length) // float[64] f; f[] = 42;
{
for (size_t i = 0; i < length; ++i)
floats[i] = value;
}
extern(C) void _memsetDouble(double* doubles, double value, size_t length) // double[64] d; d[] = 42;
{
for (size_t i = 0; i < length; ++i)
doubles[i] = value;
}
extern(C) void _memset80(real* reals, real value, size_t length) // real[64] r; d[] = 42;
{
for (size_t i = 0; i < length; ++i)
reals[i] = value;
}
extern(C) void _memset128ii(void *dest, void *value, size_t length) // void[][64] a;
{
void[]* d = cast(void[]*) dest;
void[] s = *cast(void[]*) value;
for (size_t i = 0; i < length; ++i)
d[i] = s;
}
Comment #3 by johan_forsberg_86 — 2021-04-30T09:31:02Z
It seems to me the runtime isn't linked correctly for some reason.
That stuff resides in rt.memset for example.
Comment #4 by moonlightsentinel — 2021-04-30T10:05:14Z
> It seems to me the runtime isn't linked correctly for some reason.
-betterC explicitly does not link to druntime. You'd have to manually add it to the dmd / linker command.
Comment #5 by snarwin+bugzilla — 2022-02-10T13:41:33Z
*** This issue has been marked as a duplicate of issue 19946 ***