dev/perf-host-debug-overlay-isolation #14
@ -96,6 +96,62 @@ pub struct SyscallRegistryEntry {
|
||||
pub meta: SyscallMeta,
|
||||
}
|
||||
|
||||
impl SyscallRegistryEntry {
|
||||
/// Starts the builder with mandatory fields and sensible default values.
|
||||
pub const fn builder(syscall: Syscall, module: &'static str, name: &'static str) -> Self {
|
||||
Self {
|
||||
syscall,
|
||||
meta: SyscallMeta {
|
||||
id: syscall as u32,
|
||||
module,
|
||||
name,
|
||||
version: 1, // Default for new syscalls
|
||||
arg_slots: 0,
|
||||
ret_slots: 0,
|
||||
caps: 0,
|
||||
determinism: Determinism::Deterministic,
|
||||
may_allocate: false,
|
||||
cost_hint: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn version(mut self, n: u16) -> Self {
|
||||
self.meta.version = n;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn args(mut self, n: u8) -> Self {
|
||||
self.meta.arg_slots = n;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn rets(mut self, n: u16) -> Self {
|
||||
self.meta.ret_slots = n;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn caps(mut self, caps: CapFlags) -> Self {
|
||||
self.meta.caps = caps;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn non_deterministic(mut self) -> Self {
|
||||
self.meta.determinism = Determinism::NonDeterministic;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn may_allocate(mut self) -> Self {
|
||||
self.meta.may_allocate = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub const fn cost(mut self, cost: u32) -> Self {
|
||||
self.meta.cost_hint = cost;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_for(syscall: Syscall) -> &'static SyscallMeta {
|
||||
registry::meta_for(syscall)
|
||||
}
|
||||
|
||||
@ -1,53 +1,27 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::AssetLoad,
|
||||
"asset",
|
||||
"load",
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
caps::ASSET,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::AssetStatus,
|
||||
"asset",
|
||||
"status",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::ASSET,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
entry(
|
||||
Syscall::AssetCommit,
|
||||
"asset",
|
||||
"commit",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::ASSET,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::AssetCancel,
|
||||
"asset",
|
||||
"cancel",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::ASSET,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::AssetLoad, "asset", "load")
|
||||
.args(2)
|
||||
.rets(2)
|
||||
.caps(caps::ASSET)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::AssetStatus, "asset", "status")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::ASSET)
|
||||
.non_deterministic(),
|
||||
SyscallRegistryEntry::builder(Syscall::AssetCommit, "asset", "commit")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::ASSET)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::AssetCancel, "asset", "cancel")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::ASSET)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
];
|
||||
|
||||
@ -1,29 +1,14 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::AudioPlaySample,
|
||||
"audio",
|
||||
"play_sample",
|
||||
1,
|
||||
5,
|
||||
1,
|
||||
caps::AUDIO,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::AudioPlay,
|
||||
"audio",
|
||||
"play",
|
||||
1,
|
||||
7,
|
||||
1,
|
||||
caps::AUDIO,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::AudioPlaySample, "audio", "play_sample")
|
||||
.args(5)
|
||||
.rets(1)
|
||||
.caps(caps::AUDIO)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::AudioPlay, "audio", "play")
|
||||
.args(7)
|
||||
.rets(1)
|
||||
.caps(caps::AUDIO)
|
||||
.cost(5),
|
||||
];
|
||||
|
||||
@ -1,29 +1,12 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::BankInfo,
|
||||
"bank",
|
||||
"info",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::BANK,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
entry(
|
||||
Syscall::BankSlotInfo,
|
||||
"bank",
|
||||
"slot_info",
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
caps::BANK,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::BankInfo, "bank", "info")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::BANK),
|
||||
SyscallRegistryEntry::builder(Syscall::BankSlotInfo, "bank", "slot_info")
|
||||
.args(2)
|
||||
.rets(1)
|
||||
.caps(caps::BANK),
|
||||
];
|
||||
|
||||
@ -1,150 +1,68 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::FsOpen,
|
||||
"fs",
|
||||
"open",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::FsRead,
|
||||
"fs",
|
||||
"read",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::FsWrite,
|
||||
"fs",
|
||||
"write",
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(Syscall::FsClose, "fs", "close", 1, 1, 0, caps::FS, Determinism::Deterministic, false, 5),
|
||||
entry(
|
||||
Syscall::FsListDir,
|
||||
"fs",
|
||||
"list_dir",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::FsExists,
|
||||
"fs",
|
||||
"exists",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
entry(
|
||||
Syscall::FsDelete,
|
||||
"fs",
|
||||
"delete",
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotCount,
|
||||
"mem",
|
||||
"slot_count",
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
caps::FS,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotStat,
|
||||
"mem",
|
||||
"slot_stat",
|
||||
1,
|
||||
1,
|
||||
5,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotRead,
|
||||
"mem",
|
||||
"slot_read",
|
||||
1,
|
||||
3,
|
||||
3,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotWrite,
|
||||
"mem",
|
||||
"slot_write",
|
||||
1,
|
||||
3,
|
||||
2,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotCommit,
|
||||
"mem",
|
||||
"slot_commit",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::MemSlotClear,
|
||||
"mem",
|
||||
"slot_clear",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
caps::FS,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::FsOpen, "fs", "open")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::FsRead, "fs", "read")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::FsWrite, "fs", "write")
|
||||
.args(2)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::FsClose, "fs", "close").args(1).caps(caps::FS).cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::FsListDir, "fs", "list_dir")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::FsExists, "fs", "exists").args(1).rets(1).caps(caps::FS),
|
||||
SyscallRegistryEntry::builder(Syscall::FsDelete, "fs", "delete")
|
||||
.args(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotCount, "mem", "slot_count")
|
||||
.rets(2)
|
||||
.caps(caps::FS),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotStat, "mem", "slot_stat")
|
||||
.args(1)
|
||||
.rets(5)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotRead, "mem", "slot_read")
|
||||
.args(3)
|
||||
.rets(3)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotWrite, "mem", "slot_write")
|
||||
.args(3)
|
||||
.rets(2)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotCommit, "mem", "slot_commit")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::MemSlotClear, "mem", "slot_clear")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::FS)
|
||||
.non_deterministic()
|
||||
.cost(20),
|
||||
];
|
||||
|
||||
@ -1,113 +1,41 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::GfxClear,
|
||||
"gfx",
|
||||
"clear",
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxFillRect,
|
||||
"gfx",
|
||||
"fill_rect",
|
||||
1,
|
||||
5,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxDrawLine,
|
||||
"gfx",
|
||||
"draw_line",
|
||||
1,
|
||||
5,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxDrawCircle,
|
||||
"gfx",
|
||||
"draw_circle",
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxDrawDisc,
|
||||
"gfx",
|
||||
"draw_disc",
|
||||
1,
|
||||
5,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxDrawSquare,
|
||||
"gfx",
|
||||
"draw_square",
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxSetSprite,
|
||||
"gfx",
|
||||
"set_sprite",
|
||||
1,
|
||||
10,
|
||||
1,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxDrawText,
|
||||
"gfx",
|
||||
"draw_text",
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
entry(
|
||||
Syscall::GfxClear565,
|
||||
"gfx",
|
||||
"clear_565",
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
caps::GFX,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
20,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxClear, "gfx", "clear")
|
||||
.args(1)
|
||||
.caps(caps::GFX)
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxFillRect, "gfx", "fill_rect")
|
||||
.args(5)
|
||||
.caps(caps::GFX)
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxDrawLine, "gfx", "draw_line")
|
||||
.args(5)
|
||||
.caps(caps::GFX)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxDrawCircle, "gfx", "draw_circle")
|
||||
.args(4)
|
||||
.caps(caps::GFX)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxDrawDisc, "gfx", "draw_disc")
|
||||
.args(5)
|
||||
.caps(caps::GFX)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxDrawSquare, "gfx", "draw_square")
|
||||
.args(6)
|
||||
.caps(caps::GFX)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxSetSprite, "gfx", "set_sprite")
|
||||
.args(10)
|
||||
.rets(1)
|
||||
.caps(caps::GFX)
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxDrawText, "gfx", "draw_text")
|
||||
.args(4)
|
||||
.caps(caps::GFX)
|
||||
.cost(20),
|
||||
SyscallRegistryEntry::builder(Syscall::GfxClear565, "gfx", "clear_565")
|
||||
.args(1)
|
||||
.caps(caps::GFX)
|
||||
.cost(20),
|
||||
];
|
||||
|
||||
@ -1,29 +1,14 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::LogWrite,
|
||||
"log",
|
||||
"write",
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
caps::LOG,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
entry(
|
||||
Syscall::LogWriteTag,
|
||||
"log",
|
||||
"write_tag",
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
caps::LOG,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
5,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::LogWrite, "log", "write")
|
||||
.args(2)
|
||||
.caps(caps::LOG)
|
||||
.non_deterministic()
|
||||
.cost(5),
|
||||
SyscallRegistryEntry::builder(Syscall::LogWriteTag, "log", "write_tag")
|
||||
.args(3)
|
||||
.caps(caps::LOG)
|
||||
.non_deterministic()
|
||||
.cost(5),
|
||||
];
|
||||
|
||||
@ -6,36 +6,7 @@ mod gfx;
|
||||
mod log;
|
||||
mod system;
|
||||
|
||||
use super::{CapFlags, Determinism, Syscall, SyscallMeta, SyscallRegistryEntry};
|
||||
|
||||
pub(crate) const fn entry(
|
||||
syscall: Syscall,
|
||||
module: &'static str,
|
||||
name: &'static str,
|
||||
version: u16,
|
||||
arg_slots: u8,
|
||||
ret_slots: u16,
|
||||
caps: CapFlags,
|
||||
determinism: Determinism,
|
||||
may_allocate: bool,
|
||||
cost_hint: u32,
|
||||
) -> SyscallRegistryEntry {
|
||||
SyscallRegistryEntry {
|
||||
syscall,
|
||||
meta: SyscallMeta {
|
||||
id: syscall as u32,
|
||||
module,
|
||||
name,
|
||||
version,
|
||||
arg_slots,
|
||||
ret_slots,
|
||||
caps,
|
||||
determinism,
|
||||
may_allocate,
|
||||
cost_hint,
|
||||
},
|
||||
}
|
||||
}
|
||||
use super::SyscallRegistryEntry;
|
||||
|
||||
pub(crate) fn all_entries() -> impl Iterator<Item = &'static SyscallRegistryEntry> {
|
||||
system::ENTRIES
|
||||
|
||||
@ -1,29 +1,11 @@
|
||||
use super::entry;
|
||||
use crate::syscalls::{Determinism, Syscall, SyscallRegistryEntry, caps};
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
entry(
|
||||
Syscall::SystemHasCart,
|
||||
"system",
|
||||
"has_cart",
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
caps::SYSTEM,
|
||||
Determinism::Deterministic,
|
||||
false,
|
||||
1,
|
||||
),
|
||||
entry(
|
||||
Syscall::SystemRunCart,
|
||||
"system",
|
||||
"run_cart",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
caps::SYSTEM,
|
||||
Determinism::NonDeterministic,
|
||||
false,
|
||||
50,
|
||||
),
|
||||
SyscallRegistryEntry::builder(Syscall::SystemHasCart, "system", "has_cart")
|
||||
.rets(1)
|
||||
.caps(caps::SYSTEM),
|
||||
SyscallRegistryEntry::builder(Syscall::SystemRunCart, "system", "run_cart")
|
||||
.caps(caps::SYSTEM)
|
||||
.non_deterministic()
|
||||
.cost(50),
|
||||
];
|
||||
|
||||
@ -146,10 +146,10 @@ impl Verifier {
|
||||
|
||||
let func_code = &code[func_start..func_end];
|
||||
|
||||
// Funções vazias (sem qualquer byte de código) são consideradas válidas no verificador.
|
||||
// Elas não consomem nem produzem valores na pilha e não possuem fluxo interno.
|
||||
// Observação: se uma função vazia for chamada em tempo de execução e retorno/efeitos
|
||||
// forem esperados, caberá ao gerador de código/linker impedir tal situação.
|
||||
// Empty functions (no code bytes) are considered valid in the verifier.
|
||||
// They do not consume or produce values on the stack and have no internal flow.
|
||||
// Note: if an empty function is called at runtime and return/effects
|
||||
// are expected, it is the responsibility of the code generator/linker to prevent this situation.
|
||||
if func_code.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user