<commit_before>// Copyright (c) 2016 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package codegen

import (
	"encoding/binary"
	"errors"
	"math"

	"github.com/tsavola/wag/compile/event"
	"github.com/tsavola/wag/internal/code"
	"github.com/tsavola/wag/internal/gen"
	"github.com/tsavola/wag/internal/gen/atomic"
	"github.com/tsavola/wag/internal/gen/debug"
	"github.com/tsavola/wag/internal/gen/link"
	"github.com/tsavola/wag/internal/gen/rodata"
	"github.com/tsavola/wag/internal/loader"
	"github.com/tsavola/wag/internal/module"
	"github.com/tsavola/wag/internal/obj"
	"github.com/tsavola/wag/object/abi"
	"github.com/tsavola/wag/trap"
)

func GenProgram(
	text code.Buffer,
	objMap obj.ObjectMapper,
	load loader.L,
	m *module.M,
	eventHandler func(event.Event),
	initFuncCount int,
) {
	funcStorage := gen.Func{
		Prog: gen.Prog{
			Module:    m,
			Text:      code.Buf{Buffer: text},
			Map:       objMap,
			FuncLinks: make([]link.FuncL, len(m.Funcs)),
		},
	}
	p := &funcStorage.Prog

	if debug.Enabled {
		if debug.Depth != 0 {
			debug.Printf("")
		}
		debug.Depth = 0
	}

	funcCodeCount := load.Varuint32()
	if needed := len(m.Funcs) - len(m.ImportFuncs); funcCodeCount != uint32(needed) {
		panic(module.Errorf("wrong number of function bodies: %d (should be: %d)", funcCodeCount, needed))
	}

	p.Map.InitObjectMap(len(m.ImportFuncs), int(funcCodeCount))

	if p.Text.Addr != abi.TextAddrNoFunction {
		panic(errors.New("unexpected initial text address"))
	}
	asm.JumpToTrapHandler(p, trap.NoFunction)

	if p.Text.Addr == abi.TextAddrNoFunction || p.Text.Addr > abi.TextAddrResume {
		panic("bad text address after NoFunction trap handler")
	}
	asm.AlignFunc(p)
	asm.Resume(p)

	if p.Text.Addr <= abi.TextAddrResume || p.Text.Addr > abi.TextAddrStart {
		panic("bad text address after resume routine")
	}
	asm.AlignFunc(p)
	asm.Init(p)

	// Virtual return point for resuming a program which was suspended before
	// execution started.  This call site must be at index 0.
	p.Map.PutCallSite(uint32(p.Text.Addr), obj.Word*2)

	if m.StartDefined {
		if int(m.StartIndex) >= initFuncCount {
			initFuncCount = int(m.StartIndex) + 1
		}
		retAddr := asm.CallMissing(p, false)
		p.Map.PutCallSite(uint32(retAddr), obj.Word*2) // stack depth excluding entry args (including link addr)
		p.FuncLinks[m.StartIndex].AddSite(retAddr)
	}

	if p.Text.Addr <= abi.TextAddrStart || p.Text.Addr > abi.TextAddrEnter {
		panic("bad text address after init routine and start function call")
	}<commit_msg>codegen: well-known address for call site #0<commit_after>// Copyright (c) 2016 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package codegen

import (
	"encoding/binary"
	"errors"
	"math"

	"github.com/tsavola/wag/compile/event"
	"github.com/tsavola/wag/internal/code"
	"github.com/tsavola/wag/internal/gen"
	"github.com/tsavola/wag/internal/gen/atomic"
	"github.com/tsavola/wag/internal/gen/debug"
	"github.com/tsavola/wag/internal/gen/link"
	"github.com/tsavola/wag/internal/gen/rodata"
	"github.com/tsavola/wag/internal/loader"
	"github.com/tsavola/wag/internal/module"
	"github.com/tsavola/wag/internal/obj"
	"github.com/tsavola/wag/object/abi"
	"github.com/tsavola/wag/trap"
)

func GenProgram(
	text code.Buffer,
	objMap obj.ObjectMapper,
	load loader.L,
	m *module.M,
	eventHandler func(event.Event),
	initFuncCount int,
) {
	funcStorage := gen.Func{
		Prog: gen.Prog{
			Module:    m,
			Text:      code.Buf{Buffer: text},
			Map:       objMap,
			FuncLinks: make([]link.FuncL, len(m.Funcs)),
		},
	}
	p := &funcStorage.Prog

	if debug.Enabled {
		if debug.Depth != 0 {
			debug.Printf("")
		}
		debug.Depth = 0
	}

	funcCodeCount := load.Varuint32()
	if needed := len(m.Funcs) - len(m.ImportFuncs); funcCodeCount != uint32(needed) {
		panic(module.Errorf("wrong number of function bodies: %d (should be: %d)", funcCodeCount, needed))
	}

	p.Map.InitObjectMap(len(m.ImportFuncs), int(funcCodeCount))

	if p.Text.Addr != abi.TextAddrNoFunction {
		panic(errors.New("unexpected initial text address"))
	}
	asm.JumpToTrapHandler(p, trap.NoFunction)

	if p.Text.Addr == abi.TextAddrNoFunction || p.Text.Addr > abi.TextAddrResume {
		panic("bad text address after NoFunction trap handler")
	}
	asm.AlignFunc(p)
	asm.Resume(p)

	if p.Text.Addr <= abi.TextAddrResume || p.Text.Addr > abi.TextAddrStart {
		panic("bad text address after resume routine")
	}
	asm.AlignFunc(p)

	// Virtual return point for resuming a program which was suspended before
	// execution started.  This call site must be at index 0, and its address
	// must match the start routine.
	p.Map.PutCallSite(uint32(p.Text.Addr), obj.Word*2)

	asm.Init(p)

	if m.StartDefined {
		if int(m.StartIndex) >= initFuncCount {
			initFuncCount = int(m.StartIndex) + 1
		}
		retAddr := asm.CallMissing(p, false)
		p.Map.PutCallSite(uint32(retAddr), obj.Word*2) // stack depth excluding entry args (including link addr)
		p.FuncLinks[m.StartIndex].AddSite(retAddr)
	}

	if p.Text.Addr <= abi.TextAddrStart || p.Text.Addr > abi.TextAddrEnter {
		panic("bad text address after init routine and start function call")
	}
{'fraction_non_alphanumeric': 0.14057142857142857, 'fraction_numerical': 0.007047619047619047, 'mean_word_length': 3.9305164319248824, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1760812', 'n_tokens_mistral': 2058, 'n_tokens_neox': 1954, 'n_words': 414}