package asmc

import (
	"git.urbach.dev/cli/q/src/asm"
	"git.urbach.dev/cli/q/src/config"
	"git.urbach.dev/cli/q/src/dll"
)

// Finalize generates the final machine code.
func Finalize(a *asm.Assembler, dlls dll.List) ([]byte, []byte) {
	data, dataLabels := a.Data.Finalize()

	if config.TargetOS == config.Windows && len(data) == 0 {
		data = []byte{0}
	}

	c := compiler{
		assembler:    a,
		code:         make([]byte, 0, len(a.Instructions)*8),
		codeLabels:   make(map[string]Address, 32),
		codePointers: make([]*pointer, 0, len(a.Instructions)*8),
		codeStart:    uint32(codeOffset()),
		data:         data,
		dataLabels:   dataLabels,
		dlls:         dlls,
	}

	switch config.TargetArch {
	case config.ARM:
		for _, x := range a.Instructions {
			c.compileARM(x)
		}

	case config.X86:
		for _, x := range a.Instructions {
			c.compileX86(x)
		}
	}

	c.resolvePointers()
	return c.code, c.data
}