diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21a560c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +hello* diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6161a19 --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1715653339, + "narHash": "sha256-7lR9tpVXviSccl07GXI0+ve/natd24HAkuy1sQp0OlI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "abd6d48f8c77bea7dc51beb2adfa6ed3950d2585", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index bbfe7ea..d70d271 100644 --- a/flake.nix +++ b/flake.nix @@ -11,12 +11,14 @@ let pkgs = nixpkgs.legacyPackages.${system}; harec = pkgs.callPackage ./pkgs/harec.nix { }; - #hare = pkgs.callPackage ./pkgs/hare.nix { inherit harec; }; + hare = pkgs.callPackage ./pkgs/hare.nix { inherit harec; }; in { default = pkgs.mkShell { buildInputs = [ + pkgs.qbe harec + hare ]; }; }); diff --git a/pkgs/hare-as b/pkgs/hare-as new file mode 100755 index 0000000..594e13e --- /dev/null +++ b/pkgs/hare-as @@ -0,0 +1,37 @@ +set -o pipefail + +function header() { + echo + echo + echo "# ----------------------------------------------------------------" + echo ".file \"$1\"" + echo "# ----------------------------------------------------------------" + echo +} + +args= +code= +until [ $# -eq 0 ]; do + case $1 in + --) + ;; + -o|-I|-arch) + args="$args $1 $2" + shift + ;; + -*) + args="$args $1" + ;; + *) + # file="$(fix_asm $1)" + + # # IFS=$'\n' + file=$(cat "$1") + + code="$code$(header $1)"$'\n'"$file" + ;; + esac + shift +done +echo "jer" +echo "$code" | fix_asm | as $args - diff --git a/pkgs/hare-as.py b/pkgs/hare-as.py new file mode 100755 index 0000000..b1b0411 --- /dev/null +++ b/pkgs/hare-as.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import re +import sys +from subprocess import Popen, PIPE, STDOUT + +def header(filename): + return f""" +# ------------------ +.file "{filename}" +# ------------------ +""" + +REPLACEMENTS = [ + (r'^\.section "\.text([^"]*)"(,"([^"]*))?"$', r'.text ; \1, \3'), + (r'^\.section "\.data([^"]*)"$', r'.data ; \1'), + (r'^\.section "\.bss([^"]*)"$', r'.bss ; \1'), + (r'^\.section "\.init_array"(,"([^"]*)")?', r'.section __DATA, .init_array ; \2'), + (r'^\.section "\.fini_array"(,"([^"]*)")?', r'.section __DATA, .fini_array ; \2'), + (r'^\.section "\.test_array"(,"([^"]*)")?', r'.section __DATA, .test_array ; \2'), + (r'^\.section \.abort "([^"]+)"', r'.section __DATA, .abort $COMMENT \1'), + (r'^(\.type .+)', '; \1'), + (r'^(\.global) (rt\..+)', r'\1 _\2'), + (r'^(rt\..+:)', r'_\1'), + (r'^(crypto\.aes\.x86ni_.+:)', r'_\1'), + (r'^(debug\.getfp:)', r'_\1'), + (r'adrp x0, _environ@page', r'adrp x0, _environ@GOTPAGE'), + (r'add x0, x0, _environ@pageoff', r'ldr x0, [x0, _environ@GOTPAGEOFF]'), +] + +def fix_asm(code): + for (pattern, repl) in REPLACEMENTS: + code = re.sub(pattern, repl, code, flags=re.MULTILINE) + return code + +args = ['as'] +files = [] +argv = sys.argv[1:] +while len(argv): + if argv[0] == "--": + args.append("--") + elif argv[0] in ["-o", "-I", "-arch"]: + args.append(argv[0]) + args.append(argv[1]) + argv.pop(0) + elif argv[0][0] == "-": + argv.append(argv[0]) + else: + files.append(argv[0]) + + argv.pop(0) + +args.append("-") + +code = "" +for file in files: + with open(file) as fp: + content = fp.read() + code += header(file) + code += "\n" + code += fix_asm(content) + code += "\n" + +p = Popen(args, stdout=PIPE, stdin=PIPE, stderr=PIPE, text=True) +data = p.communicate(input=code) +print(data[1], end='', file=sys.stderr) +print(data[0], end='') diff --git a/pkgs/hare.nix b/pkgs/hare.nix index b6b9803..7e801ba 100644 --- a/pkgs/hare.nix +++ b/pkgs/hare.nix @@ -1,4 +1,4 @@ -{ +{ stdenv, lib, makeWrapper, @@ -7,24 +7,45 @@ qbe, harec, binutils-unwrapped, - tzdata + tzdata, + python3, + writeScript, + rustc, }: let platform = lib.toLower stdenv.hostPlatform.uname.system; arch = stdenv.hostPlatform.uname.processor; qbePlatform = { - x86_64 = "amd64_sysv"; - aarch64 = "arm64"; - riscv64 = "rv64"; + x86_64 = "amd64_apple"; + aarch64 = "arm64_apple"; }.${arch}; + hareAs = ./hare-as.py; + hareLd = stdenv.mkDerivation (finalAttrs: { + pname = "rust-ld"; + version = "1.0"; + src = [ ./ld.rs ]; + buildInputs = [ rustc ]; + unpackPhase = '' + for srcFile in $src; do + cp $srcFile $(stripHash $srcFile) + done + ''; + buildPhase = '' + rustc -o rust-ld.bin $src + ''; + installPhase = '' + mkdir -p $out/bin + cp rust-ld.bin $out/bin/rust-ld + ''; + }); in stdenv.mkDerivation (finalAttrs: { pname = "hare"; version = "0.24"; src = builtins.fetchGit { - url = "https://git.sr.ht/~sircmpwn/hare"; + url = "https://github.com/hshq/harelang"; ref = "master"; - rev = "0cd51184a7acdfd4ef20195d1648622b04477293"; + rev = "30d097a7c7f3ccf9e4fc783d1cdae1fd506673c7"; }; patches = [ @@ -35,6 +56,7 @@ stdenv.mkDerivation (finalAttrs: { makeWrapper qbe scdoc + python3 ]; buildInputs = [ @@ -51,20 +73,25 @@ stdenv.mkDerivation (finalAttrs: { "VERSION=${finalAttrs.version}-nixpkgs" "QBEFLAGS=-t${qbePlatform}" "CC=${stdenv.cc.targetPrefix}cc" - "AS=${stdenv.cc.targetPrefix}as" - "LD=${stdenv.cc.targetPrefix}ld" + "AS=${hareAs}" + "LD=${hareLd}/bin/rust-ld" # Strip the variable of an empty $(SRCDIR)/hare/third-party, since nix does # not follow the FHS. "HAREPATH=$(SRCDIR)/hare/stdlib" ]; postConfigure = '' - ln -s configs/linux.mk config.mk + ln -s configs/darwin.mk config.mk + sed -i 's/ @#/ /' Makefile + sed -i 's/ @/ /' Makefile + sed -i 's/ @/ /' makefiles/darwin.aarch64.mk ''; postFixup = '' wrapProgram $out/bin/hare \ - --prefix PATH : ${lib.makeBinPath [binutils-unwrapped harec qbe]} + --prefix PATH : ${lib.makeBinPath [harec qbe]} \ + --set LD ${hareLd}/bin/rust-ld \ + --set AS ${hareAs} ''; setupHook = ./setup-hook.sh; diff --git a/pkgs/harec.nix b/pkgs/harec.nix index 889b7d3..2b926cb 100644 --- a/pkgs/harec.nix +++ b/pkgs/harec.nix @@ -3,16 +3,15 @@ let platform = lib.toLower stdenv.hostPlatform.uname.system; arch = stdenv.hostPlatform.uname.processor; qbePlatform = { - x86_64 = "amd64_sysv"; - aarch64 = "arm64"; - riscv64 = "rv64"; + x86_64 = "amd64_apple"; + aarch64 = "arm64_apple"; }.${arch}; in stdenv.mkDerivation (finalAttrs: { pname = "harec"; version = "0.24"; src = builtins.fetchGit { - url = "github.com/hshq/harelang-harec"; + url = "https://github.com/hshq/harelang-harec"; ref = "master"; rev = "51446fdef8b39df1fbf4fa2644d3f51f020f974a"; }; diff --git a/pkgs/ld.rs b/pkgs/ld.rs new file mode 100755 index 0000000..d5be1d3 --- /dev/null +++ b/pkgs/ld.rs @@ -0,0 +1,32 @@ +#!/usr/bin/env -S cargo +nightly -q -Zscript + +use std::env; +use std::process::Command; + +fn main() { + let mut args = vec![ + "-e".to_string(), "_start".to_string(), + "-lSystem".to_string(), + "-L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk".to_string() + ]; + + let mut argv: Vec<_> = env::args().skip(1).collect(); + while argv.len() > 0 { + let arg = argv.remove(0); + match &*arg { + "-T" | "-z" => { + // Skip next one too + _ = argv.remove(0); + } + "--gc-sections" => { } + _ if arg.starts_with("-T") => { } + _ if arg.starts_with("-z") => { } + _ if arg.starts_with("--script=") => { } + _ => { + args.push(arg); + } + } + } + + Command::new("ld").args(&args).status().unwrap(); +}