| {{/* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */}} |
| |
| {{Global "module" ""}} |
| {{Include "go_common.tmpl"}} |
| {{$ | Macro "replay_writer.go" | GoFmt | Write "replay_writer.go"}} |
| |
| {{define "replay_writer.go"}} |
| {{template "Go.GeneratedHeader" (Global "OutputDir")}} |
| |
| import ( |
| "fmt" |
| "io" |
| "io/ioutil" |
| "strings" |
| |
| "android.googlesource.com/platform/tools/gpu/atom" |
| "android.googlesource.com/platform/tools/gpu/binary" |
| "android.googlesource.com/platform/tools/gpu/database" |
| "android.googlesource.com/platform/tools/gpu/log" |
| "android.googlesource.com/platform/tools/gpu/memory" |
| "android.googlesource.com/platform/tools/gpu/replay/builder" |
| "android.googlesource.com/platform/tools/gpu/replay/protocol" |
| "android.googlesource.com/platform/tools/gpu/replay/value" |
| ) |
| |
| {{Global "Go.Statement.Override" "Statement"}} |
| |
| func loadRemap(ϟb *builder.Builder, key interface{}, ty protocol.Type, val value.Value) { |
| if ptr, found := ϟb.Remappings[key]; found { |
| ϟb.Load(ty, ptr) |
| } else { |
| ptr = ϟb.AllocateMemory(uint64(ty.Size(ϟb.Architecture().PointerSize))) |
| ϟb.Push(val) // We have an input to an unknown id, use the unmapped value. |
| ϟb.Clone(0) |
| ϟb.Store(ptr) |
| ϟb.Remappings[key] = ptr |
| } |
| } |
| |
| {{Template "DeclareBuilderFunctionInfos" $}} |
| |
| {{ForEach $.Pseudonyms "DeclarePseudonymValue" | JoinWith "\n"}} |
| |
| {{ForEach (AllCommands $) "DeclareCommandReplay" | JoinWith "\n"}} |
| |
| {{ForEach $.Pointers "PointerReplayMethods" | JoinWith "\n"}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the replay function for the specified command |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "DeclareCommandReplay"}} |
| {{AssertType $ "Function"}} |
| |
| {{if not (GetAnnotation $ "no_replay")}} |
| |
| {{$name := Macro "Go.CmdName" $}} |
| var _ = replay.Replayer(&{{$name}}{}) // interface compliance check |
| func (ϟa *{{$name}}) {{if GetAnnotation $ "replay_custom"}}default{{end}}Replay(§ |
| ϟi atom.ID, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) error { |
| ϟc := getState(ϟs) |
| _ = ϟc |
| |
| {{Global "CurrentCommand" $}} |
| |
| {{/* Simulate the call */}} |
| {{Template "Go.CommandLogic" $}} |
| |
| return nil |
| } |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits logic to push the specified input variable to the VM's stack. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "PushInput"}} |
| {{AssertType $.Type "Type"}} |
| {{AssertType $.Name "string"}} |
| |
| {{if (GetAnnotation $.Type "replay_remap")}} |
| if key, remap := {{$.Name}}.remap(ϟa, ϟs); remap { |
| loadRemap(ϟb, key, {{Template "Go.Replay.Type" $.Type}}, {{Template "Go.Replay.Value" "Type" $.Type "Name" $.Name}}) |
| } else { |
| ϟb.Push({{Template "Go.Replay.Value" "Type" $.Type "Name" $.Name}}) |
| } |
| {{else}} |
| ϟb.Push({{Template "Go.Replay.Value" "Type" $.Type "Name" $.Name}}) |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Declares the value method for a given pseudonym type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "DeclarePseudonymValue"}} |
| {{AssertType $ "Pseudonym"}} |
| |
| {{$u := $ | TypeOf | Underlying}} |
| {{if or (IsNumericType $u) (IsPointer $u)}} |
| {{if not (GetAnnotation $ "replay_custom_value")}} |
| {{$v := print (Macro "Go.Type" $.To) "(c)"}} |
| func (c {{$.Name}}) value(ϟb *builder.Builder, ϟa atom.Atom, ϟs *gfxapi.State) value.Value { return {{Template "Go.Replay.Value" "Type" $.To "Name" $v}} } |
| {{end}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Declares the value method for the given static array type. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "DeclareArrayValue"}} |
| {{AssertType $ "Array" "StaticArray"}} |
| |
| {{if not (or (Macro "IsInternal" $.ValueType) (IsAny $.ValueType))}} |
| func (arr {{Template "Go.Type" $}}) value(ϟb *builder.Builder, ϟa atom.Atom, ϟs *gfxapi.State) value.Pointer { |
| if len(arr) > 0 { |
| for _, e := range arr { |
| {{Template "PushInput" "Type" $.ValueType "Name" "e"}} |
| } |
| return ϟb.Buffer(len(arr)) |
| } else { |
| return value.AbsolutePointer(0) |
| } |
| } |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits a function info definition for each of the commands. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "DeclareBuilderFunctionInfos"}} |
| {{AssertType $ "API"}} |
| |
| {{range $i, $c := AllCommands $}} |
| var {{Template "BuilderFunctionInfo" $c}} = builder.FunctionInfo{§ |
| ID: {{$i}},§ |
| ReturnType: {{Template "Go.Replay.Type" $c.Return.Type}},§ |
| Parameters: {{len $c.CallParameters}},§ |
| } |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits the name of the variable holding the specified command's function id. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "BuilderFunctionInfo"}}{{AssertType $ "Function"}}funcInfo{{Template "Go.CmdName" $}}{{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| An override for the "Go.Statement" macro. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Statement"}} |
| {{ if IsFence $}}{{Template "Fence" $}} |
| {{else if IsReturn $}}{{/* no-op */}} |
| {{else}}{{Template "Go.Statement.Default" $}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| An override for the "Go.Fence" macro. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "Fence"}} |
| {{AssertType $ "Fence"}} |
| |
| {{$c := Global "CurrentCommand"}} |
| {{AssertType $c "Function"}} |
| |
| {{if not (IsNil $.Statement)}} |
| {{if IsCopy $.Statement}} |
| {{/* Apply the fenced-copy read */}} |
| {{/* TODO: Unlike Slice.Copy, this does not optimise for non-pointer copies. */}} |
| ϟdst, ϟsrc := {{Template "Go.Read" $.Statement.Dst}}, {{Template "Go.Read" $.Statement.Src}} |
| ϟcount := min(ϟdst.Count, ϟsrc.Count) |
| ϟdst, ϟsrc = ϟdst.Slice(0, ϟcount, ϟs), ϟsrc.Slice(0, ϟcount, ϟs) |
| ϟsrcElems := ϟsrc.Read(ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{end}} |
| {{end}} |
| |
| {{/* Push all the parameters on the stack */}} |
| {{range $p := $c.CallParameters}} |
| {{$type := TypeOf $p}} |
| {{$name := print "ϟa." (Macro "Go.Parameter" $p)}} |
| {{Template "PushInput" "Type" $type "Name" $name}} |
| {{end}} |
| |
| {{/* Call the function */}} |
| ϟb.Call({{Template "BuilderFunctionInfo" $c}}) |
| |
| {{/* Store the return value into a remapping table, if required */}} |
| {{$rty := TypeOf $c.Return}} |
| {{if (GetAnnotation $rty "replay_remap")}} |
| if key, remap := ϟa.Result.remap(ϟa, ϟs); remap { |
| ptr, found := ϟb.Remappings[key] |
| if !found { |
| ptr = ϟb.AllocateMemory({{Template "Go.SizeOf" $rty}}) |
| ϟb.Remappings[key] = ptr |
| } |
| ϟb.Clone(0) |
| ϟb.Store(ptr) |
| } |
| {{end}} |
| |
| {{/* Merge the observed writes into the application pool */}} |
| ϟa.observations.ApplyWrites(ϟs.Memory[memory.ApplicationPool]) |
| |
| {{/* Perform the fenced statement */}} |
| {{if not (IsNil $.Statement)}} |
| {{if IsCopy $.Statement}} |
| {{/* Apply the fenced-copy write */}} |
| ϟdst.Write(ϟsrcElems, ϟa, ϟs, ϟd, ϟl, ϟb) |
| {{else}} |
| {{Template "Go.Statement" $.Statement}} |
| {{end}} |
| {{end}} |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Emits additional methods used for replay generation for the Pointer type or |
| indirect type (Pseudonym) to Pointer. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "PointerReplayMethods"}} |
| {{AssertType $ "Pointer" "Pseudonym"}} |
| |
| {{$p := $ | Underlying | Unpack }} |
| {{$ptr_ty := Macro "Go.Type" $ }} |
| {{$el_ty := Macro "Go.Type" $p.To }} |
| {{$el_is_void := IsVoid ($p.To | Underlying | Unpack)}} |
| |
| func (p {{$ptr_ty}}) value() value.Pointer { |
| if p.Address != 0 { |
| return value.RemappedPointer(p.Address) |
| } else { |
| return value.AbsolutePointer(0) |
| } |
| } |
| {{end}} |