d加上缺少的置内存
原文
无法工作的代码示例:
extern(C) void main()
{
alias int3 = int[3];
union U { ulong a = 1; uint[3] b; }
//除非类型大小为`1,`否则无法组整个数切片设置为非零值.
{ ushort[] a; a[] = 1; }
{ int[] a; a[] = 1; }
{ ulong[] a; a[] = 1; }
{ float[] a; a[] = 1; }
{ double[] a; a[] = 1; }
{ cdouble[] a; a[] = cdouble.max; }
{ creal[] a; a[] = creal.max; }
{ int3[] a; int3 val = [1, 2, 3]; a[] = val; }
{ U[] a; a[] = U.init; }
//除非类型大小为`1,`否则无法为静态数组的所有成员指定非零初值
{ ushort[4] a = 1; }
{ int[4] a = 1; }
{ ulong[4] a = 1; }
{ float[4] a = 1; }
{ double[4] a = 1; }
{ cdouble[4] a = cdouble.max; }
{ creal[4] a = creal.max; }
{ U[4] a = U.init; }
//如果未显式初化,则具有非零`init`的类型的静态数组也会失败
{ wchar[4] a; }
{ float[4] a; }
{ double[4] a; }
{ real[4] a; }
{ cdouble[4] a; }
{ creal[4] a; }
{ U[4] a; }
//>8字节的标量静态数组甚至不能显式初化为零
{ real[4] a = 0; }
{ cdouble[4] a = 0+0i; }
{ creal[4] a = 0+0i; }
{ U[4] a = U(0); }
//有时甚至单独指定数组的每个元素时也会出现问题
{ int[4] a = [1, 1, 1, 1]; }
{ int[4] a = [1, 2, 3, 4]; }
//有效,因为编译器未试用类似`memset`的方法
{ char[10] a; }
//这些工作
{ wchar[2] a = [0x1234, 0x5678]; a[] = 0; }
//之所以有效,是因为编译器知道,不管类型宽度,可用`memset`清零类型位.
}
这些函数是在druntime的rt/memset中定义的,它没有与betterC链接.不确定最好方法是什么.可在依赖它们的每个翻译单元中发出这些函数.或,总是内联代码(尽管一些memset函数使用内联asm,dmd目前不能内联它)
修复很简单.我写了代码,但没有推它.
只需要成为druntime中的模板.假设可让它内联循环,但这会伤害LDC和GDC.
arrayOp实际支持memset,但是让数组降级使用arrayOp会使它最终使用自己.
我也考虑过,在后端使用任意设置memset,但是很讨厌.
除了使它为模板外,还需要从e2ir插入前端的移动调用,以便实例化时分析语义.
长远看,最好是降级前端代码,即降低模板勾挂.
我知道.在dmd中,应该有另一个仅针对dmd的语义趟,因为现有代码完全是一团糟.
如,赋值数组操作,只是数百个行访问器成员中的一个分支.
拉兹万,想法是正确的.嗯,你是对的,但重构应该在一个单独的公关.
我同意.我唯一保留意见是LDC和GDC似乎可很好地处理-betterC中的设置数组,但是如果前端降级,除非开始识别新的模板勾挂,可能会降低性能.
另一个(betterC)中示例,可触发该情况:
extern(C) void main() {
wchar[2] got;
func(got);
}
void func(out wchar[2] v) {
}
为什么会有这些勾挂呢?在编译器中,可简单重写为foreach循环,且完全不依赖运行时,更不用说rt中的函数了.
这适合GDC和LDC.问题出在dmd后端.
因为从未工作,这不是回归.更多进展.
浙公网安备 33010602011771号