mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-19 16:42:33 +00:00
Parse custom sections target_features and name
This commit is contained in:
@@ -90,6 +90,7 @@ Function :: struct {
|
||||
Module :: struct {
|
||||
version: u32,
|
||||
sections: []Section,
|
||||
customs: []Custom_Section,
|
||||
types: []Func_Type,
|
||||
imports: []Import,
|
||||
functions: []Function, // whole function index space (imports + defined)
|
||||
@@ -101,6 +102,58 @@ Module :: struct {
|
||||
allocator: runtime.Allocator,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Custom Section Layout
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Custom_Section :: struct {
|
||||
section: Section,
|
||||
variant: union {
|
||||
Custom_Section_Name,
|
||||
Custom_Section_Target_Features,
|
||||
},
|
||||
}
|
||||
|
||||
Custom_Section_Name_Function :: struct {
|
||||
id: u32,
|
||||
name: string, // borrowed
|
||||
}
|
||||
|
||||
Custom_Section_Name_Local :: struct {
|
||||
idx: u32,
|
||||
name: string, // borrowed
|
||||
}
|
||||
|
||||
Custom_Section_Name_Function_Locals :: struct {
|
||||
func_idx: u32,
|
||||
locals: []Custom_Section_Name_Local,
|
||||
}
|
||||
|
||||
Custom_Section_Name :: struct {
|
||||
module_name: string,
|
||||
functions: []Custom_Section_Name_Function,
|
||||
locals: []Custom_Section_Name_Function_Locals,
|
||||
}
|
||||
|
||||
Custom_Section_Target_Feature_Prefix :: enum u8 {
|
||||
Used = '+',
|
||||
Disallowed = '-',
|
||||
Required = '=',
|
||||
}
|
||||
|
||||
Custom_Section_Target_Feature :: struct {
|
||||
prefix: Custom_Section_Target_Feature_Prefix,
|
||||
feature: string, // borrowed
|
||||
}
|
||||
|
||||
|
||||
Custom_Section_Target_Features :: struct {
|
||||
features: []Custom_Section_Target_Feature,
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Small display helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -191,6 +191,9 @@ parse :: proc(data: []u8, allocator := context.allocator) -> (m: Module, err: Re
|
||||
}
|
||||
}
|
||||
|
||||
parse_custom_sections(&m, allocator) or_return
|
||||
|
||||
|
||||
build_functions(&m, func_typeidx, codes, allocator) or_return
|
||||
apply_name_section(&m)
|
||||
return
|
||||
@@ -289,6 +292,86 @@ parse_code :: proc(r: ^Reader, allocator: runtime.Allocator) -> (out: []Code_Bod
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
parse_custom_sections :: proc(m: ^Module, allocator: runtime.Allocator) -> Reader_Error {
|
||||
custom_count := 0
|
||||
for &sec in m.sections {
|
||||
if sec.id == .CUSTOM {
|
||||
custom_count += 1
|
||||
}
|
||||
}
|
||||
m.customs = make([]Custom_Section, custom_count, allocator) or_return
|
||||
custom_index := 0
|
||||
for &sec in m.sections {
|
||||
if sec.id != .CUSTOM {
|
||||
continue
|
||||
}
|
||||
|
||||
custom := &m.customs[custom_index]
|
||||
custom_index += 1
|
||||
|
||||
custom.section = sec
|
||||
|
||||
section_data := m.data[sec.offset:][:sec.size]
|
||||
r := reader(section_data, 0)
|
||||
sec_name := rd_name(&r) or_continue
|
||||
assert(sec_name == sec.name)
|
||||
|
||||
custom_block: switch sec.name {
|
||||
case "name":
|
||||
cname: Custom_Section_Name
|
||||
defer custom.variant = cname
|
||||
|
||||
for r.off < u32(len(r.data)) {
|
||||
id := rd_byte(&r) or_return
|
||||
size := rd_u32(&r) or_return
|
||||
end_off := r.off+size
|
||||
defer r.off = end_off
|
||||
|
||||
switch id {
|
||||
case 0: // module
|
||||
cname.module_name = rd_name(&r) or_return
|
||||
case 1: // functions
|
||||
count := rd_u32(&r) or_return
|
||||
cname.functions = make([]Custom_Section_Name_Function, count, allocator) or_return
|
||||
for &func in cname.functions {
|
||||
func.id = rd_u32(&r) or_return
|
||||
func.name = rd_name(&r) or_return
|
||||
}
|
||||
case 2: // locals
|
||||
count := rd_u32(&r) or_return
|
||||
|
||||
cname.locals = make([]Custom_Section_Name_Function_Locals, count, allocator) or_return
|
||||
|
||||
for &local_func in cname.locals {
|
||||
local_func.func_idx = rd_u32(&r) or_return
|
||||
local_count := rd_u32(&r) or_return
|
||||
local_func.locals = make([]Custom_Section_Name_Local, local_count, allocator) or_return
|
||||
for &local in local_func.locals {
|
||||
local.idx = rd_u32(&r) or_return
|
||||
local.name = rd_name(&r) or_return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "target_features":
|
||||
target_features: Custom_Section_Target_Features
|
||||
defer custom.variant = target_features
|
||||
|
||||
count := rd_u32(&r) or_return
|
||||
target_features.features = make([]Custom_Section_Target_Feature, count, allocator) or_return
|
||||
|
||||
for &feature in target_features.features {
|
||||
feature.prefix = Custom_Section_Target_Feature_Prefix(rd_byte(&r) or_return)
|
||||
feature.feature = rd_name(&r) or_return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
build_functions :: proc(m: ^Module, func_typeidx: []u32, codes: []Code_Body, allocator: runtime.Allocator) -> runtime.Allocator_Error {
|
||||
num_imports := 0
|
||||
@@ -393,6 +476,19 @@ module_destroy :: proc(m: ^Module) {
|
||||
delete(f.locals, m.allocator)
|
||||
}
|
||||
}
|
||||
for c in m.customs {
|
||||
switch v in c.variant {
|
||||
case Custom_Section_Name:
|
||||
for function_locals in v.locals {
|
||||
delete(function_locals.locals, m.allocator)
|
||||
}
|
||||
delete(v.functions, m.allocator)
|
||||
delete(v.locals, m.allocator)
|
||||
case Custom_Section_Target_Features:
|
||||
delete(v.features)
|
||||
}
|
||||
}
|
||||
delete(m.customs, m.allocator)
|
||||
delete(m.sections, m.allocator)
|
||||
delete(m.types, m.allocator)
|
||||
delete(m.imports, m.allocator)
|
||||
|
||||
@@ -5,12 +5,12 @@ import "core:os"
|
||||
import "core:fmt"
|
||||
import wasm "../"
|
||||
|
||||
print_module :: proc(m: Module) {
|
||||
print_module :: proc(m: Module, file: ^os.File) {
|
||||
sb := strings.builder_make(context.allocator)
|
||||
defer strings.builder_destroy(&sb)
|
||||
sbprint_module(&sb, m)
|
||||
s := strings.to_string(sb)
|
||||
os.write_string(os.stdout, s)
|
||||
os.write_string(file, s)
|
||||
}
|
||||
|
||||
sbprint_module :: proc(sb: ^strings.Builder, m: Module) {
|
||||
@@ -69,11 +69,45 @@ sbprint_module :: proc(sb: ^strings.Builder, m: Module) {
|
||||
}
|
||||
strings.write_byte(sb, '\n')
|
||||
|
||||
data := m.data[sec.offset:][:sec.size]
|
||||
section_data := m.data[sec.offset:][:sec.size]
|
||||
|
||||
section_printing: #partial switch sec.id {
|
||||
case .CUSTOM:
|
||||
for c in m.customs {
|
||||
if c.section != sec {
|
||||
continue
|
||||
}
|
||||
switch v in c.variant {
|
||||
case Custom_Section_Name:
|
||||
if v.module_name != "" {
|
||||
fmt.sbprintf(sb, " module: %q\n", v.module_name)
|
||||
}
|
||||
if len(v.functions) > 0 {
|
||||
fmt.sbprintf(sb, " functions:\n")
|
||||
for f in v.functions {
|
||||
fmt.sbprintf(sb, " [%d] %q\n", f.id, f.name)
|
||||
}
|
||||
}
|
||||
if len(v.locals) > 0 {
|
||||
fmt.sbprintf(sb, " locals:\n")
|
||||
for fl in v.locals {
|
||||
fmt.sbprintf(sb, " [%d] function\n", fl.func_idx)
|
||||
for local in fl.locals {
|
||||
fmt.sbprintf(sb, " [%d] %q\n", local.idx, local.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
case Custom_Section_Target_Features:
|
||||
for f in v.features {
|
||||
fmt.sbprintf(sb, " \"%c%s\"\n", u8(f.prefix), f.feature)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
strings.write_byte(sb, '\n')
|
||||
|
||||
case .DATA:
|
||||
r := reader(data, 0)
|
||||
r := reader(section_data, 0)
|
||||
count := rd_u32(&r) or_break section_printing
|
||||
assert(count == sec.count)
|
||||
for i in 0..<sec.count {
|
||||
@@ -108,7 +142,7 @@ sbprint_module :: proc(sb: ^strings.Builder, m: Module) {
|
||||
}
|
||||
}
|
||||
case .MEMORY:
|
||||
r := reader(data, 0)
|
||||
r := reader(section_data, 0)
|
||||
count := rd_u32(&r) or_break section_printing
|
||||
assert(count == sec.count)
|
||||
for i in 0..<sec.count {
|
||||
|
||||
Reference in New Issue
Block a user