feat(rtl): migrate blaise_start .s to inline asm

This commit is contained in:
Graeme Geldenhuys 2026-06-25 12:03:09 +01:00
parent 7781242696
commit d840f40e89
3 changed files with 60 additions and 57 deletions

View file

@ -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 $@

View file

@ -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

View file

@ -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.