Comments 10
text "".sum(SB), NOSPLIT|ABIInternal, $0-32
funcdata $0, gclocals·1a65e721a2ccc325b382662e7ffee780(SB)
funcdata $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
funcdata $3, gclocals·568470801006e5c0dc3947ea998fe279(SB)
pcdata $2, $0
pcdata $0, $0
movq "".numbers+16(SP), AX
pcdata $2, $1
pcdata $0, $1
movq "".numbers+8(SP), CX
xorl DX, DX
xorl BX, BX
jmp sum_pc30
sum_pc16:
leaq 1(DX), SI
movq (CX)(DX*8), DI
addq DI, BX
movq SI, DX
sum_pc30:
cmpq DX, AX
jlt sum_pc16
pcdata $2, $0
movq BX, "".~r1+32(SP)
ret
Никаких JUMP вначале и всего 4 переменных: слайс, его длина, его вместимость (не используется) и n в качестве возвращаемого.
godbolt.org/z/44KBE5
define i64 @sum(i64* %ptr, i64 %len, i64 %cap) {
br label %for.loop
for.loop: ; preds = %for.body, %entry
%0 = phi i64 [ 0, %entry ], [ %5, %for.body ]
%1 = phi i64 [ 0, %entry ], [ %6, %for.body ]
%2 = icmp slt i64 %1, %len
br i1 %2, label %for.body, label %for.done
for.body: ; preds = %for.loop
%3 = getelementptr i64, i64* %ptr, i64 %1
%4 = load i64, i64* %3
%5 = add i64 %0, %4
%6 = add i64 %1, 1
br label %for.loop
for.done: ; preds = %for.loop
ret i64 %0
}
И конечное представление LLVM IR -> ASM:
sum: # @sum
xor eax, eax
xor ecx, ecx
cmp rcx, rsi
jge .LBB0_3
.LBB0_2: # %for.body
add rax, qword ptr [rdi + 8*rcx]
inc rcx
cmp rcx, rsi
jl .LBB0_2
.LBB0_3: # %for.done
ret
godbolt.org/z/jfYKHj
gnomeby А теперь сравните с С https://godbolt.org/z/nMWLf1 ;-)
Кстати в вашем IR тоже ошибка — вы забыли entry:
godbolt.org/z/jPnH-3
Решение о представлении типа Go int принимается при создании LLVM IR-кода. Это — одна из многих причин того, что LLVM IR-код не является, как многие думают, платформенно-независимым.
Тут у меня мозг немного сломался. В LLVM IR как раз у всех переменных тип проставлен явно: i64. i64 останется i64 вне зависимости от платформы. То есть полученный код как раз является платформонезависимым (как минимум по этому вопросу), в отличие от int в Go, который, как утверждается, будет зависеть от платформы.
Такой код, созданный для одной платформы, нельзя просто взять и скомпилировать для другой платформы
Конечно же можно, если платформа является Тьюринг-полной.
Видимо i64 должен поддерживаться платформой наивно. Int Go транслируется в int64 или int32 в зависимости от целевой платформы.
Соответственно нельзя скомпилировать код с INT64 на платформу, где его нет, на условный 386. Для его поддержки уже первичный транслятор должен принимать решение какими структурами и способами работать с парой i32 как с одним i64
Соответственно нельзя скомпилировать код с INT64 на платформу, где его нет
Конечно же можно, если платформа является Тьюринг-полной (все платформы являются).
Возможно LLVM не умеет компилировать LLVM IR-код с INT64 на платформу, где его нет. Но это ограничение LLVM, а не кода и не есть признак платформозависимого кода.
Просто автор не понимает, что значат термины.
Под "нельзя скомпилировать" в данном контексте я имел в виду "не может или не хочет". И, похоже, именно не хочет по своей идеологии: LLVM IR-код — это именно low level код, примитивные типы или поддерживаются целевой платформой или нет, эмуляции типа int64 === {low: int32; high: int32} не происходит.
LLVM с точки зрения Go