blob: 2e986ac76a73888c1b8dd27cc51600f0881edd7c [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package llcpp
import (
"bytes"
_ "embed"
"fmt"
"strings"
"text/template"
"go.fuchsia.dev/fuchsia/tools/fidl/gidl/lib/config"
"go.fuchsia.dev/fuchsia/tools/fidl/gidl/lib/hlcpp"
"go.fuchsia.dev/fuchsia/tools/fidl/gidl/lib/ir"
"go.fuchsia.dev/fuchsia/tools/fidl/gidl/lib/llcpp"
"go.fuchsia.dev/fuchsia/tools/fidl/gidl/lib/mixer"
"go.fuchsia.dev/fuchsia/tools/fidl/lib/fidlgen"
)
var (
//go:embed benchmarks.tmpl
benchmarkTmplText string
benchmarkTmpl = template.Must(template.New("benchmarkTmpl").Parse(benchmarkTmplText))
)
type benchmark struct {
Path, Name, Type, EventProtocolType, EchoCallProtocolType string
ValueBuild, ValueVar string
HandleDefs string
EnableSendEventBenchmark, EnableEchoCallBenchmark bool
}
type benchmarkTmplInput struct {
FidlLibrary string
FidlInclude string
Benchmarks []benchmark
}
// Generate generates Low-Level C++ benchmarks.
func GenerateBenchmarks(gidl ir.All, fidl fidlgen.Root, config config.GeneratorConfig) ([]byte, error) {
schema := mixer.BuildSchema(fidl)
tmplInput := benchmarkTmplInput{
FidlLibrary: libraryName(config.CppBenchmarksFidlLibrary),
FidlInclude: libraryInclude(config.CppBenchmarksFidlLibrary),
}
for _, gidlBenchmark := range gidl.Benchmark {
decl, err := schema.ExtractDeclaration(gidlBenchmark.Value, gidlBenchmark.HandleDefs)
if err != nil {
return nil, fmt.Errorf("benchmark %s: %s", gidlBenchmark.Name, err)
}
valBuild, valVar := llcpp.BuildValueAllocator("allocator", gidlBenchmark.Value, decl, llcpp.HandleReprRaw)
tmplInput.Benchmarks = append(tmplInput.Benchmarks, benchmark{
Path: gidlBenchmark.Name,
Name: benchmarkName(gidlBenchmark.Name),
Type: benchmarkTypeFromValue(config.CppBenchmarksFidlLibrary, gidlBenchmark.Value),
EventProtocolType: benchmarkProtocolFromValue(config.CppBenchmarksFidlLibrary, gidlBenchmark.Value) + "EventProtocol",
EchoCallProtocolType: benchmarkProtocolFromValue(config.CppBenchmarksFidlLibrary, gidlBenchmark.Value) + "EchoCall",
ValueBuild: valBuild,
ValueVar: valVar,
HandleDefs: hlcpp.BuildHandleDefs(gidlBenchmark.HandleDefs),
EnableSendEventBenchmark: gidlBenchmark.EnableSendEventBenchmark,
EnableEchoCallBenchmark: gidlBenchmark.EnableEchoCallBenchmark,
})
}
var buf bytes.Buffer
if err := benchmarkTmpl.Execute(&buf, tmplInput); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func libraryInclude(librarySuffix string) string {
return fmt.Sprintf("fidl/test.benchmarkfidl%s/cpp/wire.h", strings.ReplaceAll(librarySuffix, " ", ""))
}
func libraryName(librarySuffix string) string {
return fmt.Sprintf("test_benchmarkfidl%s", strings.ReplaceAll(librarySuffix, " ", ""))
}
func benchmarkTypeFromValue(librarySuffix string, value ir.Value) string {
return fmt.Sprintf("%s::wire::%s", libraryName(librarySuffix), ir.TypeFromValue(value))
}
func benchmarkProtocolFromValue(librarySuffix string, value ir.Value) string {
return fmt.Sprintf("%s::%s", libraryName(librarySuffix), ir.TypeFromValue(value))
}
func benchmarkName(gidlName string) string {
return strings.ReplaceAll(gidlName, "/", "_")
}