From d840f40e8964fe547cb9a6122d1d598afd9c7cf0 Mon Sep 17 00:00:00 2001 From: Graeme Geldenhuys Date: Thu, 25 Jun 2026 12:03:09 +0100 Subject: [PATCH] feat(rtl): migrate blaise_start .s to inline asm --- runtime/Makefile | 12 +++-- runtime/src/main/asm/blaise_start_x86_64.s | 53 ---------------------- runtime/src/main/pascal/blaise_start.pas | 52 +++++++++++++++++++++ 3 files changed, 60 insertions(+), 57 deletions(-) delete mode 100644 runtime/src/main/asm/blaise_start_x86_64.s create mode 100644 runtime/src/main/pascal/blaise_start.pas diff --git a/runtime/Makefile b/runtime/Makefile index bf973d0..f5eb654 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -41,12 +41,12 @@ BLAISE = $(COMPILER_BIN)/blaise BLAISE_FLAGS = --no-incremental --assembler internal # Assembly sources — platform-specific, no C compiler needed. -# (blaise_atomic, blaise_setjmp migrated to inline-asm Pascal units.) -ASM_OBJS = $(OBJ_DIR)/blaise_start_x86_64.o \ - $(OBJ_DIR)/blaise_utf8_x86_64.o +# (blaise_atomic, blaise_setjmp, blaise_start migrated to inline-asm units.) +ASM_OBJS = $(OBJ_DIR)/blaise_utf8_x86_64.o # Pascal RTL units compiled via the Blaise compiler. -PAS_OBJS = $(OBJ_DIR)/blaise_atomic.o \ +PAS_OBJS = $(OBJ_DIR)/blaise_start.o \ + $(OBJ_DIR)/blaise_atomic.o \ $(OBJ_DIR)/blaise_setjmp.o \ $(OBJ_DIR)/blaise_mem.o \ $(OBJ_DIR)/blaise_str.o \ @@ -74,6 +74,10 @@ $(OBJ_DIR)/%.o: $(ASM_DIR)/%.s $(CC) -c -o $@ $< # --- Pascal unit rules (unit-as-top-level) --- +$(OBJ_DIR)/blaise_start.o: $(PAS_SRC_DIR)/blaise_start.pas + @mkdir -p $(OBJ_DIR) + $(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@ + $(OBJ_DIR)/blaise_atomic.o: $(PAS_SRC_DIR)/blaise_atomic.pas @mkdir -p $(OBJ_DIR) $(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@ diff --git a/runtime/src/main/asm/blaise_start_x86_64.s b/runtime/src/main/asm/blaise_start_x86_64.s deleted file mode 100644 index b640d05..0000000 --- a/runtime/src/main/asm/blaise_start_x86_64.s +++ /dev/null @@ -1,53 +0,0 @@ -# -# Blaise — An Object Pascal Compiler -# Copyright (c) 2026 Graeme Geldenhuys -# SPDX-License-Identifier: Apache-2.0 WITH Swift-exception -# Licensed under the Apache License v2.0 with Runtime Library Exception. -# See LICENSE file in the project root for full license terms. -# -# Program entry point (x86_64, System V ABI, glibc-compatible). -# -# This replaces the system Scrt1.o so the internal linker needs no -# gcc-provided startup object and no versioned gcc directory (issue #142). -# The runtime ships its own _start; the linker (TLinker.Link '_start') uses -# this symbol as the ELF entry point. -# -# On entry the kernel hands us the initial process stack: -# (%rsp) argc -# 8(%rsp) argv[0] -# ... argv[argc] = NULL, then envp, then the auxiliary vector -# and %rdx holds the dynamic linker's finaliser (rtld_fini) for PIE images. -# -# We marshal these into the arguments __libc_start_main expects: -# __libc_start_main(main, argc, argv, init, fini, rtld_fini, stack_end) -# %rdi = main (the program's C-style entry) -# %rsi = argc -# %rdx = argv -# %rcx = init = NULL (unit init runs from main, not .init_array) -# %r8 = fini = NULL -# %r9 = rtld_fini -# stack_end pushed on the stack -# glibc runs the init array (if any), calls main(argc, argv, envp), then -# exit(main's return value). This mirrors modern glibc's own Scrt1.o. - -.text - -.globl _start -.type _start, @function -_start: - endbr64 - xor %ebp, %ebp # outermost frame marker (ABI) - mov %rdx, %r9 # rtld_fini -> arg 7 - pop %rsi # argc -> arg 2 - mov %rsp, %rdx # argv -> arg 3 (now at stack top) - and $0xfffffffffffffff0, %rsp # re-align stack to 16 bytes - push %rax # padding (8 bytes) ... - push %rsp # ... and stack_end, keeping alignment - xor %r8d, %r8d # fini = NULL -> arg 5 - xor %ecx, %ecx # init = NULL -> arg 4 - lea main(%rip), %rdi # main -> arg 1 - call __libc_start_main@PLT # does not return - hlt # trap if it ever does -.size _start, .-_start - -.section .note.GNU-stack,"",@progbits diff --git a/runtime/src/main/pascal/blaise_start.pas b/runtime/src/main/pascal/blaise_start.pas new file mode 100644 index 0000000..b141b55 --- /dev/null +++ b/runtime/src/main/pascal/blaise_start.pas @@ -0,0 +1,52 @@ +{ + Blaise - An Object Pascal Compiler + Copyright (c) 2026 Graeme Geldenhuys + SPDX-License-Identifier: Apache-2.0 WITH Swift-exception + Licensed under the Apache License v2.0 with Runtime Library Exception. + See LICENSE file in the project root for full license terms. +} + +unit blaise_start; + +// Program entry point (x86_64, System V ABI, glibc-compatible). +// +// Inline-assembler port of runtime/src/main/asm/blaise_start_x86_64.s — _start +// is now an `asm … end` routine so the RTL needs no hand-written .s +// (docs/inline-asm-design.adoc, §"Migration of the .s files"). +// +// This replaces the system Scrt1.o so the internal linker needs no +// gcc-provided startup object (issue #142). The linker uses '_start' as the +// ELF entry point; an unmangled unit-level routine named _start emits exactly +// that symbol. +// +// On entry the kernel hands us the initial process stack: +// (%rsp) argc 8(%rsp) argv[0] ... then NULL, envp, auxv +// and %rdx holds rtld_fini for PIE images. We marshal these into the args +// __libc_start_main(main, argc, argv, init=NULL, fini=NULL, rtld_fini, +// stack_end) expects; glibc runs the init array, calls main(argc, argv, envp), +// then exit(main's return). nostackframe: the body owns the whole frame. + +interface + +procedure _start; + +implementation + +procedure _start; assembler; nostackframe; +asm + endbr64 + xor %ebp, %ebp + mov %rdx, %r9 + pop %rsi + mov %rsp, %rdx + and $0xfffffffffffffff0, %rsp + push %rax + push %rsp + xor %r8d, %r8d + xor %ecx, %ecx + lea main(%rip), %rdi + call __libc_start_main@PLT + hlt +end; + +end.