// Copyright 2018 The OPA Authors. All rights reserved. // Use of this source code is governed by an Apache2 // license that can be found in the LICENSE file. package module import ( "fmt" "strings" "github.com/open-policy-agent/opa/internal/wasm/instruction" "github.com/open-policy-agent/opa/internal/wasm/types" ) type ( // Module represents a WASM module. Module struct { Version uint32 Type TypeSection Import ImportSection Function FunctionSection Table TableSection Element ElementSection Global GlobalSection Export ExportSection Code RawCodeSection Data DataSection } // TypeSection represents a WASM type section. TypeSection struct { Functions []FunctionType } // ImportSection represents a WASM import section. ImportSection struct { Imports []Import } // FunctionSection represents a WASM function section. FunctionSection struct { TypeIndices []uint32 } // TableSection represents a WASM table section. TableSection struct { Tables []Table } // ElementSection represents a WASM element section. ElementSection struct { Segments []ElementSegment } // GlobalSection represents a WASM global section. GlobalSection struct { Globals []Global } // ExportSection represents a WASM export section. ExportSection struct { Exports []Export } // RawCodeSection represents a WASM code section. The code section is left as a // raw byte sequence. See CodeSection for the decoded version. RawCodeSection struct { Segments []RawCodeSegment } // DataSection represents a WASM data section. DataSection struct { Segments []DataSegment } // FunctionType represents a WASM function type definition. FunctionType struct { Params []types.ValueType Results []types.ValueType } // Import represents a WASM import statement. Import struct { Module string Name string Descriptor ImportDescriptor } // ImportDescriptor represents a WASM import descriptor. ImportDescriptor interface { fmt.Stringer Kind() ImportDescriptorType } // ImportDescriptorType defines allowed kinds of import descriptors. ImportDescriptorType int // FunctionImport represents a WASM function import statement. FunctionImport struct { Func uint32 } // MemoryImport represents a WASM memory import statement. MemoryImport struct { Mem MemType } // MemType defines the attributes of a memory import. MemType struct { Lim Limit } // TableImport represents a WASM table import statement. TableImport struct { Type types.ElementType Lim Limit } // ElementSegment represents a WASM element segment. ElementSegment struct { Index uint32 Offset Expr Indices []uint32 } // GlobalImport represents a WASM global variable import statement. GlobalImport struct { Type types.ValueType Mutable bool } // Limit represents a WASM limit. Limit struct { Min uint32 Max *uint32 } // Table represents a WASM table statement. Table struct { Type types.ElementType Lim Limit } // Global represents a WASM global statement. Global struct { Type types.ValueType Mutable bool Init Expr } // Export represents a WASM export statement. Export struct { Name string Descriptor ExportDescriptor } // ExportDescriptor represents a WASM export descriptor. ExportDescriptor struct { Type ExportDescriptorType Index uint32 } // ExportDescriptorType defines the allowed kinds of export descriptors. ExportDescriptorType int // RawCodeSegment represents a binary-encoded WASM code segment. RawCodeSegment struct { Code []byte } // DataSegment represents a WASM data segment. DataSegment struct { Index uint32 Offset Expr Init []byte } // Expr represents a WASM expression. Expr struct { Instrs []instruction.Instruction } // CodeEntry represents a code segment entry. CodeEntry struct { Func Function } // Function represents a function in a code segment. Function struct { Locals []LocalDeclaration Expr Expr } // LocalDeclaration represents a local variable declaration. LocalDeclaration struct { Count uint32 Type types.ValueType } ) // Defines the allowed kinds of imports. const ( FunctionImportType ImportDescriptorType = iota TableImportType MemoryImportType GlobalImportType ) func (x ImportDescriptorType) String() string { switch x { case FunctionImportType: return "func" case TableImportType: return "table" case MemoryImportType: return "memory" case GlobalImportType: return "global" } panic("illegal value") } // Defines the allowed kinds of exports. const ( FunctionExportType ExportDescriptorType = iota TableExportType MemoryExportType GlobalExportType ) func (x ExportDescriptorType) String() string { switch x { case FunctionExportType: return "func" case TableExportType: return "table" case MemoryExportType: return "memory" case GlobalExportType: return "global" } panic("illegal value") } // Kind returns the function import type kind. func (i FunctionImport) Kind() ImportDescriptorType { return FunctionImportType } func (i FunctionImport) String() string { return fmt.Sprintf("%v[type=%v]", i.Kind(), i.Func) } // Kind returns the memory import type kind. func (i MemoryImport) Kind() ImportDescriptorType { return MemoryImportType } func (i MemoryImport) String() string { return fmt.Sprintf("%v[%v]", i.Kind(), i.Mem.Lim) } // Kind returns the table import type kind. func (i TableImport) Kind() ImportDescriptorType { return TableImportType } func (i TableImport) String() string { return fmt.Sprintf("%v[%v, %v]", i.Kind(), i.Type, i.Lim) } // Kind returns the global import type kind. func (i GlobalImport) Kind() ImportDescriptorType { return GlobalImportType } func (i GlobalImport) String() string { return fmt.Sprintf("%v[%v, mut=%v]", i.Kind(), i.Type, i.Mutable) } func (tpe FunctionType) String() string { params := make([]string, len(tpe.Params)) results := make([]string, len(tpe.Results)) for i := range tpe.Params { params[i] = tpe.Params[i].String() } for i := range tpe.Results { results[i] = tpe.Results[i].String() } return "(" + strings.Join(params, ", ") + ") -> (" + strings.Join(results, ", ") + ")" } // Equal returns true if tpe equals other. func (tpe FunctionType) Equal(other FunctionType) bool { if len(tpe.Params) != len(other.Params) || len(tpe.Results) != len(other.Results) { return false } for i := range tpe.Params { if tpe.Params[i] != other.Params[i] { return false } } for i := range tpe.Results { if tpe.Results[i] != other.Results[i] { return false } } return true } func (imp Import) String() string { return fmt.Sprintf("%v %v.%v", imp.Descriptor.String(), imp.Module, imp.Name) } func (exp Export) String() string { return fmt.Sprintf("%v[%v] %v", exp.Descriptor.Type, exp.Descriptor.Index, exp.Name) } func (seg RawCodeSegment) String() string { return fmt.Sprintf("", len(seg.Code)) } func (seg DataSegment) String() string { return fmt.Sprintf("", seg.Index, seg.Offset, len(seg.Init)) } func (e Expr) String() string { return fmt.Sprintf("%d instr(s)", len(e.Instrs)) } func (lim Limit) String() string { if lim.Max == nil { return fmt.Sprintf("min=%v", lim.Min) } return fmt.Sprintf("min=%v max=%v", lim.Min, lim.Max) }