Skip to content

Commit

Permalink
[help] Refactor command-line options and help reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
titzer authored Aug 26, 2024
2 parents 4be784c + 75d440e commit ee5ba33
Show file tree
Hide file tree
Showing 38 changed files with 313 additions and 295 deletions.
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function make_build_file() {

# compute sources
if [ "$PROGRAM" = "wizeng" ]; then
SOURCES="$ENGINE $WIZENG $WAVE $WASI $WALI $MONITORS"
SOURCES="$ENGINE $WAVE $WASI $WALI $MONITORS $WIZENG"
if [[ "$TARGET" = "x86-64-linux" || "$TARGET" = "x86_64_linux" ]]; then
SOURCES="$SOURCES $WASI_X86_64_LINUX $WALI_X86_64_LINUX"
fi
Expand Down
6 changes: 5 additions & 1 deletion issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,17 @@ Monitors + trace
- engine: gc, compile, load, verify
LoopMonitor track and display loop count distribution, improve display
ConstArgs track runtime function argument uniqueness to detect specialization/inlining opportunities
Interactive - show an interactive, terminal-animated view of execution, e.g. which function
func | xxx xx | <- color indicates how recent / hot
mem | ====== |



Test Coverage
--------------------------------
Interpreter
doCallHost of null host function
doCallFunction of host function
doCallFunction of host function
pushFrame of EXTERNREF, FUNCREF, RefNullFunc locals
traceCallHostFunction deeper than 0
loop unbounded
Expand Down
4 changes: 2 additions & 2 deletions src/engine/BinParser.v3
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class BinParser(extensions: Extension.set, limits: Limits, filename: string) ext
def err = ErrorGen.new(filename);
var tiering: ExecutionStrategy;
var validate_code = true;
var names = true;
var names = !TraceOptions.NO_NAMES.get();

private def cache = Canon.globalCache;
private var validator: CodeValidator;
Expand Down Expand Up @@ -153,7 +153,7 @@ class BinParser(extensions: Extension.set, limits: Limits, filename: string) ext
}
var payload = decoder.readN(payload_len);
module.custom_sections.put(CustomSection.new(name, payload));
if (EngineOptions.names && Strings.equal("name", name)) module.names = NameSection.new(module, payload);
if (names && Strings.equal("name", name)) module.names = NameSection.new(module, payload);
}
def readLoop(thing_name: string, count: int, read: int -> void) {
for (i < count) {
Expand Down
72 changes: 21 additions & 51 deletions src/engine/EngineOptions.v3
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,37 @@

// Parses command-line options that configure an engine.
component EngineOptions {
var stackSize = 512u * 1024u; // default value stack size
var jitFilter: DeclFilter; // debugging option to limit JIT compilations
var names = true; // recognize names section
var group = OptionsRegistry.newGroup("ENGINE", printHelp);
var extensions: Extension.set;
def DEFAULT_STACK_SIZE = 512u * 1024u;
def STACK_SIZE = group.newSizeOption("stack-size", DEFAULT_STACK_SIZE, "Initial stack size in bytes for Wasm execution stacks.");
def JIT_FILTER = group.newDeclFilterOption("jit-filter", "Filters functions compiled by the JIT.");
def X_ = OptionsRegistry.addParseFunc(parse);

def parse(engine: Engine, arg: string) -> bool {
if (arg == null) return false;
if (arg.length < 1 || arg[0] != '-') return false;
def parse(arg: string) -> bool {
if (Strings.startsWith(arg, "-ext:")) {
if (Strings.endsWithFrom(arg, 5, "all")) {
engine.extensions = Extension.set.all;
extensions = Extension.set.all;
return true;
}
for (e in Extension) {
if (Strings.endsWithFrom(arg, 5, e.short_name)) {
engine.extensions |= Extensions.setImplications(e);
extensions |= Extensions.setImplications(e);
return true;
}
}
}
if (Strings.startsWith(arg, "-stack-size=")) {
stackSize = parseSize(arg, 12);
Trace.OUT.put1("stack size = %d", stackSize).ln();
return true;
}
if (Strings.startsWith(arg, "-mode=")) {
return ExecuteOptions.setMode(arg[6 ...]);
}
if (Strings.equal(arg, "-no-names")) {
EngineOptions.names = false;
return true;
}
var jitFilterEq = "-jit-filter=";
if (Strings.startsWith(arg, jitFilterEq)) {
var pat: string;
if (arg.length > jitFilterEq.length) {
pat = Arrays.range(arg, jitFilterEq.length, arg.length);
}
jitFilter = DeclFilters.parseString(pat);
return true;
}
return false;
}
def parseSize(str: string, pos: int) -> u32 {
var len = str.length;
var last = str[len - 1], scale = 1u, max = u32.max;
match(last) {
'k', 'K' => { scale = 1024u; max = 4194304u; len--; }
'm', 'M' => { scale = 1048576u; max = 4096u; len--; }
'g', 'G' => { scale = 1073741824u; max = 4u; len--; }
}
var p = Ints.parsePosDecimal(str, pos);
if (pos + p.0 == len) {
if (p.1 >= max) return u32.max;
return p.1 * scale;
}
return 0;
}
def printHelp() {
var out = Trace.OUT, H = out.putsln;
H("ENGINE OPTIONS");
H("");
H("Wizard supports a number of WebAssembly extensions. None are enabled by default.");
H("Each extension can be enabled independently with its own flag. Some extensions imply");
H("other extensions as indicated below.");
H("");
def printHelp(out: TraceBuilder) {
var H = out.putsln, L = out.ln;
H("Wizard supports a number of engine-wide options which enable extensions and configure");
H("the execution mode. Each extension can be enabled independently with its own flag.");
H("Some extensions imply other extensions as indicated below.");
L();

for (e in Extension) {
out.puts(" -ext:");
Expand All @@ -90,7 +56,11 @@ component EngineOptions {
out.ln();
}
}
H("");
ExecuteOptions.printHelp();
L();
ExecuteOptions.printHelp(out);
L();
H("Other engine configuration options include:");
L();
group.print(out);
}
}
13 changes: 5 additions & 8 deletions src/engine/Execute.v3
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,10 @@ component ExecuteOptions {
return false;
}
// Print help for the supported modes.
def printHelp() {
var out = Trace.OUT, H = out.putsln;
H("");
H("This build of the Wizard Engine responds to the execution mode flag in the following ways.");
H("");
def printHelp(out: TraceBuilder) {
var H = out.putsln, L = out.ln;
H("This build of the Wizard Engine supports the following execution modes:");
L();
for (l = modes; l != null; l = l.tail) {
var t = l.head;
out.puts(" -mode=");
Expand All @@ -219,7 +218,5 @@ component ExecuteOptions {
out.puts(t.2);
out.ln();
}

H("");
}
}
}
22 changes: 0 additions & 22 deletions src/engine/Metrics.v3
Original file line number Diff line number Diff line change
Expand Up @@ -99,28 +99,6 @@ component Metrics {
}
}

// Parses and enables collection/reporting of metrics based on arguments.
component MetricOptions {
// TODO: print help for metrics option
// Parse command-line argument and update metric collection. Return {true} if the
// argument was matched as a trace flag.
def parse(arg: string) -> bool {
if (Strings.equal(arg, "--metrics")) {
Metrics.enableAll();
return true;
}
var prefix = "--metrics=";
if (Strings.startsWith(arg, prefix)) {
var pat = Arrays.range(arg, prefix.length, arg.length);
var glob = GlobMatcher.new(pat);
Metrics.enable(glob);
return true;
}
return false;
}
// TODO: help
}

// Internal representation of a metric.
class Metric(name: string, units: string, help: string) {
var enabled: bool;
Expand Down
51 changes: 32 additions & 19 deletions src/engine/TraceOptions.v3
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ enum TraceOption(ch: byte, help: string) {

// Parses and updates trace options based on arguments.
component TraceOptions {
def group = OptionsRegistry.newGroup("TRACING", printHelp);
def NO_NAMES = group.newBoolOption("no-names", false, "Disables parsing and reporting from the name section.");
def COLORS = group.newBoolOption("colors", true, "Enable or disable terminal colors.")
.onSet(Palettes.reset);
def FATAL = group.newFlag("fatal", setFatal, "Aborts upon parsing, validation, or test failure.");
def X_ = OptionsRegistry.addParseFunc(parse);

def setFatal(str: string) {
if (str == null || Strings.equal(str, "true")) Trace.fatal = true;
}
// Parse command-line argument and update trace flags. Return {true} if the
// argument was matched as a trace flag.
def parse(arg: string) -> bool {
Expand Down Expand Up @@ -48,8 +58,6 @@ component TraceOptions {
Trace.callsFilter = DeclFilters.parseString(pat);
return true;
}
} else if (Strings.equal(arg, "-fatal")) {
return Trace.fatal = true;
} else if (Strings.startsWith(arg, "-t")) {
for (i = 2; i < arg.length; i++) {
var ch = arg[i];
Expand All @@ -59,6 +67,17 @@ component TraceOptions {
}
return true;
}
if (Strings.equal(arg, "--metrics")) {
Metrics.enableAll();
return true;
}
var prefix = "--metrics=";
if (Strings.startsWith(arg, prefix)) {
var pat = Arrays.range(arg, prefix.length, arg.length);
var glob = GlobMatcher.new(pat);
Metrics.enable(glob);
return true;
}
return false;
}
private def setOption(opt: TraceOption) {
Expand All @@ -78,19 +97,16 @@ component TraceOptions {
whamm => Trace.whamm = true;
}
}
def printHelp() {
var out = Trace.OUT, H = out.putsln;
H("");
H("TRACE OPTIONS");
H("");
def printHelp(out: TraceBuilder) {
var H = out.putsln, L = out.ln;
H("A number of tracing options enable debugging output from various components of the engine.");
H("These options help debug both the engine and wasm modules, including ones that are");
H("malformed or have type errors.");
H("Note that the '-t' short form supports multiple combined options, such as '-tiov'.");
H("");
L();

for (t in TraceOption) {
out.puts(" -t");
out.puts(" -t");
out.putc(t.ch);
out.puts(" --trace-");
out.puts(t.name);
Expand All @@ -99,19 +115,16 @@ component TraceOptions {
out.puts(t.help);
out.ln();
}
H("");
H(" --trace-module=[<module pattern*>]");
L();
H(" --trace-module[=<module pattern*>]");
H(" Trace calls into the given module(s).");

H("");
H(" --trace-calls=[<function pattern*>]");
H(" --trace-calls[=<function pattern*>]");
H(" Trace calls into and out of the given functions(s). The pattern can use function");
H(" names from the module or function indexes.");

H("");
out.puts(" -fatal");
out.pad(' ', 32);
out.puts("print stack trace and exit on module errors");
out.ln().ln();
L();
H(" --metrics[=<pattern*>]");
H(" Reports the given metrics.");
group.print(out);
}
}
2 changes: 1 addition & 1 deletion src/engine/x86-64/X86_64Stack.v3
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ component X86_64StackManager {
var cache: X86_64Stack;

def getFreshStack() -> X86_64Stack {
if (cache == null) return X86_64Stack.new(EngineOptions.stackSize);
if (cache == null) return X86_64Stack.new(EngineOptions.STACK_SIZE.get());
var result = cache;
cache = null;
return result;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/x86-64/X86_64Target.v3
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def allocateCodeForModule(module: Module, codeSize: int) {
}

def applyJitFilter(module: Module, func: FuncDecl, how: string) -> bool {
var filter = EngineOptions.jitFilter;
var filter = EngineOptions.JIT_FILTER.get();
if (filter == null || filter.matches(module, func)) return true;
Trace.OUT.put2("func[%d] %s compile suppressed by filter", func.func_index, how).ln();
return false;
Expand Down
3 changes: 2 additions & 1 deletion src/modules/ModuleRegistry.v3
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ component ModuleRegistry {
def add(m: HostModule, exposed: bool) {
map[m.name] = (m, exposed);
}
def expose(glob: GlobMatcher) {
def expose(pattern: string) {
var glob = GlobMatcher.new(pattern);
for (l = Maps.keyList(map); l != null; l = l.tail) {
var n = l.head;
if (glob.matches(n)) map[n] = (map[n].0, true);
Expand Down
Loading

0 comments on commit ee5ba33

Please sign in to comment.