mirror of
https://github.com/decompme/decomp.me.git
synced 2026-02-20 13:29:14 -06:00
Allow specifying custom objdump flags (#427)
* Trying to add a new section * objdump section is no longer borken * objdump section is a bit more independent from the compilerargs one * add objdump_flags to database * Allow to save objdump flags on change * Actually pass the objdump flags to objdump * Allow adding objdump flags to presets * add short description to compilers.json * filter_objdump_flags * Introduce GCCMIPSCompiler class * Add -M gekko / broadway by default for gc/wii compilers * format autogenerated file * type annotation * Disable enum trailing comma warnings on Majora's Mask * wip * flags as array, backend parsing, frontend cleanup * style scratch options * loose ends * only show diff opts section if there are any options to show * fix mypy Co-authored-by: Ethan Roseman <ethteck@gmail.com> Co-authored-by: Alex Bates <alex@nanaian.town>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from functools import cache
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import ClassVar, Dict, List, Optional, OrderedDict
|
||||
|
||||
@@ -11,7 +11,6 @@ from coreapp.flags import (
|
||||
COMMON_IDO_FLAGS,
|
||||
COMMON_MWCC_FLAGS,
|
||||
COMMON_GCC_PS1_FLAGS,
|
||||
FlagSet,
|
||||
Flags,
|
||||
)
|
||||
|
||||
@@ -49,14 +48,16 @@ class Compiler:
|
||||
@dataclass(frozen=True)
|
||||
class Preset:
|
||||
name: str
|
||||
flags: str
|
||||
compiler: Compiler
|
||||
flags: str
|
||||
diff_flags: list[str] = field(default_factory=list)
|
||||
|
||||
def to_json(self) -> Dict[str, str]:
|
||||
def to_json(self) -> Dict[str, object]:
|
||||
return {
|
||||
"name": self.name,
|
||||
"flags": self.flags,
|
||||
"compiler": self.compiler.id,
|
||||
"flags": self.flags,
|
||||
"diff_flags": self.diff_flags,
|
||||
}
|
||||
|
||||
|
||||
@@ -553,128 +554,133 @@ _all_presets = [
|
||||
# GBA
|
||||
Preset(
|
||||
"Rhythm Tengoku",
|
||||
"-mthumb-interwork -Wparentheses -O2 -fhex-asm",
|
||||
AGBCC,
|
||||
"-mthumb-interwork -Wparentheses -O2 -fhex-asm",
|
||||
),
|
||||
Preset(
|
||||
"The Minish Cap",
|
||||
"-O2 -Wimplicit -Wparentheses -Werror -Wno-multichar -g3",
|
||||
AGBCC,
|
||||
"-O2 -Wimplicit -Wparentheses -Werror -Wno-multichar -g3",
|
||||
),
|
||||
Preset(
|
||||
"Mother 3",
|
||||
"-fno-exceptions -fno-rtti -fhex-asm -mthumb-interwork -Wimplicit -Wparentheses -O2 -g3",
|
||||
AGBCCPP,
|
||||
"-fno-exceptions -fno-rtti -fhex-asm -mthumb-interwork -Wimplicit -Wparentheses -O2 -g3",
|
||||
),
|
||||
# Switch
|
||||
Preset(
|
||||
"Super Mario Odyssey",
|
||||
"-x c++ -O3 -g2 -std=c++1z -fno-rtti -fno-exceptions -Wall -Wextra -Wdeprecated -Wno-unused-parameter -Wno-unused-private-field -fno-strict-aliasing -Wno-invalid-offsetof -D SWITCH -D NNSDK -D MATCHING_HACK_NX_CLANG",
|
||||
CLANG_391,
|
||||
"-x c++ -O3 -g2 -std=c++1z -fno-rtti -fno-exceptions -Wall -Wextra -Wdeprecated -Wno-unused-parameter -Wno-unused-private-field -fno-strict-aliasing -Wno-invalid-offsetof -D SWITCH -D NNSDK -D MATCHING_HACK_NX_CLANG",
|
||||
),
|
||||
Preset(
|
||||
"Breath of the Wild",
|
||||
"-x c++ -O3 -g2 -std=c++1z -fno-rtti -fno-exceptions -Wall -Wextra -Wdeprecated -Wno-unused-parameter -Wno-unused-private-field -fno-strict-aliasing -Wno-invalid-offsetof -D SWITCH -D NNSDK -D MATCHING_HACK_NX_CLANG",
|
||||
CLANG_401,
|
||||
"-x c++ -O3 -g2 -std=c++1z -fno-rtti -fno-exceptions -Wall -Wextra -Wdeprecated -Wno-unused-parameter -Wno-unused-private-field -fno-strict-aliasing -Wno-invalid-offsetof -D SWITCH -D NNSDK -D MATCHING_HACK_NX_CLANG",
|
||||
),
|
||||
# PS1
|
||||
Preset(
|
||||
"Castlevania: Symphony of the Night",
|
||||
"-O2 -G0 -funsigned-char",
|
||||
GCC263_MIPSEL,
|
||||
"-O2 -G0 -funsigned-char",
|
||||
),
|
||||
Preset(
|
||||
"Evo's Sapce Adventures",
|
||||
"-O2",
|
||||
PSYQ46,
|
||||
"-O2",
|
||||
),
|
||||
# N64
|
||||
Preset("Super Mario 64", "-O1 -g -mips2", IDO53),
|
||||
Preset("Mario Kart 64", "-O2 -mips2", IDO53),
|
||||
Preset("GoldenEye / Perfect Dark", "-Olimit 2000 -mips2 -O2", IDO53),
|
||||
Preset("Diddy Kong Racing", "-O2 -mips1", IDO53),
|
||||
Preset("Dinosaur Planet", "-O2 -g3 -mips2", IDO53),
|
||||
Preset("Dinosaur Planet (DLLs)", "-O2 -g3 -mips2 -KPIC", IDO53),
|
||||
Preset("Ocarina of Time", "-O2 -mips2", IDO71),
|
||||
Preset("Majora's Mask", "-O2 -g3 -mips2", IDO71),
|
||||
Preset("Mario Party 3", "-O1 -mips2", GCC272KMC),
|
||||
Preset("Paper Mario", "-O2 -fforce-addr", GCC281),
|
||||
Preset("Super Mario 64", IDO53, "-O1 -g -mips2"),
|
||||
Preset("Mario Kart 64", IDO53, "-O2 -mips2"),
|
||||
Preset("GoldenEye / Perfect Dark", IDO53, "-Olimit 2000 -mips2 -O2"),
|
||||
Preset("Diddy Kong Racing", IDO53, "-O2 -mips1"),
|
||||
Preset("Dinosaur Planet", IDO53, "-O2 -g3 -mips2"),
|
||||
Preset("Dinosaur Planet (DLLs)", IDO53, "-O2 -g3 -mips2 -KPIC"),
|
||||
Preset("Ocarina of Time", IDO71, "-O2 -mips2"),
|
||||
Preset(
|
||||
"Majora's Mask",
|
||||
IDO71,
|
||||
"-O2 -g3 -mips2 -woff 624",
|
||||
diff_flags=["-Mreg-names=32"],
|
||||
),
|
||||
Preset("Mario Party 3", GCC272KMC, "-O1 -mips2"),
|
||||
Preset("Paper Mario", GCC281, "-O2 -fforce-addr"),
|
||||
# GC_WII
|
||||
Preset(
|
||||
"Super Monkey Ball",
|
||||
"-O4,p -nodefaults -fp hard -Cpp_exceptions off -enum int -inline auto",
|
||||
MWCC_233_159,
|
||||
"-O4,p -nodefaults -fp hard -Cpp_exceptions off -enum int -inline auto",
|
||||
),
|
||||
Preset(
|
||||
"Super Mario Sunshine",
|
||||
"-lang=c++ -Cpp_exceptions off -fp hard -O4 -nodefaults -enum int -rostr",
|
||||
MWCC_233_163,
|
||||
"-lang=c++ -Cpp_exceptions off -fp hard -O4 -nodefaults -enum int -rostr",
|
||||
),
|
||||
Preset(
|
||||
"Pikmin",
|
||||
"-lang=c++ -nodefaults -Cpp_exceptions off -RTTI on -fp hard -O4,p",
|
||||
MWCC_233_163E,
|
||||
"-lang=c++ -nodefaults -Cpp_exceptions off -RTTI on -fp hard -O4,p",
|
||||
),
|
||||
Preset(
|
||||
"Super Smash Bros. Melee",
|
||||
"-O4,p -nodefaults -fp hard -Cpp_exceptions off -enum int -fp_contract on -inline auto",
|
||||
MWCC_233_163E,
|
||||
"-O4,p -nodefaults -fp hard -Cpp_exceptions off -enum int -fp_contract on -inline auto",
|
||||
),
|
||||
Preset(
|
||||
"Battle for Bikini Bottom",
|
||||
"-lang=c++ -g -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -O4,p -maxerrors 1 -str reuse,pool,readonly -char unsigned -enum int -use_lmw_stmw on -inline off",
|
||||
MWCC_247_92,
|
||||
"-lang=c++ -g -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -O4,p -maxerrors 1 -str reuse,pool,readonly -char unsigned -enum int -use_lmw_stmw on -inline off",
|
||||
),
|
||||
Preset(
|
||||
"Pikmin 2",
|
||||
"-lang=c++ -nodefaults -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -rostr -O4,p -use_lmw_stmw on -enum int -inline auto -sdata 8 -sdata2 8",
|
||||
MWCC_247_107,
|
||||
"-lang=c++ -nodefaults -Cpp_exceptions off -RTTI off -fp hard -fp_contract on -rostr -O4,p -use_lmw_stmw on -enum int -inline auto -sdata 8 -sdata2 8",
|
||||
),
|
||||
Preset(
|
||||
"The Thousand-Year Door",
|
||||
"-fp hard -fp_contract on -enum int -O4,p -sdata 48 -sdata2 6 -rostr -multibyte -use_lmw_stmw on -inline deferred -Cpp_exceptions off",
|
||||
MWCC_247_108,
|
||||
"-fp hard -fp_contract on -enum int -O4,p -sdata 48 -sdata2 6 -rostr -multibyte -use_lmw_stmw on -inline deferred -Cpp_exceptions off",
|
||||
),
|
||||
Preset(
|
||||
"Twilight Princess",
|
||||
"-lang=c++ -Cpp_exceptions off -nodefaults -O3 -fp hard -msgstyle gcc -str pool,readonly,reuse -RTTI off -maxerrors 1 -enum int",
|
||||
MWCC_247_108,
|
||||
"-lang=c++ -Cpp_exceptions off -nodefaults -O3 -fp hard -msgstyle gcc -str pool,readonly,reuse -RTTI off -maxerrors 1 -enum int",
|
||||
),
|
||||
Preset(
|
||||
"Super Paper Mario (DOL)",
|
||||
"-lang=c99 -enc SJIS -fp hard -O4 -use_lmw_stmw on -str pool -rostr -inline all -sdata 4 -sdata2 4",
|
||||
MWCC_41_60831,
|
||||
"-lang=c99 -enc SJIS -fp hard -O4 -use_lmw_stmw on -str pool -rostr -inline all -sdata 4 -sdata2 4",
|
||||
),
|
||||
Preset(
|
||||
"Super Paper Mario (REL)",
|
||||
"-lang=c99 -enc SJIS -fp hard -O4 -use_lmw_stmw on -str pool -rostr -ipa file -sdata 0 -sdata2 0 -pool off -ordered-fp-compares",
|
||||
MWCC_41_60831,
|
||||
"-lang=c99 -enc SJIS -fp hard -O4 -use_lmw_stmw on -str pool -rostr -ipa file -sdata 0 -sdata2 0 -pool off -ordered-fp-compares",
|
||||
),
|
||||
Preset(
|
||||
"Wii Sports",
|
||||
"-lang=c++ -enum int -inline auto -Cpp_exceptions off -RTTI off -fp hard -O4,p -nodefaults",
|
||||
MWCC_41_60831,
|
||||
"-lang=c++ -enum int -inline auto -Cpp_exceptions off -RTTI off -fp hard -O4,p -nodefaults",
|
||||
),
|
||||
Preset(
|
||||
"Super Mario Galaxy",
|
||||
"-Cpp_exceptions off -stdinc -nodefaults -fp hard -lang=c++ -inline auto,level=2 -ipa file -O4,s -rtti off -sdata 4 -sdata2 4 -enum int",
|
||||
MWCC_41_60126,
|
||||
"-Cpp_exceptions off -stdinc -nodefaults -fp hard -lang=c++ -inline auto,level=2 -ipa file -O4,s -rtti off -sdata 4 -sdata2 4 -enum int",
|
||||
),
|
||||
Preset(
|
||||
"Mario Party 4",
|
||||
MWCC_242_81,
|
||||
"-O0,p -str pool -fp hard -Cpp_exceptions off",
|
||||
),
|
||||
# NDS
|
||||
Preset(
|
||||
"Pokémon Diamond / Pearl",
|
||||
"-O4,p -gccext,on -fp soft -lang c99 -Cpp_exceptions off -interworking -enum int",
|
||||
MWCC_30_123,
|
||||
"-O4,p -gccext,on -fp soft -lang c99 -Cpp_exceptions off -interworking -enum int",
|
||||
),
|
||||
Preset(
|
||||
"Pokémon HeartGold / SoulSilver",
|
||||
"-O4,p -enum int -lang c99 -Cpp_exceptions off -gccext,on -gccinc -interworking -gccdep -MD",
|
||||
MWCC_30_137,
|
||||
),
|
||||
Preset(
|
||||
"Mario Party 4",
|
||||
"-O0,p -str pool -fp hard -Cpp_exceptions off",
|
||||
MWCC_242_81,
|
||||
"-O4,p -enum int -lang c99 -Cpp_exceptions off -gccext,on -gccinc -interworking -gccdep -MD",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -19,7 +19,35 @@ logger = logging.getLogger(__name__)
|
||||
MAX_FUNC_SIZE_LINES = 5000
|
||||
|
||||
|
||||
class AsmDifferWrapper:
|
||||
class DiffWrapper:
|
||||
@staticmethod
|
||||
def filter_objdump_flags(compiler_flags: str) -> str:
|
||||
# Remove irrelevant flags that are part of the base objdump configs, but clutter the compiler settings field.
|
||||
# TODO: use cfg for this?
|
||||
skip_flags_with_args: set[str] = set()
|
||||
skip_flags = {
|
||||
"--disassemble",
|
||||
"--disassemble-zeroes",
|
||||
"--line-numbers",
|
||||
"--reloc",
|
||||
}
|
||||
|
||||
skip_next = False
|
||||
flags = []
|
||||
for flag in compiler_flags.split():
|
||||
if skip_next:
|
||||
skip_next = False
|
||||
continue
|
||||
if flag in skip_flags:
|
||||
continue
|
||||
if flag in skip_flags_with_args:
|
||||
skip_next = True
|
||||
continue
|
||||
if any(flag.startswith(f) for f in skip_flags_with_args):
|
||||
continue
|
||||
flags.append(flag)
|
||||
return " ".join(flags)
|
||||
|
||||
@staticmethod
|
||||
def create_config(arch: asm_differ.ArchSettings) -> asm_differ.Config:
|
||||
return asm_differ.Config(
|
||||
@@ -84,14 +112,24 @@ class AsmDifferWrapper:
|
||||
|
||||
return ["--start-address=0"]
|
||||
|
||||
@staticmethod
|
||||
def parse_objdump_flags(diff_flags: list[str]) -> list[str]:
|
||||
ret = []
|
||||
|
||||
if "-Mreg-names=32" in diff_flags:
|
||||
ret.append("-Mreg-names=32")
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def run_objdump(
|
||||
target_data: bytes,
|
||||
platform: Platform,
|
||||
config: asm_differ.Config,
|
||||
label: Optional[str],
|
||||
flags: list[str],
|
||||
) -> str:
|
||||
flags = [
|
||||
flags += [
|
||||
"--disassemble",
|
||||
"--disassemble-zeroes",
|
||||
"--line-numbers",
|
||||
@@ -102,15 +140,16 @@ class AsmDifferWrapper:
|
||||
target_path = sandbox.path / "out.s"
|
||||
target_path.write_bytes(target_data)
|
||||
|
||||
flags += AsmDifferWrapper.get_objdump_target_function_flags(
|
||||
flags += DiffWrapper.get_objdump_target_function_flags(
|
||||
sandbox, target_path, platform, label
|
||||
)
|
||||
|
||||
flags += config.arch.arch_flags
|
||||
|
||||
if platform.objdump_cmd:
|
||||
try:
|
||||
objdump_proc = sandbox.run_subprocess(
|
||||
[platform.objdump_cmd]
|
||||
+ config.arch.arch_flags
|
||||
platform.objdump_cmd.split()
|
||||
+ flags
|
||||
+ [sandbox.rewrite_path(target_path)],
|
||||
shell=True,
|
||||
@@ -132,13 +171,14 @@ class AsmDifferWrapper:
|
||||
platform: Platform,
|
||||
diff_label: Optional[str],
|
||||
config: asm_differ.Config,
|
||||
diff_flags: list[str],
|
||||
) -> str:
|
||||
|
||||
if len(elf_object) == 0:
|
||||
raise AssemblyError("Asm empty")
|
||||
|
||||
basedump = AsmDifferWrapper.run_objdump(
|
||||
elf_object, platform, config, diff_label
|
||||
basedump = DiffWrapper.run_objdump(
|
||||
elf_object, platform, config, diff_label, diff_flags
|
||||
)
|
||||
if not basedump:
|
||||
raise ObjdumpError("Error running objdump")
|
||||
@@ -162,7 +202,8 @@ class AsmDifferWrapper:
|
||||
platform: Platform,
|
||||
diff_label: Optional[str],
|
||||
compiled_elf: bytes,
|
||||
allow_target_only: bool = False,
|
||||
allow_target_only: bool,
|
||||
diff_flags: list[str],
|
||||
) -> DiffResult:
|
||||
|
||||
if platform == DUMMY:
|
||||
@@ -175,14 +216,20 @@ class AsmDifferWrapper:
|
||||
logger.error(f"Unsupported arch: {platform.arch}. Continuing assuming mips")
|
||||
arch = asm_differ.get_arch("mips")
|
||||
|
||||
config = AsmDifferWrapper.create_config(arch)
|
||||
objdump_flags = DiffWrapper.parse_objdump_flags(diff_flags)
|
||||
|
||||
basedump = AsmDifferWrapper.get_dump(
|
||||
bytes(target_assembly.elf_object), platform, diff_label, config
|
||||
config = DiffWrapper.create_config(arch) # TODO pass and use diff_flags
|
||||
|
||||
basedump = DiffWrapper.get_dump(
|
||||
bytes(target_assembly.elf_object),
|
||||
platform,
|
||||
diff_label,
|
||||
config,
|
||||
objdump_flags,
|
||||
)
|
||||
try:
|
||||
mydump = AsmDifferWrapper.get_dump(
|
||||
compiled_elf, platform, diff_label, config
|
||||
mydump = DiffWrapper.get_dump(
|
||||
compiled_elf, platform, diff_label, config, objdump_flags
|
||||
)
|
||||
except Exception as e:
|
||||
if allow_target_only:
|
||||
@@ -72,6 +72,10 @@ COMMON_IDO_FLAGS: Flags = [
|
||||
Checkbox("kpic", "-KPIC"),
|
||||
]
|
||||
|
||||
COMMON_MIPS_DIFF_FLAGS: Flags = [
|
||||
Checkbox("mreg_names=32", "-Mreg-names=32"),
|
||||
]
|
||||
|
||||
COMMON_MWCC_FLAGS: Flags = [
|
||||
FlagSet(
|
||||
id="mwcc_opt_level",
|
||||
|
||||
23
backend/coreapp/migrations/0020_diff_flags.py
Normal file
23
backend/coreapp/migrations/0020_diff_flags.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.0.3 on 2022-04-05 09:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("coreapp", "0019_scratch_preset"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="compilerconfig",
|
||||
name="diff_flags",
|
||||
field=models.JSONField(blank=True, default=str),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="scratch",
|
||||
name="diff_flags",
|
||||
field=models.JSONField(blank=True, default=str),
|
||||
),
|
||||
]
|
||||
@@ -224,6 +224,7 @@ class ProjectFunction(models.Model):
|
||||
"platform": compiler_config.platform,
|
||||
"compiler": compiler_config.compiler,
|
||||
"compiler_flags": compiler_config.compiler_flags,
|
||||
"diff_flags": compiler_config.diff_flags,
|
||||
},
|
||||
allow_project=True,
|
||||
)
|
||||
|
||||
@@ -38,6 +38,7 @@ class CompilerConfig(models.Model):
|
||||
compiler = models.CharField(max_length=100)
|
||||
platform = models.CharField(max_length=100)
|
||||
compiler_flags = models.TextField(max_length=1000, default="", blank=True)
|
||||
diff_flags = models.JSONField(default=str, blank=True)
|
||||
|
||||
|
||||
class Scratch(models.Model):
|
||||
@@ -53,6 +54,9 @@ class Scratch(models.Model):
|
||||
compiler_flags = models.TextField(
|
||||
max_length=1000, default="", blank=True
|
||||
) # TODO: reference a CompilerConfig
|
||||
diff_flags = models.JSONField(
|
||||
default=str, blank=True
|
||||
) # TODO: reference a CompilerConfig
|
||||
preset = models.CharField(max_length=100, blank=True, null=True)
|
||||
target_assembly = models.ForeignKey(Assembly, on_delete=models.CASCADE)
|
||||
source_code = models.TextField(blank=True)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from typing import OrderedDict
|
||||
from dataclasses import dataclass, field
|
||||
from typing import ClassVar, OrderedDict
|
||||
|
||||
from coreapp.flags import COMMON_MIPS_DIFF_FLAGS, Flags
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -16,7 +18,8 @@ class Platform:
|
||||
objdump_cmd: str
|
||||
nm_cmd: str
|
||||
asm_prelude: str
|
||||
supports_objdump_disassemble: bool = False
|
||||
diff_flags: Flags = field(default_factory=list, hash=False)
|
||||
supports_objdump_disassemble: bool = False # TODO turn into objdump flag
|
||||
|
||||
|
||||
def from_id(platform_id: str) -> Platform:
|
||||
@@ -56,6 +59,7 @@ N64 = Platform(
|
||||
assemble_cmd='mips-linux-gnu-as -march=vr4300 -mabi=32 -o "$OUTPUT" "$INPUT"',
|
||||
objdump_cmd="mips-linux-gnu-objdump",
|
||||
nm_cmd="mips-linux-gnu-nm",
|
||||
diff_flags=COMMON_MIPS_DIFF_FLAGS,
|
||||
asm_prelude="""
|
||||
.macro .late_rodata
|
||||
.section .rodata
|
||||
@@ -171,7 +175,7 @@ GC_WII = Platform(
|
||||
description="PowerPC",
|
||||
arch="ppc",
|
||||
assemble_cmd='powerpc-eabi-as -mgekko -o "$OUTPUT" "$INPUT"',
|
||||
objdump_cmd="powerpc-eabi-objdump",
|
||||
objdump_cmd="powerpc-eabi-objdump -M broadway",
|
||||
nm_cmd="powerpc-eabi-nm",
|
||||
asm_prelude="""
|
||||
.macro glabel label
|
||||
|
||||
@@ -110,6 +110,7 @@ class ScratchCreateSerializer(serializers.Serializer[None]):
|
||||
compiler = serializers.CharField(allow_blank=True, required=True)
|
||||
platform = serializers.CharField(allow_blank=True, required=False)
|
||||
compiler_flags = serializers.CharField(allow_blank=True, required=False)
|
||||
diff_flags = serializers.CharField(allow_blank=True, required=False)
|
||||
preset = serializers.CharField(allow_blank=True, required=False)
|
||||
source_code = serializers.CharField(allow_blank=True, required=False)
|
||||
target_asm = serializers.CharField(allow_blank=True)
|
||||
|
||||
@@ -410,6 +410,52 @@ class CompilationTests(BaseTestCase):
|
||||
"The compilation result should be different",
|
||||
)
|
||||
|
||||
@requiresCompiler(IDO71)
|
||||
def test_fpr_reg_names_output(self):
|
||||
"""
|
||||
Ensure that we can view fpr reg names by passing the appropriate diff flag
|
||||
"""
|
||||
scratch_dict = {
|
||||
"platform": N64.id,
|
||||
"compiler": IDO71.id,
|
||||
"diff_flags": "[-Mreg-names=32]",
|
||||
"context": "",
|
||||
"target_asm": """
|
||||
glabel test
|
||||
lui $at, 0x3ff0
|
||||
mtc1 $at, $fv1f
|
||||
mtc1 $zero, $fv1
|
||||
beqz $a0, .L00400194
|
||||
move $v0, $a0
|
||||
andi $a1, $a0, 3
|
||||
negu $a1, $a1
|
||||
beqz $a1, .L004000EC
|
||||
addu $v1, $a1, $a0
|
||||
mtc1 $v0, $ft0
|
||||
nop
|
||||
""",
|
||||
}
|
||||
scratch = self.create_scratch(scratch_dict)
|
||||
|
||||
# Test that we can compile a scratch
|
||||
response = self.client.post(
|
||||
reverse("scratch-compile", kwargs={"pk": scratch.slug})
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.json()["errors"]), 0)
|
||||
# Confirm the output contains the expected fpr reg names
|
||||
self.assertTrue("fv1f" in str(response.json()))
|
||||
|
||||
response = self.client.post(
|
||||
reverse("scratch-compile", kwargs={"pk": scratch.slug}),
|
||||
{"diff_flags": "[]"},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(response.json()["errors"]), 0)
|
||||
# Confirm the output does not contain the expected fpr reg names
|
||||
self.assertFalse("fv1f" in str(response.json()))
|
||||
|
||||
@requiresCompiler(MWCC_247_92)
|
||||
def test_mwcc_wine(self):
|
||||
"""
|
||||
|
||||
@@ -18,6 +18,7 @@ class CompilersDetail(APIView):
|
||||
c.id: {
|
||||
"platform": c.platform.id,
|
||||
"flags": [f.to_json() for f in c.flags],
|
||||
"diff_flags": [f.to_json() for f in c.platform.diff_flags],
|
||||
}
|
||||
for c in compilers.available_compilers()
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from coreapp import compilers, platforms
|
||||
|
||||
from ..asm_diff_wrapper import AsmDifferWrapper
|
||||
from ..diff_wrapper import DiffWrapper
|
||||
from ..compiler_wrapper import CompilationResult, CompilerWrapper, DiffResult
|
||||
from ..decompiler_wrapper import DecompilerWrapper
|
||||
|
||||
@@ -68,12 +68,13 @@ def compile_scratch(scratch: Scratch) -> CompilationResult:
|
||||
def diff_compilation(
|
||||
scratch: Scratch, compilation: CompilationResult, allow_target_only: bool = False
|
||||
) -> DiffResult:
|
||||
return AsmDifferWrapper.diff(
|
||||
return DiffWrapper.diff(
|
||||
scratch.target_assembly,
|
||||
platforms.from_id(scratch.platform),
|
||||
scratch.diff_label,
|
||||
compilation.elf_object,
|
||||
allow_target_only=allow_target_only,
|
||||
diff_flags=scratch.diff_flags,
|
||||
)
|
||||
|
||||
|
||||
@@ -156,7 +157,13 @@ def family_etag(request: Request, pk: Optional[str] = None) -> Optional[str]:
|
||||
|
||||
|
||||
def update_needs_recompile(partial: Dict[str, Any]) -> bool:
|
||||
recompile_params = ["compiler", "compiler_flags", "source_code", "context"]
|
||||
recompile_params = [
|
||||
"compiler",
|
||||
"compiler_flags",
|
||||
"diff_flags",
|
||||
"source_code",
|
||||
"context",
|
||||
]
|
||||
|
||||
for param in recompile_params:
|
||||
if param in partial:
|
||||
@@ -213,6 +220,9 @@ def create_scratch(data: Dict[str, Any], allow_project=False) -> Scratch:
|
||||
compiler_flags = data.get("compiler_flags", "")
|
||||
compiler_flags = CompilerWrapper.filter_compiler_flags(compiler_flags)
|
||||
|
||||
diff_flags = data.get("diff_flags", "")
|
||||
diff_flags = DiffWrapper.filter_objdump_flags(diff_flags)
|
||||
|
||||
preset = data.get("preset", "")
|
||||
if preset and not compilers.preset_from_name(preset):
|
||||
raise serializers.ValidationError("Unknown preset:" + preset)
|
||||
@@ -246,6 +256,7 @@ def create_scratch(data: Dict[str, Any], allow_project=False) -> Scratch:
|
||||
"name": name,
|
||||
"compiler": compiler.id,
|
||||
"compiler_flags": compiler_flags,
|
||||
"diff_flags": diff_flags,
|
||||
"preset": preset,
|
||||
"context": context,
|
||||
"diff_label": diff_label,
|
||||
@@ -337,6 +348,8 @@ class ScratchViewSet(
|
||||
scratch.compiler = request.data["compiler"]
|
||||
if "compiler_flags" in request.data:
|
||||
scratch.compiler_flags = request.data["compiler_flags"]
|
||||
if "diff_flags" in request.data:
|
||||
scratch.diff_flags = request.data["diff_flags"]
|
||||
if "source_code" in request.data:
|
||||
scratch.source_code = request.data["source_code"]
|
||||
if "context" in request.data:
|
||||
|
||||
@@ -188,5 +188,6 @@
|
||||
"sdata_limit": "Small data limit",
|
||||
"sdata_limit.-G0": "0 bytes",
|
||||
"sdata_limit.-G4": "4 bytes",
|
||||
"sdata_limit.-G8": "8 bytes"
|
||||
"sdata_limit.-G8": "8 bytes",
|
||||
"mreg_names=32": "ABI FPR names"
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
.chooseACompiler {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chooseACompilerActions {
|
||||
padding: 1em;
|
||||
align-self: center;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { useState } from "react"
|
||||
|
||||
import { ArrowRightIcon } from "@primer/octicons-react"
|
||||
|
||||
import Button from "../Button"
|
||||
import CompilerOpts, { CompilerOptsT } from "../compiler/CompilerOpts"
|
||||
|
||||
import styles from "./ChooseACompiler.module.scss"
|
||||
|
||||
export default function ChooseACompiler({ platform, onCommit }: {
|
||||
platform: string
|
||||
onCommit: (opts: CompilerOptsT) => void
|
||||
}) {
|
||||
const [compiler, setCompiler] = useState<CompilerOptsT>()
|
||||
|
||||
return <div className={styles.chooseACompiler}>
|
||||
<CompilerOpts
|
||||
platform={platform}
|
||||
value={compiler}
|
||||
onChange={c => setCompiler(c)}
|
||||
/>
|
||||
|
||||
<div className={styles.chooseACompilerActions}>
|
||||
<Button primary onClick={() => onCommit(compiler)}>
|
||||
Use this compiler
|
||||
<ArrowRightIcon size={16} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -2,11 +2,8 @@ import { Dispatch, JSXElementConstructor, ReactElement, RefObject, SetStateActio
|
||||
|
||||
import * as resizer from "react-simple-resizer"
|
||||
|
||||
import { Scratch } from "../../lib/api"
|
||||
import { CompilerOptsT } from "../compiler/CompilerOpts"
|
||||
import Tabs, { Tab } from "../Tabs"
|
||||
|
||||
import ChooseACompiler from "./ChooseACompiler"
|
||||
import styles from "./ScratchBody.module.scss"
|
||||
|
||||
const LEFT_PANE_MIN_WIDTH = 100
|
||||
@@ -21,8 +18,6 @@ export type Props = {
|
||||
setRightTab: Dispatch<SetStateAction<string>>
|
||||
leftTabs: ReactElement<typeof Tab, string | JSXElementConstructor<unknown>>[]
|
||||
rightTabs: ReactElement<typeof Tab, string | JSXElementConstructor<unknown>>[]
|
||||
setCompilerOpts: ({ compiler, compiler_flags }: CompilerOptsT) => void
|
||||
scratch: Scratch
|
||||
}
|
||||
|
||||
export default function ScratchBody({
|
||||
@@ -33,8 +28,6 @@ export default function ScratchBody({
|
||||
setRightTab,
|
||||
leftTabs,
|
||||
rightTabs,
|
||||
setCompilerOpts,
|
||||
scratch,
|
||||
}: Props) {
|
||||
return container.width > TWO_PANE_MIN_CONTAINER_WIDTH
|
||||
? (<resizer.Container className={styles.resizer}>
|
||||
@@ -56,18 +49,13 @@ export default function ScratchBody({
|
||||
/>
|
||||
|
||||
<resizer.Section className={styles.diffSection} minSize={RIGHT_PANE_MIN_WIDTH}>
|
||||
{scratch.compiler === ""
|
||||
? <ChooseACompiler platform={scratch.platform} onCommit={setCompilerOpts} />
|
||||
: <Tabs activeTab={rightTab} onChange={setRightTab} background="var(--g300)" border={false}>
|
||||
{rightTabs}
|
||||
</Tabs>
|
||||
}
|
||||
{<Tabs activeTab={rightTab} onChange={setRightTab} background="var(--g300)" border={false}>
|
||||
{rightTabs}
|
||||
</Tabs>}
|
||||
</resizer.Section>
|
||||
</resizer.Container>)
|
||||
: scratch.compiler === ""
|
||||
? (<ChooseACompiler platform={scratch.platform} onCommit={setCompilerOpts} />)
|
||||
: (<Tabs activeTab={leftTab} onChange={setLeftTab} background="var(--g300)" border={false}>
|
||||
{leftTabs}
|
||||
{rightTabs}
|
||||
</Tabs>)
|
||||
: (<Tabs activeTab={leftTab} onChange={setLeftTab} background="var(--g300)" border={false}>
|
||||
{leftTabs}
|
||||
{rightTabs}
|
||||
</Tabs>)
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ export function useLeftTabs({ scratch, setScratch, setSelectedSourceLine }: {
|
||||
</Tab>
|
||||
),
|
||||
[LeftScratchTab.COMPILER_OPTS]: (
|
||||
<Tab key="compiler_opts" tabKey="compiler_opts" label="Compiler options" className={styles.compilerOptsTab}>
|
||||
<Tab key="compiler_opts" tabKey="compiler_opts" label="Scratch options" className={styles.compilerOptsTab}>
|
||||
<div className={styles.compilerOptsContainer}>
|
||||
<CompilerOpts
|
||||
platform={scratch.platform}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
.popover {
|
||||
border: 1px solid var(--g500);
|
||||
border-radius: 1em;
|
||||
box-shadow: 0 2px 8px 0 #0008;
|
||||
max-width: 50em;
|
||||
|
||||
z-index: 999;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import { useState } from "react"
|
||||
|
||||
import { CpuIcon } from "@primer/octicons-react"
|
||||
import { motion, AnimatePresence } from "framer-motion"
|
||||
import { useLayer, Arrow } from "react-laag"
|
||||
|
||||
import { useThemeVariable } from "../../lib/hooks"
|
||||
import Button from "../Button"
|
||||
|
||||
import styles from "./CompilerButton.module.css"
|
||||
import CompilerOpts, { Props as CompilerOptsProps } from "./CompilerOpts"
|
||||
|
||||
export type Props = {
|
||||
platform: CompilerOptsProps["platform"]
|
||||
value: CompilerOptsProps["value"]
|
||||
onChange: CompilerOptsProps["onChange"]
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export default function CompilerButton({ platform, value, onChange, disabled }: Props) {
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
const arrowColor = useThemeVariable("--g300")
|
||||
const arrowBorderColor = useThemeVariable("--g500")
|
||||
|
||||
const close = () => setOpen(false)
|
||||
|
||||
const { renderLayer, triggerProps, layerProps, arrowProps } = useLayer({
|
||||
isOpen,
|
||||
onOutsideClick: close,
|
||||
overflowContainer: false,
|
||||
auto: true,
|
||||
placement: "bottom-end",
|
||||
triggerOffset: 14,
|
||||
})
|
||||
|
||||
return <>
|
||||
<Button
|
||||
{...triggerProps}
|
||||
onClick={() => {
|
||||
if (!disabled)
|
||||
setOpen(!isOpen)
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
<CpuIcon size={16} />
|
||||
Compiler...
|
||||
</Button>
|
||||
|
||||
{renderLayer(
|
||||
<AnimatePresence>
|
||||
{isOpen && <motion.div
|
||||
className={styles.popover}
|
||||
initial={{ y: -50, scaleX: 0.7, scaleY: 0, opacity: 0 }}
|
||||
animate={{ y: 0, scaleX: 1, scaleY: 1, opacity: 1 }}
|
||||
exit={{ y: -50, scaleX: 0.7, scaleY: 0, opacity: 0 }}
|
||||
transition={{ type: "spring", duration: 0.3 }}
|
||||
{...layerProps}
|
||||
>
|
||||
<CompilerOpts isPopup={true} platform={platform} value={value} onChange={onChange} />
|
||||
<Arrow
|
||||
size={12}
|
||||
backgroundColor={arrowColor}
|
||||
borderWidth={1}
|
||||
borderColor={arrowBorderColor}
|
||||
{...arrowProps}
|
||||
/>
|
||||
</motion.div>}
|
||||
</AnimatePresence>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
.header {
|
||||
padding: 1.5em;
|
||||
padding-bottom: 0;
|
||||
background: var(--g300);
|
||||
background: transparent;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -14,19 +14,27 @@
|
||||
|
||||
.header > * {
|
||||
flex-shrink: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
.section {
|
||||
padding: 1.5em;
|
||||
background: var(--g300);
|
||||
}
|
||||
|
||||
.header:not([data-is-popup]),
|
||||
.container:not([data-is-popup]) {
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* border-bottom: 1px solid var(--g400); */
|
||||
.section:not(:last-child) {
|
||||
border-bottom: 1px solid var(--a100);
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-size: 1.1em;
|
||||
font-weight: 500;
|
||||
|
||||
padding: 0.5em;
|
||||
padding-top: 0;
|
||||
|
||||
color: var(--g1200);
|
||||
}
|
||||
|
||||
.preset {
|
||||
@@ -82,6 +90,13 @@
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.diffFlags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.flag {
|
||||
flex-grow: 1;
|
||||
display: inline-block;
|
||||
|
||||
@@ -6,9 +6,9 @@ import * as api from "../../lib/api"
|
||||
import PlatformIcon from "../PlatformSelect/PlatformIcon"
|
||||
import Select from "../Select"
|
||||
|
||||
import CompilerFlags, { NO_TRANSLATION } from "./CompilerFlags"
|
||||
import styles from "./CompilerOpts.module.css"
|
||||
import { useCompilersForPlatform } from "./compilers"
|
||||
import Flags, { NO_TRANSLATION } from "./Flags"
|
||||
import PresetSelect from "./PresetSelect"
|
||||
|
||||
interface IOptsContext {
|
||||
@@ -63,6 +63,7 @@ export function FlagOption({ flag, description }: { flag: string, description?:
|
||||
export type CompilerOptsT = {
|
||||
compiler: string
|
||||
compiler_flags: string
|
||||
diff_flags: string[]
|
||||
preset: string
|
||||
}
|
||||
|
||||
@@ -70,17 +71,18 @@ export type Props = {
|
||||
platform?: string
|
||||
value: CompilerOptsT
|
||||
onChange: (value: CompilerOptsT) => void
|
||||
isPopup?: boolean
|
||||
}
|
||||
|
||||
export default function CompilerOpts({ platform, value, onChange, isPopup }: Props) {
|
||||
export default function CompilerOpts({ platform, value, onChange }: Props) {
|
||||
const compiler = value.compiler
|
||||
let opts = value.compiler_flags
|
||||
const diff_opts = value.diff_flags || []
|
||||
|
||||
const setCompiler = (compiler: string) => {
|
||||
onChange({
|
||||
compiler,
|
||||
compiler_flags: opts,
|
||||
diff_flags: diff_opts,
|
||||
preset: "",
|
||||
})
|
||||
}
|
||||
@@ -89,6 +91,16 @@ export default function CompilerOpts({ platform, value, onChange, isPopup }: Pro
|
||||
onChange({
|
||||
compiler,
|
||||
compiler_flags: opts,
|
||||
diff_flags: diff_opts,
|
||||
preset: "",
|
||||
})
|
||||
}
|
||||
|
||||
const setDiffOpts = (diff_opts: string[]) => {
|
||||
onChange({
|
||||
compiler,
|
||||
compiler_flags: opts,
|
||||
diff_flags: diff_opts,
|
||||
preset: "",
|
||||
})
|
||||
}
|
||||
@@ -97,36 +109,58 @@ export default function CompilerOpts({ platform, value, onChange, isPopup }: Pro
|
||||
onChange({
|
||||
compiler: preset.compiler,
|
||||
compiler_flags: preset.flags,
|
||||
diff_flags: preset.diff_flags,
|
||||
preset: preset.name,
|
||||
})
|
||||
}
|
||||
|
||||
return <OptsContext.Provider value={{
|
||||
checkFlag(flag: string) {
|
||||
return (" " + opts + " ").includes(" " + flag + " ")
|
||||
},
|
||||
|
||||
setFlag(flag: string, enable: boolean) {
|
||||
if (enable) {
|
||||
opts = opts + " " + flag
|
||||
} else {
|
||||
opts = (" " + opts + " ").replace(" " + flag + " ", " ")
|
||||
}
|
||||
opts = opts.trim()
|
||||
setOpts(opts)
|
||||
},
|
||||
}}>
|
||||
<div className={styles.header} data-is-popup={isPopup}>
|
||||
return <div>
|
||||
<section className={styles.header}>
|
||||
<PlatformIcon platform={platform} size={32} />
|
||||
<div className={styles.preset}>
|
||||
Preset
|
||||
<PresetSelect platform={platform} presetName={value.preset} setPreset={setPreset} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.container} data-is-popup={isPopup}>
|
||||
<OptsEditor platform={platform} compiler={compiler} setCompiler={setCompiler} opts={opts} setOpts={setOpts} />
|
||||
</div>
|
||||
</OptsContext.Provider>
|
||||
</section>
|
||||
<OptsContext.Provider value={{
|
||||
checkFlag(flag: string) {
|
||||
return (" " + opts + " ").includes(" " + flag + " ")
|
||||
},
|
||||
|
||||
setFlag(flag: string, enable: boolean) {
|
||||
if (enable) {
|
||||
opts = opts + " " + flag
|
||||
} else {
|
||||
opts = (" " + opts + " ").replace(" " + flag + " ", " ")
|
||||
}
|
||||
opts = opts.trim()
|
||||
setOpts(opts)
|
||||
},
|
||||
}}>
|
||||
<section className={styles.section}>
|
||||
<h3 className={styles.heading}>Compiler options</h3>
|
||||
<OptsEditor platform={platform} compiler={compiler} setCompiler={setCompiler} opts={opts} setOpts={setOpts} />
|
||||
</section>
|
||||
</OptsContext.Provider>
|
||||
<OptsContext.Provider value={{
|
||||
checkFlag(flag: string) {
|
||||
return diff_opts.includes(flag)
|
||||
},
|
||||
|
||||
setFlag(flag: string, enable: boolean) {
|
||||
if (enable && !diff_opts.includes(flag)) {
|
||||
setDiffOpts([...diff_opts, flag])
|
||||
} else if (!enable && diff_opts.includes(flag)) {
|
||||
setDiffOpts(diff_opts.filter(o => o != flag))
|
||||
}
|
||||
},
|
||||
}}>
|
||||
{diff_opts.length > 0 && <section className={styles.section}>
|
||||
<h3 className={styles.heading}>Diff options</h3>
|
||||
<DiffOptsEditor platform={platform} compiler={compiler} />
|
||||
</section>}
|
||||
</OptsContext.Provider>
|
||||
</div>
|
||||
}
|
||||
|
||||
export function OptsEditor({ platform, compiler: compilerId, setCompiler, opts, setOpts }: {
|
||||
@@ -172,7 +206,21 @@ export function OptsEditor({ platform, compiler: compilerId, setCompiler, opts,
|
||||
</div>
|
||||
|
||||
<div className={styles.flags}>
|
||||
{(compilerId && compiler) ? <CompilerFlags schema={compiler.flags} /> : <div />}
|
||||
{(compilerId && compiler) ? <Flags schema={compiler.flags} /> : <div />}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
export function DiffOptsEditor({ platform, compiler: compilerId }: {
|
||||
platform?: string
|
||||
compiler: string
|
||||
}) {
|
||||
const compilers = useCompilersForPlatform(platform)
|
||||
const compiler = compilers[compilerId]
|
||||
|
||||
return <div>
|
||||
<div className={styles.diffFlags}>
|
||||
{(compilerId && compiler) ? <Flags schema={compiler.diff_flags} /> : <div />}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import { Checkbox, FlagSet, FlagOption } from "./CompilerOpts"
|
||||
export const NO_TRANSLATION = "NO_TRANSLATION"
|
||||
|
||||
export interface Props {
|
||||
schema: api.CompilerFlag[]
|
||||
schema: api.Flag[]
|
||||
}
|
||||
|
||||
export default function CompilerFlags({ schema }: Props) {
|
||||
export default function Flags({ schema }: Props) {
|
||||
const compilersTranslation = useTranslation("compilers")
|
||||
|
||||
return <>
|
||||
@@ -188,6 +188,7 @@ export interface Scratch extends TerseScratch {
|
||||
slug: string // avoid using, use `url` instead
|
||||
description: string
|
||||
compiler_flags: string
|
||||
diff_flags: string[]
|
||||
preset: string
|
||||
source_code: string
|
||||
context: string
|
||||
@@ -270,7 +271,7 @@ export type DiffText = {
|
||||
key?: string
|
||||
}
|
||||
|
||||
export type CompilerFlag = {
|
||||
export type Flag = {
|
||||
type: "checkbox"
|
||||
id: string
|
||||
flag: string
|
||||
@@ -284,11 +285,13 @@ export type CompilerPreset = {
|
||||
name: string
|
||||
flags: string
|
||||
compiler: string
|
||||
diff_flags: string[]
|
||||
}
|
||||
|
||||
export type Compiler = {
|
||||
platform: string
|
||||
flags: CompilerFlag[]
|
||||
flags: Flag[]
|
||||
diff_flags: Flag[]
|
||||
}
|
||||
|
||||
export type Platform = {
|
||||
@@ -353,6 +356,7 @@ export function useSaveScratch(localScratch: Scratch): () => Promise<Scratch> {
|
||||
context: undefinedIfUnchanged(savedScratch, localScratch, "context"),
|
||||
compiler: undefinedIfUnchanged(savedScratch, localScratch, "compiler"),
|
||||
compiler_flags: undefinedIfUnchanged(savedScratch, localScratch, "compiler_flags"),
|
||||
diff_flags: undefinedIfUnchanged(savedScratch, localScratch, "diff_flags"),
|
||||
preset: undefinedIfUnchanged(savedScratch, localScratch, "preset"),
|
||||
name: undefinedIfUnchanged(savedScratch, localScratch, "name"),
|
||||
description: undefinedIfUnchanged(savedScratch, localScratch, "description"),
|
||||
@@ -409,6 +413,7 @@ export function useIsScratchSaved(scratch: Scratch): boolean {
|
||||
scratch.description === saved.description &&
|
||||
scratch.compiler === saved.compiler &&
|
||||
scratch.compiler_flags === saved.compiler_flags &&
|
||||
scratch.diff_flags === saved.diff_flags &&
|
||||
scratch.source_code === saved.source_code &&
|
||||
scratch.context === saved.context
|
||||
)
|
||||
@@ -441,6 +446,7 @@ export function useCompilation(scratch: Scratch | null, autoRecompile = true, au
|
||||
// TODO: api should take { scratch } and support undefinedIfUnchanged on all fields
|
||||
compiler: scratch.compiler,
|
||||
compiler_flags: scratch.compiler_flags,
|
||||
diff_flags: scratch.diff_flags,
|
||||
source_code: scratch.source_code,
|
||||
context: savedScratch ? undefinedIfUnchanged(savedScratch, scratch, "context") : scratch.context,
|
||||
}).then((compilation: Compilation) => {
|
||||
@@ -489,7 +495,8 @@ export function useCompilation(scratch: Scratch | null, autoRecompile = true, au
|
||||
autoRecompile,
|
||||
|
||||
// fields passed to compilations
|
||||
scratch.compiler, scratch.compiler_flags,
|
||||
scratch.compiler,
|
||||
scratch.compiler_flags, scratch.diff_flags,
|
||||
scratch.source_code, scratch.context,
|
||||
])
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
const [platform, setPlatform] = useState("")
|
||||
const [compilerId, setCompiler] = useState<string>()
|
||||
const [compilerFlags, setCompilerFlags] = useState<string>("")
|
||||
const [diffFlags, setDiffFlags] = useState<string>("")
|
||||
const [presetName, setPresetName] = useState<string>("")
|
||||
|
||||
const router = useRouter()
|
||||
@@ -90,6 +91,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
const setPreset = (preset: api.CompilerPreset) => {
|
||||
setCompiler(preset.compiler)
|
||||
setCompilerFlags(preset.flags)
|
||||
setDiffFlags(preset.diff_flags)
|
||||
setPresetName(preset.name)
|
||||
}
|
||||
|
||||
@@ -102,6 +104,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
setPlatform(localStorage["new_scratch_platform"] ?? "")
|
||||
setCompiler(localStorage["new_scratch_compiler"] ?? undefined)
|
||||
setCompilerFlags(localStorage["new_scratch_compilerFlags"] ?? "")
|
||||
setDiffFlags(localStorage["new_scratch_diffFlags"] ?? "")
|
||||
setPresetName(localStorage["new_scratch_presetName"] ?? "")
|
||||
} catch (error) {
|
||||
console.warn("bad localStorage", error)
|
||||
@@ -116,8 +119,9 @@ export default function NewScratch({ serverCompilers }: {
|
||||
localStorage["new_scratch_platform"] = platform
|
||||
localStorage["new_scratch_compiler"] = compilerId
|
||||
localStorage["new_scratch_compilerFlags"] = compilerFlags
|
||||
localStorage["new_scratch_diffFlags"] = diffFlags
|
||||
localStorage["new_scratch_presetName"] = presetName
|
||||
}, [label, asm, context, platform, compilerId, compilerFlags, presetName])
|
||||
}, [label, asm, context, platform, compilerId, compilerFlags, diffFlags, presetName])
|
||||
|
||||
const platformCompilers = useCompilersForPlatform(platform, serverCompilers.compilers)
|
||||
const compiler = platformCompilers[compilerId]
|
||||
@@ -134,6 +138,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
// Fall back to the first supported compiler and no flags
|
||||
setCompiler(Object.keys(platformCompilers)[0])
|
||||
setCompilerFlags("")
|
||||
setDiffFlags("")
|
||||
|
||||
// If there is a preset for this platform, use it
|
||||
for (const [k, v] of Object.entries(serverCompilers.compilers)) {
|
||||
@@ -154,6 +159,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
platform,
|
||||
compiler: compilerId,
|
||||
compiler_flags: compilerFlags,
|
||||
diffFlags: diffFlags,
|
||||
preset: presetName,
|
||||
diff_label: label || defaultLabel || "",
|
||||
})
|
||||
@@ -217,6 +223,7 @@ export default function NewScratch({ serverCompilers }: {
|
||||
onChange={c => {
|
||||
setCompiler(c)
|
||||
setCompilerFlags("")
|
||||
setDiffFlags("")
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user