diff --git a/linker.go b/linker.go index 6f97af278..024b72bbc 100644 --- a/linker.go +++ b/linker.go @@ -207,13 +207,19 @@ func flattenPrograms(progs map[string]*ProgramSpec, names []string) { // dependencies of each program. func flattenInstructions(name string, progs map[string]*ProgramSpec, refs map[*ProgramSpec][]string) asm.Instructions { prog := progs[name] + progRefs := refs[prog] + + if len(progRefs) == 0 { + // No references, nothing to do. + return prog.Instructions + } insns := make(asm.Instructions, len(prog.Instructions)) copy(insns, prog.Instructions) // Add all direct references of prog to the list of to be linked programs. - pending := make([]string, len(refs[prog])) - copy(pending, refs[prog]) + pending := make([]string, len(progRefs)) + copy(pending, progRefs) // All references for which we've appended instructions. linked := make(map[string]bool) diff --git a/linker_test.go b/linker_test.go index 39b01cf65..cbe31d683 100644 --- a/linker_test.go +++ b/linker_test.go @@ -159,3 +159,24 @@ func TestSplitSymbols(t *testing.T) { qt.Assert(t, qt.HasLen(m["sym3"], 3)) qt.Assert(t, qt.HasLen(m["sym4"], 4)) } + +func TestFlattenInstructionsAllocations(t *testing.T) { + name := "entrypoint" + instructions := asm.Instructions{ + asm.LoadImm(asm.R0, 0, asm.DWord), + asm.Return(), + } + prog := &ProgramSpec{ + Name: name, + Instructions: instructions, + } + progs := map[string]*ProgramSpec{name: prog} + refs := make(map[*ProgramSpec][]string) + + // ensure that flattenInstructions does not allocate memory + // if there is no reference for the given program. + allocs := testing.AllocsPerRun(5, func() { + _ = flattenInstructions(name, progs, refs) + }) + qt.Assert(t, qt.Equals(allocs, float64(0))) +}