Parse custom sections target_features and name

This commit is contained in:
gingerBill
2026-06-17 13:42:26 +01:00
parent 53fe193868
commit b6fdabc874
3 changed files with 188 additions and 5 deletions

View File

@@ -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
// -----------------------------------------------------------------------------

View File

@@ -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)

View File

@@ -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 {