341 lines
7.2 KiB
Go
341 lines
7.2 KiB
Go
// 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("<code %d bytes>", len(seg.Code))
|
|
}
|
|
|
|
func (seg DataSegment) String() string {
|
|
return fmt.Sprintf("<data index=%v [%v] len=%d bytes>", 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)
|
|
}
|