From 5ab4f99a88361ee7d1d0ec1379afcfe234e52145 Mon Sep 17 00:00:00 2001 From: wk333 <13474090681@163.com> Date: Fri, 21 Jun 2024 10:21:27 +0800 Subject: [PATCH] Sync 24.03-LTS release --- 0004-add-loongarch64-native-support.patch | 4160 +++++++++++++++++++++ ocaml.spec | 23 +- 2 files changed, 4171 insertions(+), 12 deletions(-) create mode 100644 0004-add-loongarch64-native-support.patch diff --git a/0004-add-loongarch64-native-support.patch b/0004-add-loongarch64-native-support.patch new file mode 100644 index 0000000..205c2d6 --- /dev/null +++ b/0004-add-loongarch64-native-support.patch @@ -0,0 +1,4160 @@ +From 0ceb8f2a8457b09a31112046aa30f144f09b153c Mon Sep 17 00:00:00 2001 +From: yala +Date: Sat, 8 Jul 2023 17:01:21 +0800 +Subject: [PATCH] add loongarch64 native support + +--- + Makefile | 2 +- + asmcomp/dune | 4 +- + asmcomp/loongarch64/CSE.ml | 38 + + asmcomp/loongarch64/NOTES.md | 13 + + asmcomp/loongarch64/arch.ml | 91 ++ + asmcomp/loongarch64/emit.mlp | 683 +++++++++++++++ + asmcomp/loongarch64/proc.ml | 320 +++++++ + asmcomp/loongarch64/reload.ml | 18 + + asmcomp/loongarch64/scheduling.ml | 21 + + asmcomp/loongarch64/selection.ml | 64 ++ + build-aux/config.guess | 1211 ++++++++++++++------------ + build-aux/config.sub | 124 ++- + configure.ac | 9 +- + runtime/caml/stack.h | 5 + + runtime/loongarch64.S | 443 ++++++++++ + testsuite/tools/asmgen_loongarch64.S | 75 ++ + 16 files changed, 2520 insertions(+), 601 deletions(-) + create mode 100644 asmcomp/loongarch64/CSE.ml + create mode 100644 asmcomp/loongarch64/NOTES.md + create mode 100644 asmcomp/loongarch64/arch.ml + create mode 100644 asmcomp/loongarch64/emit.mlp + create mode 100644 asmcomp/loongarch64/proc.ml + create mode 100644 asmcomp/loongarch64/reload.ml + create mode 100644 asmcomp/loongarch64/scheduling.ml + create mode 100644 asmcomp/loongarch64/selection.ml + create mode 100644 runtime/loongarch64.S + create mode 100644 testsuite/tools/asmgen_loongarch64.S + +diff --git a/Makefile b/Makefile +index 0e92785..d1d9dd7 100644 +--- a/Makefile ++++ b/Makefile +@@ -39,7 +39,7 @@ include stdlib/StdlibModules + + CAMLC=$(BOOT_OCAMLC) -g -nostdlib -I boot -use-prims runtime/primitives + CAMLOPT=$(OCAMLRUN) ./ocamlopt$(EXE) -g -nostdlib -I stdlib -I otherlibs/dynlink +-ARCHES=amd64 i386 arm arm64 power s390x riscv ++ARCHES=amd64 i386 arm arm64 power s390x riscv loongarch64 + INCLUDES=-I utils -I parsing -I typing -I bytecomp -I file_formats \ + -I lambda -I middle_end -I middle_end/closure \ + -I middle_end/flambda -I middle_end/flambda/base_types \ +diff --git a/asmcomp/dune b/asmcomp/dune +index 1a4d561..1817bc4 100644 +--- a/asmcomp/dune ++++ b/asmcomp/dune +@@ -23,6 +23,7 @@ + (glob_files power/*.ml) + (glob_files riscv/*.ml) + (glob_files s390x/*.ml)) ++ (glob_files loongarch64/*.ml) + (action (bash "cp `grep '^ARCH=' %{conf} | cut -d'=' -f2`/*.ml ."))) + + (rule +@@ -35,7 +36,8 @@ + i386/emit.mlp + power/emit.mlp + riscv/emit.mlp +- s390x/emit.mlp) ++ s390x/emit.mlp ++ loongarch64/emit.mlp) + (action + (progn + (with-stdout-to contains-input-name +diff --git a/asmcomp/loongarch64/CSE.ml b/asmcomp/loongarch64/CSE.ml +new file mode 100644 +index 0000000..dc7c66c +--- /dev/null ++++ b/asmcomp/loongarch64/CSE.ml +@@ -0,0 +1,38 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* CSE for the loongarch *) ++ ++open Arch ++open Mach ++open CSEgen ++ ++class cse = object (_self) ++ ++inherit cse_generic as super ++ ++method! class_of_operation op = ++ match op with ++ | Ispecific(Imultaddf _ | Imultsubf _) -> Op_pure ++ | _ -> super#class_of_operation op ++ ++method! is_cheap_operation op = ++ match op with ++ | Iconst_int n -> n <= 0x7FFF_FFFFn && n >= -0x8000_0000n ++ | _ -> false ++ ++end ++ ++let fundecl f = ++ (new cse)#fundecl f +diff --git a/asmcomp/loongarch64/NOTES.md b/asmcomp/loongarch64/NOTES.md +new file mode 100644 +index 0000000..aacca61 +--- /dev/null ++++ b/asmcomp/loongarch64/NOTES.md +@@ -0,0 +1,13 @@ ++# Supported platforms ++ ++LoongArch in 64-bit mode ++ ++Debian architecture name: `loongarch64` ++ ++# Reference documents ++ ++* Instruction set specification: ++ - https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html ++ ++* ELF ABI specification: ++ - https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html +diff --git a/asmcomp/loongarch64/arch.ml b/asmcomp/loongarch64/arch.ml +new file mode 100644 +index 0000000..8dd4abe +--- /dev/null ++++ b/asmcomp/loongarch64/arch.ml +@@ -0,0 +1,91 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* Specific operations for the loongarch processor *) ++ ++open Format ++ ++(* Machine-specific command-line options *) ++ ++let command_line_options = [] ++ ++(* Specific operations *) ++ ++type specific_operation = ++ | Imultaddf of bool (* multiply, optionally negate, and add *) ++ | Imultsubf of bool (* multiply, optionally negate, and subtract *) ++ ++(* Addressing modes *) ++ ++type addressing_mode = ++ | Iindexed of int (* reg + displ *) ++ ++let is_immediate n = ++ (n <= 0x7FF) && (n >= -0x800) ++ ++(* Sizes, endianness *) ++ ++let big_endian = false ++ ++let size_addr = 8 ++let size_int = size_addr ++let size_float = 8 ++ ++let allow_unaligned_access = false ++ ++(* Behavior of division *) ++ ++let division_crashes_on_overflow = false ++ ++(* Operations on addressing modes *) ++ ++let identity_addressing = Iindexed 0 ++ ++let offset_addressing addr delta = ++ match addr with ++ | Iindexed n -> Iindexed(n + delta) ++ ++let num_args_addressing = function ++ | Iindexed _ -> 1 ++ ++(* Printing operations and addressing modes *) ++ ++let print_addressing printreg addr ppf arg = ++ match addr with ++ | Iindexed n -> ++ let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in ++ fprintf ppf "%a%s" printreg arg.(0) idx ++ ++let print_specific_operation printreg op ppf arg = ++ match op with ++ | Imultaddf false -> ++ fprintf ppf "%a *f %a +f %a" ++ printreg arg.(0) printreg arg.(1) printreg arg.(2) ++ | Imultaddf true -> ++ fprintf ppf "-f (%a *f %a +f %a)" ++ printreg arg.(0) printreg arg.(1) printreg arg.(2) ++ | Imultsubf false -> ++ fprintf ppf "%a *f %a -f %a" ++ printreg arg.(0) printreg arg.(1) printreg arg.(2) ++ | Imultsubf true -> ++ fprintf ppf "-f (%a *f %a -f %a)" ++ printreg arg.(0) printreg arg.(1) printreg arg.(2) ++ ++(* Specific operations that are pure *) ++ ++let operation_is_pure _ = true ++ ++(* Specific operations that can raise *) ++ ++let operation_can_raise _ = false +diff --git a/asmcomp/loongarch64/emit.mlp b/asmcomp/loongarch64/emit.mlp +new file mode 100644 +index 0000000..fd4a30b +--- /dev/null ++++ b/asmcomp/loongarch64/emit.mlp +@@ -0,0 +1,683 @@ ++(**************************************************************************) ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++ ++(* Emission of loongarch assembly code *) ++ ++open Cmm ++open Arch ++open Proc ++open Reg ++open Mach ++open Linear ++open Emitaux ++open Emitenv ++ ++(* Layout of the stack. The stack is kept 16-aligned. *) ++ ++let frame_size env = ++ let size = ++ env.stack_offset + (* Trap frame, outgoing parameters *) ++ size_int * env.f.fun_num_stack_slots.(0) + (* Local int variables *) ++ size_float * env.f.fun_num_stack_slots.(1) + (* Local float variables *) ++ (if env.f.fun_contains_calls then size_addr else 0) (* Return address *) ++ in ++ Misc.align size 16 ++ ++let slot_offset env loc cls = ++ match loc with ++ | Local n -> ++ ("$sp", ++ if cls = 0 ++ then env.stack_offset + env.f.fun_num_stack_slots.(1) * size_float ++ + n * size_int ++ else env.stack_offset + n * size_float) ++ | Incoming n -> ++ ("$sp", frame_size env + n) ++ | Outgoing n -> ++ ("$sp", n) ++ | Domainstate n -> ++ ("$s8", n + Domainstate.(idx_of_field Domain_extra_params) * 8) ++ ++(* Output a symbol *) ++ ++let emit_symbol s = ++ emit_symbol '$' s ++ ++let emit_jump op s = ++ if !Clflags.dlcode || !Clflags.pic_code ++ then `{emit_string op} %plt({emit_symbol s})` ++ else `{emit_string op} {emit_symbol s}` ++ ++let emit_call = emit_jump "bl" ++let emit_tail = emit_jump "b" ++ ++(* Output a label *) ++ ++let emit_label lbl = ++ emit_string ".L"; emit_int lbl ++ ++(* Section switching *) ++ ++let data_space = ++ ".section .data" ++ ++let code_space = ++ ".section .text" ++ ++let rodata_space = ++ ".section .rodata" ++ ++(* Names for special regs *) ++ ++let reg_tmp = phys_reg 22 (* t1 *) ++let reg_t2 = phys_reg 13 (* t2 *) ++let reg_domain_state_ptr = phys_reg 25 (* s8 *) ++let reg_trap = phys_reg 23 (* s1 *) ++let reg_alloc_ptr = phys_reg 24 (* s7 *) ++ ++(* Output a pseudo-register *) ++ ++let reg_name = function ++ | {loc = Reg r} -> register_name r ++ | _ -> Misc.fatal_error "Emit.reg_name" ++ ++let emit_reg r = ++ emit_string (reg_name r) ++ ++(* Adjust sp by the given byte amount *) ++ ++let emit_stack_adjustment = function ++ | 0 -> () ++ | n when is_immediate n -> ++ ` addi.d $sp, $sp, {emit_int n}\n` ++ | n -> ++ ` li.d {emit_reg reg_tmp}, {emit_int n}\n`; ++ ` add.d $sp, $sp, {emit_reg reg_tmp}\n` ++ ++(* Adjust stack_offset and emit corresponding CFI directive *) ++ ++let adjust_stack_offset env delta = ++ env.stack_offset <- env.stack_offset + delta; ++ cfi_adjust_cfa_offset delta ++ ++let emit_mem_op ?(base = "$sp") op src ofs = ++ if is_immediate ofs then ++ ` {emit_string op} {emit_string src}, {emit_string base}, {emit_int ofs}\n` ++ else begin ++ ` li.d {emit_reg reg_tmp}, {emit_int ofs}\n`; ++ ` add.d {emit_reg reg_tmp}, {emit_string base}, {emit_reg reg_tmp}\n`; ++ ` {emit_string op} {emit_string src}, {emit_reg reg_tmp}, 0\n` ++ end ++ ++let reload_ra n = ++ emit_mem_op "ld.d" "$ra" (n - size_addr) ++ ++let store_ra n = ++ emit_mem_op "st.d" "$ra" (n - size_addr) ++ ++let emit_store ?base src ofs = ++ emit_mem_op ?base "st.d" (reg_name src) ofs ++ ++let emit_load ?base dst ofs = ++ emit_mem_op ?base "ld.d" (reg_name dst) ofs ++ ++let emit_float_load ?base dst ofs = ++ emit_mem_op ?base "fld.d" (reg_name dst) ofs ++ ++let emit_float_store ?base src ofs = ++ emit_mem_op ?base "fst.d" (reg_name src) ofs ++ ++let emit_float_test cmp ~arg ~res = ++let negated = ++ match cmp with ++ | CFneq | CFnlt | CFngt | CFnle | CFnge -> true ++ | CFeq | CFlt | CFgt | CFle | CFge -> false ++in ++begin match cmp with ++| CFeq | CFneq -> ` fcmp.ceq.d $fcc0, {emit_reg arg.(0)}, {emit_reg arg.(1)}\n movcf2gr {emit_reg res}, $fcc0\n` ++| CFlt | CFnlt -> ` fcmp.clt.d $fcc0, {emit_reg arg.(0)}, {emit_reg arg.(1)}\n movcf2gr {emit_reg res}, $fcc0\n` ++| CFgt | CFngt -> ` fcmp.clt.d $fcc0, {emit_reg arg.(1)}, {emit_reg arg.(0)}\n movcf2gr {emit_reg res}, $fcc0\n` ++| CFle | CFnle -> ` fcmp.cle.d $fcc0, {emit_reg arg.(0)}, {emit_reg arg.(1)}\n movcf2gr {emit_reg res}, $fcc0\n` ++| CFge | CFnge -> ` fcmp.cle.d $fcc0, {emit_reg arg.(1)}, {emit_reg arg.(0)}\n movcf2gr {emit_reg res}, $fcc0\n` ++end; ++negated ++ ++(* Record live pointers at call points *) ++ ++let record_frame_label env live dbg = ++ let lbl = new_label () in ++ let live_offset = ref [] in ++ Reg.Set.iter ++ (function ++ {typ = Val; loc = Reg r} -> ++ live_offset := (r lsl 1) + 1 :: !live_offset ++ | {typ = Val; loc = Stack s} as reg -> ++ let (base, ofs) = slot_offset env s (register_class reg) in ++ assert (base = "$sp"); ++ live_offset := ofs :: !live_offset ++ | {typ = Addr} as r -> ++ Misc.fatal_error ("bad GC root " ^ Reg.name r) ++ | _ -> () ++ ) ++ live; ++ record_frame_descr ~label:lbl ~frame_size:(frame_size env) ++ ~live_offset:!live_offset dbg; ++ lbl ++ ++let record_frame env live dbg = ++ let lbl = record_frame_label env live dbg in ++ `{emit_label lbl}:\n` ++ ++let emit_call_gc gc = ++ `{emit_label gc.gc_lbl}:\n`; ++ ` {emit_call "caml_call_gc"}\n`; ++ `{emit_label gc.gc_frame_lbl}:\n`; ++ ` b {emit_label gc.gc_return_lbl}\n` ++ ++let bound_error_label env dbg = ++ if !Clflags.debug || env.bound_error_sites = [] then begin ++ let lbl_bound_error = new_label() in ++ let lbl_frame = record_frame_label env Reg.Set.empty (Dbg_other dbg) in ++ env.bound_error_sites <- ++ { bd_lbl = lbl_bound_error; ++ bd_frame = lbl_frame; } :: env.bound_error_sites; ++ lbl_bound_error ++ end else ++ let bd = List.hd env.bound_error_sites in ++ bd.bd_lbl ++ ++let emit_call_bound_error bd = ++ `{emit_label bd.bd_lbl}:\n`; ++ ` {emit_call "caml_ml_array_bound_error"}\n`; ++ `{emit_label bd.bd_frame}:\n` ++ ++(* Names for various instructions *) ++ ++let name_for_intop = function ++ | Iadd -> "add.d" ++ | Isub -> "sub.d" ++ | Imul -> "mul.d" ++ | Imulh -> "mulh.d" ++ | Idiv -> "div.d" ++ | Iand -> "and" ++ | Ior -> "or" ++ | Ixor -> "xor" ++ | Ilsl -> "sll.d" ++ | Ilsr -> "srl.d" ++ | Iasr -> "sra.d" ++ | Imod -> "mod.d" ++ | _ -> Misc.fatal_error "Emit.Intop" ++ ++let name_for_intop_imm = function ++ | Iadd -> "addi.d" ++ | Iand -> "andi" ++ | Ior -> "ori" ++ | Ixor -> "xori" ++ | Ilsl -> "slli.d" ++ | Ilsr -> "srli.d" ++ | Iasr -> "srai.d" ++ | _ -> Misc.fatal_error "Emit.Intop_imm" ++ ++let name_for_floatop1 = function ++ | Inegf -> "fneg.d" ++ | Iabsf -> "fabs.d" ++ | _ -> Misc.fatal_error "Emit.Iopf1" ++ ++let name_for_floatop2 = function ++ | Iaddf -> "fadd.d" ++ | Isubf -> "fsub.d" ++ | Imulf -> "fmul.d" ++ | Idivf -> "fdiv.d" ++ | _ -> Misc.fatal_error "Emit.Iopf2" ++ ++let name_for_specific = function ++ | Imultaddf false -> "fmadd.d" ++ | Imultaddf true -> "fnmadd.d" ++ | Imultsubf false -> "fmsub.d" ++ | Imultsubf true -> "fnmsub.d" ++ ++(* Output the assembly code for an instruction *) ++ ++let emit_instr env i = ++ emit_debug_info i.dbg; ++ match i.desc with ++ Lend -> () ++ | Lprologue -> ++ assert (env.f.fun_prologue_required); ++ let n = frame_size env in ++ emit_stack_adjustment (-n); ++ if n > 0 then cfi_adjust_cfa_offset n; ++ if env.f.fun_contains_calls then begin ++ store_ra n; ++ cfi_offset ~reg:1 (* ra *) ~offset:(-size_addr) ++ end; ++ | Lop(Imove | Ispill | Ireload) -> ++ let src = i.arg.(0) and dst = i.res.(0) in ++ if src.loc <> dst.loc then begin ++ match (src, dst) with ++ | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Reg _} -> ++ ` move {emit_reg dst}, {emit_reg src}\n` ++ | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} -> ++ ` fmov.d {emit_reg dst}, {emit_reg src}\n` ++ | {loc = Reg _; typ = Float}, {loc = Reg _; typ = (Val | Int | Addr)} -> ++ ` movfr2gr.d {emit_reg dst}, {emit_reg src}\n` ++ | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack s} -> ++ let (base, ofs) = slot_offset env s (register_class dst) in ++ emit_store ~base src ofs ++ | {loc = Reg _; typ = Float}, {loc = Stack s} -> ++ let (base, ofs) = slot_offset env s (register_class dst) in ++ emit_float_store ~base src ofs ++ | {loc = Stack s; typ = (Val | Int | Addr)}, {loc = Reg _} -> ++ let (base, ofs) = slot_offset env s (register_class src) in ++ emit_load ~base dst ofs ++ | {loc = Stack s; typ = Float}, {loc = Reg _} -> ++ let (base, ofs) = slot_offset env s (register_class src) in ++ emit_float_load ~base dst ofs ++ | {loc = Stack _}, {loc = Stack _} ++ | {loc = Unknown}, _ | _, {loc = Unknown} -> ++ Misc.fatal_error "Emit: Imove" ++ end ++ | Lop(Iconst_int n) -> ++ ` li.d {emit_reg i.res.(0)}, {emit_nativeint n}\n` ++ | Lop(Iconst_float f) -> ++ let lbl = new_label() in ++ env.float_literals <- {fl=f; lbl} :: env.float_literals; ++ ` la.local {emit_reg reg_tmp}, {emit_label lbl} \n`; ++ ` fld.d {emit_reg i.res.(0)}, {emit_reg reg_tmp}, 0\n` ++ | Lop(Iconst_symbol s) -> ++ ` pcaddi {emit_reg i.res.(0)}, 0 \n`; ++ ` b 7112233f\n`; ++ ` .dword {emit_symbol s}\n`; ++ ` 7112233: ld.d {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 8\n` ++ | Lop(Icall_ind) -> ++ ` jirl $ra, {emit_reg i.arg.(0)}, 0\n`; ++ record_frame env i.live (Dbg_other i.dbg) ++ | Lop(Icall_imm {func}) -> ++ ` {emit_call func}\n`; ++ record_frame env i.live (Dbg_other i.dbg) ++ | Lop(Itailcall_ind) -> ++ let n = frame_size env in ++ if env.f.fun_contains_calls then reload_ra n; ++ emit_stack_adjustment n; ++ ` jr {emit_reg i.arg.(0)}\n` ++ | Lop(Itailcall_imm {func}) -> ++ if func = env.f.fun_name then begin ++ ` b {emit_label env.f.fun_tailrec_entry_point_label}\n` ++ end else begin ++ let n = frame_size env in ++ if env.f.fun_contains_calls then reload_ra n; ++ emit_stack_adjustment n; ++ ` {emit_tail func}\n` ++ end ++ | Lop(Iextcall{func; alloc = true}) -> ++ ` la.global {emit_reg reg_t2}, {emit_symbol func}\n`; ++ ` {emit_call "caml_c_call"}\n`; ++ record_frame env i.live (Dbg_other i.dbg) ++ | Lop(Iextcall{func; alloc = false}) -> ++ ` {emit_call func}\n` ++ | Lop(Istackoffset n) -> ++ assert (n mod 16 = 0); ++ emit_stack_adjustment (-n); ++ adjust_stack_offset env n ++ | Lop(Iload(Single, Iindexed ofs, _mut)) -> ++ ` fld.s {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int ofs}\n`; ++ ` fcvt.d.s {emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n` ++ | Lop(Iload(chunk, Iindexed ofs, _mut)) -> ++ let instr = ++ match chunk with ++ | Byte_unsigned -> "ld.bu" ++ | Byte_signed -> "ld.b" ++ | Sixteen_unsigned -> "ld.hu" ++ | Sixteen_signed -> "ld.h" ++ | Thirtytwo_unsigned -> "ld.wu" ++ | Thirtytwo_signed -> "ld.w" ++ | Word_int | Word_val -> "ld.d" ++ | Single -> assert false ++ | Double -> "fld.d" ++ in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int ofs}\n` ++ | Lop(Istore(Single, Iindexed ofs, _)) -> ++ (* ft0 is marked as destroyed for this operation *) ++ ` fcvt.s.d $ft0, {emit_reg i.arg.(0)}\n`; ++ ` fst.s $ft0, {emit_reg i.arg.(1)}, {emit_int ofs}\n` ++ | Lop(Istore(chunk, Iindexed ofs, _)) -> ++ let instr = ++ match chunk with ++ | Byte_unsigned | Byte_signed -> "st.b" ++ | Sixteen_unsigned | Sixteen_signed -> "st.h" ++ | Thirtytwo_unsigned | Thirtytwo_signed -> "st.w" ++ | Word_int | Word_val -> "st.d" ++ | Single -> assert false ++ | Double -> "fst.d" ++ in ++ ` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)} ,{emit_int ofs}\n` ++ | Lop(Ialloc {bytes; dbginfo}) -> ++ let lbl_frame_lbl = record_frame_label env i.live (Dbg_alloc dbginfo) in ++ let lbl_after_alloc = new_label () in ++ let lbl_call_gc = new_label () in ++ let n = -bytes in ++ let offset = Domainstate.(idx_of_field Domain_young_limit) * 8 in ++ if is_immediate n then ++ ` addi.d {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, {emit_int n}\n` ++ else begin ++ ` li.d {emit_reg reg_tmp}, {emit_int n}\n`; ++ ` add.d {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, {emit_reg reg_tmp}\n` ++ end; ++ ` ld.d {emit_reg reg_tmp}, {emit_reg reg_domain_state_ptr},{emit_int offset}\n`; ++ ` sltu {emit_reg reg_tmp}, {emit_reg reg_alloc_ptr}, {emit_reg reg_tmp}\n`; ++ ` bnez {emit_reg reg_tmp}, {emit_label lbl_call_gc}\n`; ++ `{emit_label lbl_after_alloc}:\n`; ++ ` addi.d {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, {emit_int size_addr}\n`; ++ env.call_gc_sites <- ++ { gc_lbl = lbl_call_gc; ++ gc_return_lbl = lbl_after_alloc; ++ gc_frame_lbl = lbl_frame_lbl } :: env.call_gc_sites ++ | Lop(Ipoll { return_label }) -> ++ let lbl_frame_lbl = record_frame_label env i.live (Dbg_alloc []) in ++ let lbl_after_poll = match return_label with ++ | None -> new_label() ++ | Some(lbl) -> lbl in ++ let lbl_call_gc = new_label () in ++ let offset = Domainstate.(idx_of_field Domain_young_limit) * 8 in ++ ` ld.d {emit_reg reg_tmp}, {emit_reg reg_domain_state_ptr} ,{emit_int offset}\n`; ++ begin match return_label with ++ | None -> ` bltu {emit_reg reg_alloc_ptr}, {emit_reg reg_tmp}, {emit_label lbl_call_gc}\n`; ++ `{emit_label lbl_after_poll}:\n`; ++ | Some lbl -> ` bgeu {emit_reg reg_alloc_ptr}, {emit_reg reg_tmp}, {emit_label lbl}\n`; ++ ` b {emit_label lbl_call_gc}\n` ++ end; ++ env.call_gc_sites <- ++ { gc_lbl = lbl_call_gc; ++ gc_return_lbl = lbl_after_poll; ++ gc_frame_lbl = lbl_frame_lbl } :: env.call_gc_sites ++ | Lop(Iintop(Icomp cmp)) -> ++ begin match cmp with ++ | Isigned Clt -> ++ ` slt {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Isigned Cge -> ++ ` slt {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` xori {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 1\n`; ++ | Isigned Cgt -> ++ ` slt {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n` ++ | Isigned Cle -> ++ ` slt {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`; ++ ` xori {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 1\n`; ++ | Isigned Ceq | Iunsigned Ceq -> ++ ` sub.d {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` sltui {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 1\n` ++ | Isigned Cne | Iunsigned Cne -> ++ ` sub.d {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` sltu {emit_reg i.res.(0)}, $zero, {emit_reg i.res.(0)}\n` ++ | Iunsigned Clt -> ++ ` sltu {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Iunsigned Cge -> ++ ` sltu {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ++ ` xori {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 1\n`; ++ | Iunsigned Cgt -> ++ ` sltu {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n` ++ | Iunsigned Cle -> ++ ` sltu {emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`; ++ ` xori {emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 1\n`; ++ end ++ | Lop(Iintop (Icheckbound)) -> ++ let lbl = bound_error_label env i.dbg in ++ ` bleu {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_label lbl}\n` ++ | Lop(Iintop op) -> ++ let instr = name_for_intop op in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Lop(Iintop_imm(Isub, n)) -> ++ ` addi.d {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int(-n)}\n` ++ | Lop(Iintop_imm(op, n)) -> (* FIXME *) ++ let instri = name_for_intop_imm op in ++ if n<0 then (* FIXME *) ++ let instr = name_for_intop op in ++ ` addi.d {emit_reg reg_tmp}, $zero, {emit_int n}\n {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp} \n` ++ else ++ ` {emit_string instri} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_int n}\n` ++ | Lop(Inegf | Iabsf as op) -> ++ let instr = name_for_floatop1 op in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n` ++ | Lop(Iaddf | Isubf | Imulf | Idivf as op) -> ++ let instr = name_for_floatop2 op in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n` ++ | Lop(Ifloatofint) -> ++ ` movgr2fr.d $ft0, {emit_reg i.arg.(0)} \n`; ++ ` ffint.d.l {emit_reg i.res.(0)}, $ft0\n` ++ | Lop(Iintoffloat) -> ++ ` ftintrz.l.d $ft0, {emit_reg i.arg.(0)}\n`; ++ ` movfr2gr.d {emit_reg i.res.(0)}, $ft0 \n` ++ | Lop(Iopaque) -> ++ assert (i.arg.(0).loc = i.res.(0).loc) ++ | Lop(Ispecific sop) -> ++ let instr = name_for_specific sop in ++ ` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(2)}\n` ++ | Lreloadretaddr -> ++ let n = frame_size env in ++ reload_ra n ++ | Lreturn -> ++ let n = frame_size env in ++ emit_stack_adjustment n; ++ ` jr $ra\n` ++ | Llabel lbl -> ++ `{emit_label lbl}:\n` ++ | Lbranch lbl -> ++ ` b {emit_label lbl}\n` ++ | Lcondbranch(tst, lbl) -> ++ begin match tst with ++ | Itruetest -> ++ ` bnez {emit_reg i.arg.(0)}, {emit_label lbl}\n` ++ | Ifalsetest -> ++ ` beqz {emit_reg i.arg.(0)}, {emit_label lbl}\n` ++ | Iinttest cmp -> ++ let name = match cmp with ++ | Iunsigned Ceq | Isigned Ceq -> "beq" ++ | Iunsigned Cne | Isigned Cne -> "bne" ++ | Iunsigned Cle -> "bleu" | Isigned Cle -> "ble" ++ | Iunsigned Cge -> "bgeu" | Isigned Cge -> "bge" ++ | Iunsigned Clt -> "bltu" | Isigned Clt -> "blt" ++ | Iunsigned Cgt -> "bgtu" | Isigned Cgt -> "bgt" ++ in ++ ` {emit_string name} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_label lbl}\n` ++ | Iinttest_imm _ -> ++ Misc.fatal_error "Emit.emit_instr (Iinttest_imm _)" ++ | Ifloattest cmp -> ++ let negated = emit_float_test cmp ~arg:i.arg ~res:reg_tmp in ++ let branch = ++ if negated ++ then "beqz" ++ else "bnez" ++ in ++ ` {emit_string branch} {emit_reg reg_tmp}, {emit_label lbl}\n` ++ | Ioddtest -> ++ ` andi {emit_reg reg_tmp}, {emit_reg i.arg.(0)}, 1\n`; ++ ` bnez {emit_reg reg_tmp}, {emit_label lbl}\n` ++ | Ieventest -> ++ ` andi {emit_reg reg_tmp}, {emit_reg i.arg.(0)}, 1\n`; ++ ` beqz {emit_reg reg_tmp}, {emit_label lbl}\n` ++ end ++ | Lcondbranch3(lbl0, lbl1, lbl2) -> ++ ` addi.d {emit_reg reg_tmp}, {emit_reg i.arg.(0)}, -1\n`; ++ begin match lbl0 with ++ | None -> () ++ | Some lbl -> ` bltz {emit_reg reg_tmp}, {emit_label lbl}\n` ++ end; ++ begin match lbl1 with ++ | None -> () ++ | Some lbl -> ` beqz {emit_reg reg_tmp}, {emit_label lbl}\n` ++ end; ++ begin match lbl2 with ++ | None -> () ++ | Some lbl -> ` bgtz {emit_reg reg_tmp}, {emit_label lbl}\n` ++ end ++ | Lswitch jumptbl -> ++ (* t0 is marked as destroyed for this operation *) ++ let lbl = new_label() in ++ ` la.local {emit_reg reg_tmp}, {emit_label lbl}\n`; ++ ` slli.d $t0, {emit_reg i.arg.(0)}, 2\n`; ++ ` add.d {emit_reg reg_tmp}, {emit_reg reg_tmp}, $t0\n`; ++ ` jr {emit_reg reg_tmp}\n`; ++ `{emit_label lbl}:\n`; ++ for i = 0 to Array.length jumptbl - 1 do ++ ` b {emit_label jumptbl.(i)}\n` ++ done ++ | Lentertrap -> ++ () ++ | Ladjust_trap_depth { delta_traps } -> ++ (* each trap occupes 16 bytes on the stack *) ++ let delta = 16 * delta_traps in ++ adjust_stack_offset env delta ++ | Lpushtrap {lbl_handler} -> ++ ` la.local {emit_reg reg_tmp}, {emit_label lbl_handler}\n`; ++ ` addi.d $sp, $sp, -16\n`; ++ adjust_stack_offset env 16; ++ emit_store reg_tmp size_addr; ++ emit_store reg_trap 0; ++ ` move {emit_reg reg_trap}, $sp\n` ++ | Lpoptrap -> ++ emit_load reg_trap 0; ++ ` addi.d $sp, $sp, 16\n`; ++ adjust_stack_offset env (-16) ++ | Lraise k -> ++ begin match k with ++ | Lambda.Raise_regular -> ++ let offset = Domainstate.(idx_of_field Domain_backtrace_pos) * 8 in ++ ` st.d $zero, {emit_reg reg_domain_state_ptr},{emit_int offset}\n`; ++ ` {emit_call "caml_raise_exn"}\n`; ++ record_frame env Reg.Set.empty (Dbg_raise i.dbg) ++ | Lambda.Raise_reraise -> ++ ` {emit_call "caml_raise_exn"}\n`; ++ record_frame env Reg.Set.empty (Dbg_raise i.dbg) ++ | Lambda.Raise_notrace -> ++ ` move $sp, {emit_reg reg_trap}\n`; ++ emit_load reg_tmp size_addr; ++ emit_load reg_trap 0; ++ ` addi.d $sp, $sp, 16\n`; ++ ` jr {emit_reg reg_tmp}\n` ++ end ++ ++(* Emit a sequence of instructions *) ++ ++let rec emit_all env = function ++ | {desc = Lend} -> () | i -> emit_instr env i; emit_all env i.next ++ ++(* Emission of a function declaration *) ++ ++let fundecl fundecl = ++ let env = mk_env fundecl in ++ ` .globl {emit_symbol fundecl.fun_name}\n`; ++ ` .type {emit_symbol fundecl.fun_name}, @function\n`; ++ ` {emit_string code_space}\n`; ++ ` .align 2\n`; ++ `{emit_symbol fundecl.fun_name}:\n`; ++ emit_debug_info fundecl.fun_dbg; ++ cfi_startproc(); ++ emit_all env fundecl.fun_body; ++ List.iter emit_call_gc env.call_gc_sites; ++ List.iter emit_call_bound_error env.bound_error_sites; ++ cfi_endproc(); ++ ` .size {emit_symbol fundecl.fun_name}, .-{emit_symbol fundecl.fun_name}\n`; ++ (* Emit the float literals *) ++ if env.float_literals <> [] then begin ++ ` {emit_string rodata_space}\n`; ++ ` .align 3\n`; ++ List.iter ++ (fun {fl; lbl} -> ++ `{emit_label lbl}:\n`; ++ emit_float64_directive ".quad" fl) ++ env.float_literals; ++ end ++ ++(* Emission of data *) ++ ++let declare_global_data s = ++ ` .globl {emit_symbol s}\n`; ++ ` .type {emit_symbol s}, @object\n` ++ ++let emit_item = function ++ | Cglobal_symbol s -> ++ declare_global_data s ++ | Cdefine_symbol s -> ++ `{emit_symbol s}:\n`; ++ | Cint8 n -> ++ ` .byte {emit_int n}\n` ++ | Cint16 n -> ++ ` .short {emit_int n}\n` ++ | Cint32 n -> ++ ` .long {emit_nativeint n}\n` ++ | Cint n -> ++ ` .quad {emit_nativeint n}\n` ++ | Csingle f -> ++ emit_float32_directive ".long" (Int32.bits_of_float f) ++ | Cdouble f -> ++ emit_float64_directive ".quad" (Int64.bits_of_float f) ++ | Csymbol_address s -> ++ ` .quad {emit_symbol s}\n` ++ | Cstring s -> ++ emit_bytes_directive " .byte " s ++ | Cskip n -> ++ if n > 0 then ` .space {emit_int n}\n` ++ | Calign n -> ++ ` .align {emit_int (Misc.log2 n)}\n` ++ ++let data l = ++ ` {emit_string data_space}\n`; ++ List.iter emit_item l ++ ++(* Beginning / end of an assembly file *) ++ ++let begin_assembly() = ++ if !Clflags.dlcode || !Clflags.pic_code then ` \n`; ++ ` .file \"\"\n`; (* PR#7073 *) ++ reset_debug_info (); ++ (* Emit the beginning of the segments *) ++ let lbl_begin = Compilenv.make_symbol (Some "data_begin") in ++ ` {emit_string data_space}\n`; ++ declare_global_data lbl_begin; ++ `{emit_symbol lbl_begin}:\n`; ++ let lbl_begin = Compilenv.make_symbol (Some "code_begin") in ++ ` {emit_string code_space}\n`; ++ declare_global_data lbl_begin; ++ `{emit_symbol lbl_begin}:\n` ++ ++let end_assembly() = ++ ` {emit_string code_space}\n`; ++ let lbl_end = Compilenv.make_symbol (Some "code_end") in ++ declare_global_data lbl_end; ++ `{emit_symbol lbl_end}:\n`; ++ ` .long 0\n`; ++ ` {emit_string data_space}\n`; ++ let lbl_end = Compilenv.make_symbol (Some "data_end") in ++ declare_global_data lbl_end; ++ ` .quad 0\n`; (* PR#6329 *) ++ `{emit_symbol lbl_end}:\n`; ++ ` .quad 0\n`; ++ (* Emit the frame descriptors *) ++ ` {emit_string data_space}\n`; (* not rodata because relocations inside *) ++ let lbl = Compilenv.make_symbol (Some "frametable") in ++ declare_global_data lbl; ++ `{emit_symbol lbl}:\n`; ++ emit_frames ++ { efa_code_label = (fun l -> ` .quad {emit_label l}\n`); ++ efa_data_label = (fun l -> ` .quad {emit_label l}\n`); ++ efa_8 = (fun n -> ` .byte {emit_int n}\n`); ++ efa_16 = (fun n -> ` .short {emit_int n}\n`); ++ efa_32 = (fun n -> ` .long {emit_int32 n}\n`); ++ efa_word = (fun n -> ` .quad {emit_int n}\n`); ++ efa_align = (fun n -> ` .align {emit_int (Misc.log2 n)}\n`); ++ efa_label_rel = (fun lbl ofs -> ++ ` .long ({emit_label lbl} - .) + {emit_int32 ofs}\n`); ++ efa_def_label = (fun l -> `{emit_label l}:\n`); ++ efa_string = (fun s -> emit_bytes_directive " .byte " (s ^ "\000")) ++ } +diff --git a/asmcomp/loongarch64/proc.ml b/asmcomp/loongarch64/proc.ml +new file mode 100644 +index 0000000..2e3d692 +--- /dev/null ++++ b/asmcomp/loongarch64/proc.ml +@@ -0,0 +1,320 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* Description of the loongarch *) ++ ++open Misc ++open Cmm ++open Reg ++open Arch ++open Mach ++ ++(* Instruction selection *) ++ ++let word_addressed = false ++ ++(* Registers available for register allocation *) ++ ++(* Integer register map ++ -------------------- ++ ++ zero always zero ++ ra return address ++ sp, gp, tp stack pointer, global pointer, thread pointer ++ a0-a7 0-7 arguments/results ++ s2-s6 8-12 arguments/results (preserved by C) ++ t2-t8 13-19 temporary ++ s0 20 general purpose (preserved by C) ++ t0 21 temporary ++ t1 22 temporary (used by code generator) ++ s1 23 trap pointer (preserved by C) ++ s7 24 allocation pointer (preserved by C) ++ s8 25 domain pointer (preserved by C) ++ ++ Floating-point register map ++ --------------------------- ++ ++ ft0-ft7 100-107 temporary ++ fs0-fs1 108-109 general purpose (preserved by C) ++ fa0-fa7 110-117 arguments/results ++ fs2-fs9 118-125 arguments/results (preserved by C) ++ fs10-fs11 126-127 general purpose (preserved by C) ++ ft8-ft11 128-131 temporary ++ ++ Additional notes ++ ---------------- ++ ++ - t1 is used by the code generator, so not available for register ++ allocation. ++ ++ - t0-t6 may be used by PLT stubs, so should not be used to pass ++ arguments and may be clobbered by [Ialloc] in the presence of dynamic ++ linking. ++*) ++ ++let int_reg_name = ++ [| "$a0"; "$a1"; "$a2"; "$a3"; "$a4"; "$a5"; "$a6"; "$a7"; (* 0 - 7 *) ++ "$s2"; "$s3"; "$s4"; "$s5"; "$s6"; (* 8 - 12 *) ++ "$t2"; "$t3"; "$t4"; "$t5"; "$t6"; "$t7"; "$t8"; (* 13 - 19 *) ++ "$s0"; (* 20 *) ++ "$t0"; "$t1"; (* 21 - 22 *) ++ "$s1"; "$s7"; "$s8" |] (* 23 - 25 *) ++ ++let float_reg_name = ++ [| "$ft0"; "$ft1"; "$ft2"; "$ft3"; "$ft4"; "$ft5"; "$ft6"; "$ft7"; ++ "$fs0"; "$fs1"; ++ "$fa0"; "$fa1"; "$fa2"; "$fa3"; "$fa4"; "$fa5"; "$fa6"; "$fa7"; ++ "$fs2"; "$fs3"; "$fs4"; "$fs5"; "$fs6"; "$fs7"; ++ "$ft8"; "$ft9"; "$ft10"; "$ft11"; "$ft12"; "$ft13"; "$ft14"; "$ft15"; |] ++ ++let num_register_classes = 2 ++ ++let register_class r = ++ match r.typ with ++ | Val | Int | Addr -> 0 ++ | Float -> 1 ++ ++let num_available_registers = [| 21; 32 |] ++ ++let first_available_register = [| 0; 100 |] ++ ++let register_name r = ++ if r < 100 then int_reg_name.(r) else float_reg_name.(r - 100) ++ ++let rotate_registers = true ++ ++(* Representation of hard registers by pseudo-registers *) ++ ++let hard_int_reg = ++ let v = Array.make 26 Reg.dummy in ++ for i = 0 to 25 do ++ v.(i) <- Reg.at_location Int (Reg i) ++ done; ++ v ++ ++let hard_float_reg = ++ let v = Array.make 32 Reg.dummy in ++ for i = 0 to 31 do ++ v.(i) <- Reg.at_location Float (Reg(100 + i)) ++ done; ++ v ++ ++let all_phys_regs = ++ Array.append hard_int_reg hard_float_reg ++ ++let phys_reg n = ++ if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100) ++ ++let stack_slot slot ty = ++ Reg.at_location ty (Stack slot) ++ ++(* Calling conventions *) ++ ++let size_domainstate_args = 64 * size_int ++ ++let calling_conventions ++ first_int last_int first_float last_float make_stack first_stack arg = ++ let loc = Array.make (Array.length arg) Reg.dummy in ++ let int = ref first_int in ++ let float = ref first_float in ++ let ofs = ref first_stack in ++ for i = 0 to Array.length arg - 1 do ++ match arg.(i) with ++ | Val | Int | Addr as ty -> ++ if !int <= last_int then begin ++ loc.(i) <- phys_reg !int; ++ incr int ++ end else begin ++ loc.(i) <- stack_slot (make_stack !ofs) ty; ++ ofs := !ofs + size_int ++ end ++ | Float -> ++ if !float <= last_float then begin ++ loc.(i) <- phys_reg !float; ++ incr float ++ end else begin ++ loc.(i) <- stack_slot (make_stack !ofs) Float; ++ ofs := !ofs + size_float ++ end ++ done; ++ (loc, Misc.align (max 0 !ofs) 16) (* Keep stack 16-aligned. *) ++ ++let incoming ofs = ++ if ofs >= 0 ++ then Incoming ofs ++ else Domainstate (ofs + size_domainstate_args) ++let outgoing ofs = ++ if ofs >= 0 ++ then Outgoing ofs ++ else Domainstate (ofs + size_domainstate_args) ++let not_supported _ = fatal_error "Proc.loc_results: cannot call" ++ ++let max_arguments_for_tailcalls = 13 (* in regs *) + 64 (* in domain state *) ++ ++(* OCaml calling convention: ++ first integer args in a0 .. a7, s2 .. s9 ++ first float args in fa0 .. fa7, fs2 .. fs9 ++ remaining args in domain state area, then on stack. ++ Return values in a0 .. a7, s2 .. s9 or fa0 .. fa7, fs2 .. fs9. *) ++ ++let loc_arguments arg = ++ calling_conventions 0 12 110 121 outgoing (- size_domainstate_args) arg ++ ++let loc_parameters arg = ++ let (loc, _ofs) = ++ calling_conventions 0 12 110 121 incoming (- size_domainstate_args) arg ++ in ++ loc ++ ++let loc_results res = ++ let (loc, _ofs) = ++ calling_conventions 0 12 110 121 not_supported 0 res ++ in ++ loc ++ ++(* C calling convention: ++ first integer args in a0 .. a7 ++ first float args in fa0 .. fa7 ++ remaining args on stack. ++ A FP argument can be passed in an integer register if all FP registers ++ are exhausted but integer registers remain. ++ Return values in a0 .. a1 or fa0 .. fa1. *) ++ ++let external_calling_conventions ++ first_int last_int first_float last_float make_stack arg = ++ let loc = Array.make (Array.length arg) [| Reg.dummy |] in ++ let int = ref first_int in ++ let float = ref first_float in ++ let ofs = ref 0 in ++ for i = 0 to Array.length arg - 1 do ++ match arg.(i) with ++ | Val | Int | Addr as ty -> ++ if !int <= last_int then begin ++ loc.(i) <- [| phys_reg !int |]; ++ incr int ++ end else begin ++ loc.(i) <- [| stack_slot (make_stack !ofs) ty |]; ++ ofs := !ofs + size_int ++ end ++ | Float -> ++ if !float <= last_float then begin ++ loc.(i) <- [| phys_reg !float |]; ++ incr float ++ end else if !int <= last_int then begin ++ loc.(i) <- [| phys_reg !int |]; ++ incr int ++ end else begin ++ loc.(i) <- [| stack_slot (make_stack !ofs) Float |]; ++ ofs := !ofs + size_float ++ end ++ done; ++ (loc, Misc.align !ofs 16) (* Keep stack 16-aligned. *) ++ ++let loc_external_arguments ty_args = ++ let arg = Cmm.machtype_of_exttype_list ty_args in ++ external_calling_conventions 0 7 110 117 outgoing arg ++ ++let loc_external_results res = ++ let (loc, _ofs) = calling_conventions 0 1 110 111 not_supported 0 res ++ in loc ++ ++(* Exceptions are in a0 *) ++ ++let loc_exn_bucket = phys_reg 0 ++ ++(* Volatile registers: none *) ++ ++let regs_are_volatile _ = false ++ ++(* Registers destroyed by operations *) ++ ++let destroyed_at_c_call = ++ (* s0-s11 and fs0-fs11 are callee-save. However s2 needs to be in this ++ list since it is clobbered by caml_c_call itself. *) ++ Array.of_list(List.map phys_reg ++ [0; 1; 2; 3; 4; 5; 6; 7; 8; 13; 14; 15; 16; 17; 18; 19; ++ 100; 101; 102; 103; 104; 105; 106; 107; 110; 111; 112; 113; 114; 115; 116; ++ 117; 128; 129; 130; 131]) ++ ++let destroyed_at_alloc = ++ (* t0-t6 are used for PLT stubs *) ++ if !Clflags.dlcode then Array.map phys_reg [|13; 14; 15; 16; 17; 18; 19; 20; 21; 22|] ++ else [| |] ++ ++let destroyed_at_oper = function ++ | Iop(Icall_ind | Icall_imm _ | Iextcall{alloc = true; _}) -> all_phys_regs ++ | Iop(Iextcall{alloc = false; _}) -> destroyed_at_c_call ++ | Iop(Ialloc _) | Iop(Ipoll _) -> destroyed_at_alloc ++ | Iop(Istore(Single, _, _)) -> [| phys_reg 100 |] ++ | Iop(Ifloatofint | Iintoffloat) -> [| phys_reg 100 |] ++ | Iswitch _ -> [| phys_reg 21 |] (* t0 *) ++ | _ -> [||] ++ ++let destroyed_at_raise = all_phys_regs ++ ++let destroyed_at_reloadretaddr = [| |] ++ ++(* Maximal register pressure *) ++ ++let safe_register_pressure = function ++ | Iextcall _ -> 5 ++ | _ -> 21 ++ ++let max_register_pressure = function ++ | Iextcall _ -> [| 5; 8 |] ++ | _ -> [| 21; 30 |] ++ ++(* Layout of the stack *) ++ ++let frame_required fd = ++ fd.fun_contains_calls ++ || fd.fun_num_stack_slots.(0) > 0 ++ || fd.fun_num_stack_slots.(1) > 0 ++ ++let prologue_required fd = ++ frame_required fd ++ ++let int_dwarf_reg_numbers = ++ [| 10; 11; 12; 13; 14; 15; 16; 17; ++ 18; 19; 20; 21; 22; 23; 24; 25; ++ 7; 28; 29; 30; 31; ++ 8; ++ 5; 6; ++ 9; 26; 27; ++ |] ++ ++let float_dwarf_reg_numbers = ++ [| 32; 33; 34; 35; 36; 37; 38; 39; ++ 40; 41; ++ 42; 43; 44; 45; 46; 47; 48; 49; ++ 50; 51; 52; 53; 54; 55; 56; 57; ++ 58; 59; ++ 60; 61; 62; 63; ++ |] ++ ++let dwarf_register_numbers ~reg_class = ++ match reg_class with ++ | 0 -> int_dwarf_reg_numbers ++ | 1 -> float_dwarf_reg_numbers ++ | _ -> Misc.fatal_errorf "Bad register class %d" reg_class ++ ++let stack_ptr_dwarf_register_number = 2 ++ ++(* Calling the assembler *) ++ ++let assemble_file infile outfile = ++ Ccomp.command ++ (Config.asm ^ " -o " ^ Filename.quote outfile ^ " " ^ Filename.quote infile) ++ ++let init () = () +diff --git a/asmcomp/loongarch64/reload.ml b/asmcomp/loongarch64/reload.ml +new file mode 100644 +index 0000000..179f1b7 +--- /dev/null ++++ b/asmcomp/loongarch64/reload.ml +@@ -0,0 +1,18 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* Reloading for the loongarch *) ++ ++let fundecl f = ++ (new Reloadgen.reload_generic)#fundecl f +diff --git a/asmcomp/loongarch64/scheduling.ml b/asmcomp/loongarch64/scheduling.ml +new file mode 100644 +index 0000000..0f05416 +--- /dev/null ++++ b/asmcomp/loongarch64/scheduling.ml +@@ -0,0 +1,21 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* Instruction scheduling for the loongarch *) ++ ++open! Schedgen (* to create a dependency *) ++ ++(* Scheduling is turned off. *) ++ ++let fundecl f = f +diff --git a/asmcomp/loongarch64/selection.ml b/asmcomp/loongarch64/selection.ml +new file mode 100644 +index 0000000..cb6ffc5 +--- /dev/null ++++ b/asmcomp/loongarch64/selection.ml +@@ -0,0 +1,64 @@ ++ ++(**************************************************************************) ++(* *) ++(* OCaml *) ++(* *) ++(* yala *) ++(* *) ++(* Copyright © 2008-2023 LOONGSON *) ++(* *) ++(* All rights reserved. This file is distributed under the terms of *) ++(* the GNU Lesser General Public License version 2.1, with the *) ++(* special exception on linking described in the file LICENSE. *) ++(* *) ++(**************************************************************************) ++(* Instruction selection for the loongarch processor *) ++ ++open Cmm ++open Arch ++open Mach ++ ++(* Instruction selection *) ++ ++class selector = object ++ ++inherit Selectgen.selector_generic as super ++ ++(* loongarch does not support immediate operands for comparison operators *) ++method is_immediate_test _cmp _n = false ++ ++method! is_immediate op n = ++ match op with ++ | Iadd | Iand | Ior | Ixor -> is_immediate n ++ (* sub immediate is turned into add immediate opposite *) ++ | Isub -> is_immediate (-n) ++ | _ -> super#is_immediate op n ++ ++method select_addressing _ = function ++ | Cop(Cadda, [arg; Cconst_int (n, _)], _) when is_immediate n -> ++ (Iindexed n, arg) ++ | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int (n, _)], _)], dbg) ++ when is_immediate n -> ++ (Iindexed n, Cop(Caddi, [arg1; arg2], dbg)) ++ | arg -> ++ (Iindexed 0, arg) ++ ++method! select_operation op args dbg = ++ match (op, args) with ++ (* Recognize (neg-)mult-add and (neg-)mult-sub instructions *) ++ | (Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3]) ++ | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2], _)]) -> ++ (Ispecific (Imultaddf false), [arg1; arg2; arg3]) ++ | (Csubf, [Cop(Cmulf, [arg1; arg2], _); arg3]) -> ++ (Ispecific (Imultsubf false), [arg1; arg2; arg3]) ++ | (Cnegf, [Cop(Csubf, [Cop(Cmulf, [arg1; arg2], _); arg3], _)]) -> ++ (Ispecific (Imultsubf true), [arg1; arg2; arg3]) ++ | (Cnegf, [Cop(Caddf, [Cop(Cmulf, [arg1; arg2], _); arg3], _)]) -> ++ (Ispecific (Imultaddf true), [arg1; arg2; arg3]) ++ | _ -> ++ super#select_operation op args dbg ++ ++end ++ ++let fundecl ~future_funcnames f = ++ (new selector)#emit_fundecl ~future_funcnames f +diff --git a/build-aux/config.guess b/build-aux/config.guess +index e94095c..980b020 100755 +--- a/build-aux/config.guess ++++ b/build-aux/config.guess +@@ -1,12 +1,14 @@ + #! /bin/sh + # Attempt to guess a canonical system name. +-# Copyright 1992-2020 Free Software Foundation, Inc. ++# Copyright 1992-2022 Free Software Foundation, Inc. + +-timestamp='2020-07-12' ++# shellcheck disable=SC2006,SC2268 # see below for rationale ++ ++timestamp='2022-09-17' + + # This file is free software; you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by +-# the Free Software Foundation; either version 3 of the License, or ++# the Free Software Foundation, either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, but +@@ -27,11 +29,19 @@ timestamp='2020-07-12' + # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. + # + # You can get the latest version of this script from: +-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess ++# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess + # + # Please send patches to . + + ++# The "shellcheck disable" line above the timestamp inhibits complaints ++# about features and limitations of the classic Bourne shell that were ++# superseded or lifted in POSIX. However, this script identifies a wide ++# variety of pre-POSIX systems that do not have POSIX shells at all, and ++# even some reasonably current systems (Solaris 10 as case-in-point) still ++# have a pre-POSIX /bin/sh. ++ ++ + me=`echo "$0" | sed -e 's,.*/,,'` + + usage="\ +@@ -50,7 +60,7 @@ version="\ + GNU config.guess ($timestamp) + + Originally written by Per Bothner. +-Copyright 1992-2020 Free Software Foundation, Inc. ++Copyright 1992-2022 Free Software Foundation, Inc. + + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +@@ -84,6 +94,9 @@ if test $# != 0; then + exit 1 + fi + ++# Just in case it came from the environment. ++GUESS= ++ + # CC_FOR_BUILD -- compiler used by this script. Note that the use of a + # compiler to aid in system detection is discouraged as it requires + # temporary files to be created and, as you can see below, it is a +@@ -102,7 +115,7 @@ set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" +- # shellcheck disable=SC2039 ++ # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || +@@ -112,7 +125,7 @@ set_cc_for_build() { + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then +- CC_FOR_BUILD="$driver" ++ CC_FOR_BUILD=$driver + break + fi + done +@@ -133,14 +146,12 @@ fi + + UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown + UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown ++UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown + UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +-case "$UNAME_SYSTEM" in ++case $UNAME_SYSTEM in + Linux|GNU|GNU/*) +- # If the system lacks a compiler, then just pick glibc. +- # We could probably try harder. +- LIBC=gnu ++ LIBC=unknown + + set_cc_for_build + cat <<-EOF > "$dummy.c" +@@ -149,24 +160,37 @@ Linux|GNU|GNU/*) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc +- #else ++ #elif defined(__GLIBC__) + LIBC=gnu ++ #else ++ #include ++ /* First heuristic to detect musl libc. */ ++ #ifdef __DEFINED_va_list ++ LIBC=musl ++ #endif + #endif + EOF +- eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" ++ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ++ eval "$cc_set_libc" + +- # If ldd exists, use it to detect musl libc. +- if command -v ldd >/dev/null && \ +- ldd --version 2>&1 | grep -q ^musl +- then +- LIBC=musl ++ # Second heuristic to detect musl libc. ++ if [ "$LIBC" = unknown ] && ++ command -v ldd >/dev/null && ++ ldd --version 2>&1 | grep -q ^musl; then ++ LIBC=musl ++ fi ++ ++ # If the system lacks a compiler, then just pick glibc. ++ # We could probably try harder. ++ if [ "$LIBC" = unknown ]; then ++ LIBC=gnu + fi + ;; + esac + + # Note: order is significant - the case branches are not exclusive. + +-case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in ++case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, +@@ -178,12 +202,12 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". +- sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ +- "/sbin/$sysctl" 2>/dev/null || \ +- "/usr/sbin/$sysctl" 2>/dev/null || \ ++ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ ++ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + echo unknown)` +- case "$UNAME_MACHINE_ARCH" in ++ case $UNAME_MACHINE_ARCH in ++ aarch64eb) machine=aarch64_be-unknown ;; + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; +@@ -192,13 +216,13 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` +- machine="${arch}${endian}"-unknown ++ machine=${arch}${endian}-unknown + ;; +- *) machine="$UNAME_MACHINE_ARCH"-unknown ;; ++ *) machine=$UNAME_MACHINE_ARCH-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. +- case "$UNAME_MACHINE_ARCH" in ++ case $UNAME_MACHINE_ARCH in + earm*) + os=netbsdelf + ;; +@@ -219,7 +243,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + ;; + esac + # Determine ABI tags. +- case "$UNAME_MACHINE_ARCH" in ++ case $UNAME_MACHINE_ARCH in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` +@@ -230,7 +254,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. +- case "$UNAME_VERSION" in ++ case $UNAME_VERSION in + Debian*) + release='-gnu' + ;; +@@ -241,51 +265,57 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. +- echo "$machine-${os}${release}${abi-}" +- exit ;; ++ GUESS=$machine-${os}${release}${abi-} ++ ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` +- echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ++ ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` +- echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ++ ;; ++ *:SecBSD:*:*) ++ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` ++ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ++ ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` +- echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ++ ;; + *:MidnightBSD:*:*) +- echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ++ ;; + *:ekkoBSD:*:*) +- echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ++ ;; + *:SolidBSD:*:*) +- echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ++ ;; + *:OS108:*:*) +- echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ++ ;; + macppc:MirBSD:*:*) +- echo powerpc-unknown-mirbsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ++ ;; + *:MirBSD:*:*) +- echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ++ ;; + *:Sortix:*:*) +- echo "$UNAME_MACHINE"-unknown-sortix +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-sortix ++ ;; + *:Twizzler:*:*) +- echo "$UNAME_MACHINE"-unknown-twizzler +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-twizzler ++ ;; + *:Redox:*:*) +- echo "$UNAME_MACHINE"-unknown-redox +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-redox ++ ;; + mips:OSF1:*.*) +- echo mips-dec-osf1 +- exit ;; ++ GUESS=mips-dec-osf1 ++ ;; + alpha:OSF1:*:*) ++ # Reset EXIT trap before exiting to avoid spurious non-zero exit code. ++ trap '' 0 + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` +@@ -299,7 +329,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` +- case "$ALPHA_CPU_TYPE" in ++ case $ALPHA_CPU_TYPE in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") +@@ -336,117 +366,121 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. +- echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" +- # Reset EXIT trap before exiting to avoid spurious non-zero exit code. +- exitcode=$? +- trap '' 0 +- exit $exitcode ;; ++ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` ++ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ++ ;; + Amiga*:UNIX_System_V:4.0:*) +- echo m68k-unknown-sysv4 +- exit ;; ++ GUESS=m68k-unknown-sysv4 ++ ;; + *:[Aa]miga[Oo][Ss]:*:*) +- echo "$UNAME_MACHINE"-unknown-amigaos +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-amigaos ++ ;; + *:[Mm]orph[Oo][Ss]:*:*) +- echo "$UNAME_MACHINE"-unknown-morphos +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-morphos ++ ;; + *:OS/390:*:*) +- echo i370-ibm-openedition +- exit ;; ++ GUESS=i370-ibm-openedition ++ ;; + *:z/VM:*:*) +- echo s390-ibm-zvmoe +- exit ;; ++ GUESS=s390-ibm-zvmoe ++ ;; + *:OS400:*:*) +- echo powerpc-ibm-os400 +- exit ;; ++ GUESS=powerpc-ibm-os400 ++ ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) +- echo arm-acorn-riscix"$UNAME_RELEASE" +- exit ;; ++ GUESS=arm-acorn-riscix$UNAME_RELEASE ++ ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) +- echo arm-unknown-riscos +- exit ;; ++ GUESS=arm-unknown-riscos ++ ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) +- echo hppa1.1-hitachi-hiuxmpp +- exit ;; ++ GUESS=hppa1.1-hitachi-hiuxmpp ++ ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. +- if test "`(/bin/universe) 2>/dev/null`" = att ; then +- echo pyramid-pyramid-sysv3 +- else +- echo pyramid-pyramid-bsd +- fi +- exit ;; ++ case `(/bin/universe) 2>/dev/null` in ++ att) GUESS=pyramid-pyramid-sysv3 ;; ++ *) GUESS=pyramid-pyramid-bsd ;; ++ esac ++ ;; + NILE*:*:*:dcosx) +- echo pyramid-pyramid-svr4 +- exit ;; ++ GUESS=pyramid-pyramid-svr4 ++ ;; + DRS?6000:unix:4.0:6*) +- echo sparc-icl-nx6 +- exit ;; ++ GUESS=sparc-icl-nx6 ++ ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in +- sparc) echo sparc-icl-nx7; exit ;; +- esac ;; ++ sparc) GUESS=sparc-icl-nx7 ;; ++ esac ++ ;; + s390x:SunOS:*:*) +- echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ++ ;; + sun4H:SunOS:5.*:*) +- echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=sparc-hal-solaris2$SUN_REL ++ ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) +- echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=sparc-sun-solaris2$SUN_REL ++ ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) +- echo i386-pc-auroraux"$UNAME_RELEASE" +- exit ;; ++ GUESS=i386-pc-auroraux$UNAME_RELEASE ++ ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. +- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then ++ if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ +- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ ++ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi +- echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ++ ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. +- echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=sparc-sun-solaris3$SUN_REL ++ ;; + sun4*:SunOS:*:*) +- case "`/usr/bin/arch -k`" in ++ case `/usr/bin/arch -k` in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. +- echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` ++ GUESS=sparc-sun-sunos$SUN_REL ++ ;; + sun3*:SunOS:*:*) +- echo m68k-sun-sunos"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-sun-sunos$UNAME_RELEASE ++ ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 +- case "`/bin/arch`" in ++ case `/bin/arch` in + sun3) +- echo m68k-sun-sunos"$UNAME_RELEASE" ++ GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; + sun4) +- echo sparc-sun-sunos"$UNAME_RELEASE" ++ GUESS=sparc-sun-sunos$UNAME_RELEASE + ;; + esac +- exit ;; ++ ;; + aushp:SunOS:*:*) +- echo sparc-auspex-sunos"$UNAME_RELEASE" +- exit ;; ++ GUESS=sparc-auspex-sunos$UNAME_RELEASE ++ ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor +@@ -456,41 +490,41 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) +- echo m68k-atari-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-atari-mint$UNAME_RELEASE ++ ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) +- echo m68k-atari-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-atari-mint$UNAME_RELEASE ++ ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) +- echo m68k-atari-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-atari-mint$UNAME_RELEASE ++ ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) +- echo m68k-milan-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-milan-mint$UNAME_RELEASE ++ ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) +- echo m68k-hades-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-hades-mint$UNAME_RELEASE ++ ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) +- echo m68k-unknown-mint"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-unknown-mint$UNAME_RELEASE ++ ;; + m68k:machten:*:*) +- echo m68k-apple-machten"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-apple-machten$UNAME_RELEASE ++ ;; + powerpc:machten:*:*) +- echo powerpc-apple-machten"$UNAME_RELEASE" +- exit ;; ++ GUESS=powerpc-apple-machten$UNAME_RELEASE ++ ;; + RISC*:Mach:*:*) +- echo mips-dec-mach_bsd4.3 +- exit ;; ++ GUESS=mips-dec-mach_bsd4.3 ++ ;; + RISC*:ULTRIX:*:*) +- echo mips-dec-ultrix"$UNAME_RELEASE" +- exit ;; ++ GUESS=mips-dec-ultrix$UNAME_RELEASE ++ ;; + VAX*:ULTRIX*:*:*) +- echo vax-dec-ultrix"$UNAME_RELEASE" +- exit ;; ++ GUESS=vax-dec-ultrix$UNAME_RELEASE ++ ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) +- echo clipper-intergraph-clix"$UNAME_RELEASE" +- exit ;; ++ GUESS=clipper-intergraph-clix$UNAME_RELEASE ++ ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +@@ -518,75 +552,76 @@ EOF + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } +- echo mips-mips-riscos"$UNAME_RELEASE" +- exit ;; ++ GUESS=mips-mips-riscos$UNAME_RELEASE ++ ;; + Motorola:PowerMAX_OS:*:*) +- echo powerpc-motorola-powermax +- exit ;; ++ GUESS=powerpc-motorola-powermax ++ ;; + Motorola:*:4.3:PL8-*) +- echo powerpc-harris-powermax +- exit ;; ++ GUESS=powerpc-harris-powermax ++ ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) +- echo powerpc-harris-powermax +- exit ;; ++ GUESS=powerpc-harris-powermax ++ ;; + Night_Hawk:Power_UNIX:*:*) +- echo powerpc-harris-powerunix +- exit ;; ++ GUESS=powerpc-harris-powerunix ++ ;; + m88k:CX/UX:7*:*) +- echo m88k-harris-cxux7 +- exit ;; ++ GUESS=m88k-harris-cxux7 ++ ;; + m88k:*:4*:R4*) +- echo m88k-motorola-sysv4 +- exit ;; ++ GUESS=m88k-motorola-sysv4 ++ ;; + m88k:*:3*:R3*) +- echo m88k-motorola-sysv3 +- exit ;; ++ GUESS=m88k-motorola-sysv3 ++ ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` +- if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] ++ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 + then +- if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ +- [ "$TARGET_BINARY_INTERFACE"x = x ] ++ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ ++ test "$TARGET_BINARY_INTERFACE"x = x + then +- echo m88k-dg-dgux"$UNAME_RELEASE" ++ GUESS=m88k-dg-dgux$UNAME_RELEASE + else +- echo m88k-dg-dguxbcs"$UNAME_RELEASE" ++ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE + fi + else +- echo i586-dg-dgux"$UNAME_RELEASE" ++ GUESS=i586-dg-dgux$UNAME_RELEASE + fi +- exit ;; ++ ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) +- echo m88k-dolphin-sysv3 +- exit ;; ++ GUESS=m88k-dolphin-sysv3 ++ ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 +- echo m88k-motorola-sysv3 +- exit ;; ++ GUESS=m88k-motorola-sysv3 ++ ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) +- echo m88k-tektronix-sysv3 +- exit ;; ++ GUESS=m88k-tektronix-sysv3 ++ ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) +- echo m68k-tektronix-bsd +- exit ;; ++ GUESS=m68k-tektronix-bsd ++ ;; + *:IRIX*:*:*) +- echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" +- exit ;; ++ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` ++ GUESS=mips-sgi-irix$IRIX_REL ++ ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. +- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id +- exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' ++ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ++ ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) +- echo i386-ibm-aix +- exit ;; ++ GUESS=i386-ibm-aix ++ ;; + ia64:AIX:*:*) +- if [ -x /usr/bin/oslevel ] ; then ++ if test -x /usr/bin/oslevel ; then + IBM_REV=`/usr/bin/oslevel` + else +- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" ++ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi +- echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" +- exit ;; ++ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ++ ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build +@@ -603,16 +638,16 @@ EOF + EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then +- echo "$SYSTEM_NAME" ++ GUESS=$SYSTEM_NAME + else +- echo rs6000-ibm-aix3.2.5 ++ GUESS=rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then +- echo rs6000-ibm-aix3.2.4 ++ GUESS=rs6000-ibm-aix3.2.4 + else +- echo rs6000-ibm-aix3.2 ++ GUESS=rs6000-ibm-aix3.2 + fi +- exit ;; ++ ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then +@@ -620,56 +655,56 @@ EOF + else + IBM_ARCH=powerpc + fi +- if [ -x /usr/bin/lslpp ] ; then +- IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | ++ if test -x /usr/bin/lslpp ; then ++ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else +- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" ++ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi +- echo "$IBM_ARCH"-ibm-aix"$IBM_REV" +- exit ;; ++ GUESS=$IBM_ARCH-ibm-aix$IBM_REV ++ ;; + *:AIX:*:*) +- echo rs6000-ibm-aix +- exit ;; ++ GUESS=rs6000-ibm-aix ++ ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) +- echo romp-ibm-bsd4.4 +- exit ;; ++ GUESS=romp-ibm-bsd4.4 ++ ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and +- echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to +- exit ;; # report: romp-ibm BSD 4.3 ++ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ++ ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) +- echo rs6000-bull-bosx +- exit ;; ++ GUESS=rs6000-bull-bosx ++ ;; + DPX/2?00:B.O.S.:*:*) +- echo m68k-bull-sysv3 +- exit ;; ++ GUESS=m68k-bull-sysv3 ++ ;; + 9000/[34]??:4.3bsd:1.*:*) +- echo m68k-hp-bsd +- exit ;; ++ GUESS=m68k-hp-bsd ++ ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) +- echo m68k-hp-bsd4.4 +- exit ;; ++ GUESS=m68k-hp-bsd4.4 ++ ;; + 9000/[34678]??:HP-UX:*:*) +- HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` +- case "$UNAME_MACHINE" in ++ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` ++ case $UNAME_MACHINE in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) +- if [ -x /usr/bin/getconf ]; then ++ if test -x /usr/bin/getconf; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` +- case "$sc_cpu_version" in ++ case $sc_cpu_version in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 +- case "$sc_kernel_bits" in ++ case $sc_kernel_bits in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi +- if [ "$HP_ARCH" = "" ]; then ++ if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + +@@ -708,7 +743,7 @@ EOF + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac +- if [ "$HP_ARCH" = hppa2.0w ] ++ if test "$HP_ARCH" = hppa2.0w + then + set_cc_for_build + +@@ -729,12 +764,12 @@ EOF + HP_ARCH=hppa64 + fi + fi +- echo "$HP_ARCH"-hp-hpux"$HPUX_REV" +- exit ;; ++ GUESS=$HP_ARCH-hp-hpux$HPUX_REV ++ ;; + ia64:HP-UX:*:*) +- HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` +- echo ia64-hp-hpux"$HPUX_REV" +- exit ;; ++ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` ++ GUESS=ia64-hp-hpux$HPUX_REV ++ ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +@@ -764,36 +799,36 @@ EOF + EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } +- echo unknown-hitachi-hiuxwe2 +- exit ;; ++ GUESS=unknown-hitachi-hiuxwe2 ++ ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) +- echo hppa1.1-hp-bsd +- exit ;; ++ GUESS=hppa1.1-hp-bsd ++ ;; + 9000/8??:4.3bsd:*:*) +- echo hppa1.0-hp-bsd +- exit ;; ++ GUESS=hppa1.0-hp-bsd ++ ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) +- echo hppa1.0-hp-mpeix +- exit ;; ++ GUESS=hppa1.0-hp-mpeix ++ ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) +- echo hppa1.1-hp-osf +- exit ;; ++ GUESS=hppa1.1-hp-osf ++ ;; + hp8??:OSF1:*:*) +- echo hppa1.0-hp-osf +- exit ;; ++ GUESS=hppa1.0-hp-osf ++ ;; + i*86:OSF1:*:*) +- if [ -x /usr/sbin/sysversion ] ; then +- echo "$UNAME_MACHINE"-unknown-osf1mk ++ if test -x /usr/sbin/sysversion ; then ++ GUESS=$UNAME_MACHINE-unknown-osf1mk + else +- echo "$UNAME_MACHINE"-unknown-osf1 ++ GUESS=$UNAME_MACHINE-unknown-osf1 + fi +- exit ;; ++ ;; + parisc*:Lites*:*:*) +- echo hppa1.1-hp-lites +- exit ;; ++ GUESS=hppa1.1-hp-lites ++ ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) +- echo c1-convex-bsd +- exit ;; ++ GUESS=c1-convex-bsd ++ ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd +@@ -801,17 +836,18 @@ EOF + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) +- echo c34-convex-bsd +- exit ;; ++ GUESS=c34-convex-bsd ++ ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) +- echo c38-convex-bsd +- exit ;; ++ GUESS=c38-convex-bsd ++ ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) +- echo c4-convex-bsd +- exit ;; ++ GUESS=c4-convex-bsd ++ ;; + CRAY*Y-MP:*:*:*) +- echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' +- exit ;; ++ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` ++ GUESS=ymp-cray-unicos$CRAY_REL ++ ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ +@@ -819,112 +855,133 @@ EOF + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) +- echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' +- exit ;; ++ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` ++ GUESS=t90-cray-unicos$CRAY_REL ++ ;; + CRAY*T3E:*:*:*) +- echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' +- exit ;; ++ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` ++ GUESS=alphaev5-cray-unicosmk$CRAY_REL ++ ;; + CRAY*SV1:*:*:*) +- echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' +- exit ;; ++ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` ++ GUESS=sv1-cray-unicos$CRAY_REL ++ ;; + *:UNICOS/mp:*:*) +- echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' +- exit ;; ++ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` ++ GUESS=craynv-cray-unicosmp$CRAY_REL ++ ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` +- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" +- exit ;; ++ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ++ ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` +- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" +- exit ;; ++ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ++ ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) +- echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ++ ;; + sparc*:BSD/OS:*:*) +- echo sparc-unknown-bsdi"$UNAME_RELEASE" +- exit ;; ++ GUESS=sparc-unknown-bsdi$UNAME_RELEASE ++ ;; + *:BSD/OS:*:*) +- echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ++ ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then +- echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi ++ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` ++ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else +- echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf ++ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` ++ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi +- exit ;; ++ ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` +- case "$UNAME_PROCESSOR" in ++ case $UNAME_PROCESSOR in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac +- echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" +- exit ;; ++ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` ++ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ++ ;; + i*:CYGWIN*:*) +- echo "$UNAME_MACHINE"-pc-cygwin +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-cygwin ++ ;; + *:MINGW64*:*) +- echo "$UNAME_MACHINE"-pc-mingw64 +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-mingw64 ++ ;; + *:MINGW*:*) +- echo "$UNAME_MACHINE"-pc-mingw32 +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-mingw32 ++ ;; + *:MSYS*:*) +- echo "$UNAME_MACHINE"-pc-msys +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-msys ++ ;; + i*:PW*:*) +- echo "$UNAME_MACHINE"-pc-pw32 +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-pw32 ++ ;; ++ *:SerenityOS:*:*) ++ GUESS=$UNAME_MACHINE-pc-serenity ++ ;; + *:Interix*:*) +- case "$UNAME_MACHINE" in ++ case $UNAME_MACHINE in + x86) +- echo i586-pc-interix"$UNAME_RELEASE" +- exit ;; ++ GUESS=i586-pc-interix$UNAME_RELEASE ++ ;; + authenticamd | genuineintel | EM64T) +- echo x86_64-unknown-interix"$UNAME_RELEASE" +- exit ;; ++ GUESS=x86_64-unknown-interix$UNAME_RELEASE ++ ;; + IA64) +- echo ia64-unknown-interix"$UNAME_RELEASE" +- exit ;; ++ GUESS=ia64-unknown-interix$UNAME_RELEASE ++ ;; + esac ;; + i*:UWIN*:*) +- echo "$UNAME_MACHINE"-pc-uwin +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-uwin ++ ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) +- echo x86_64-pc-cygwin +- exit ;; ++ GUESS=x86_64-pc-cygwin ++ ;; + prep*:SunOS:5.*:*) +- echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" +- exit ;; ++ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` ++ GUESS=powerpcle-unknown-solaris2$SUN_REL ++ ;; + *:GNU:*:*) + # the GNU system +- echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" +- exit ;; ++ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` ++ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` ++ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ++ ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland +- echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" +- exit ;; ++ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` ++ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` ++ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ++ ;; ++ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) ++ GUESS="$UNAME_MACHINE-pc-managarm-mlibc" ++ ;; ++ *:[Mm]anagarm:*:*) ++ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" ++ ;; + *:Minix:*:*) +- echo "$UNAME_MACHINE"-unknown-minix +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-minix ++ ;; + aarch64:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in + EV5) UNAME_MACHINE=alphaev5 ;; +@@ -937,60 +994,63 @@ EOF + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; +- arc:Linux:*:* | arceb:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; ++ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi ++ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi + else +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf ++ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf + fi + fi +- exit ;; ++ ;; + avr32*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + cris:Linux:*:*) +- echo "$UNAME_MACHINE"-axis-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-axis-linux-$LIBC ++ ;; + crisv32:Linux:*:*) +- echo "$UNAME_MACHINE"-axis-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-axis-linux-$LIBC ++ ;; + e2k:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + frv:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + hexagon:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + i*86:Linux:*:*) +- echo "$UNAME_MACHINE"-pc-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-linux-$LIBC ++ ;; + ia64:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + k1om:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; ++ loongarch32:Linux:*:* | loongarch64:Linux:*:*) ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + m32r*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + m68*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 +@@ -1035,123 +1095,135 @@ EOF + #endif + #endif + EOF +- eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" ++ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` ++ eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + openrisc*:Linux:*:*) +- echo or1k-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=or1k-unknown-linux-$LIBC ++ ;; + or32:Linux:*:* | or1k*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + padre:Linux:*:*) +- echo sparc-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=sparc-unknown-linux-$LIBC ++ ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) +- echo hppa64-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=hppa64-unknown-linux-$LIBC ++ ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in +- PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; +- PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; +- *) echo hppa-unknown-linux-"$LIBC" ;; ++ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; ++ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; ++ *) GUESS=hppa-unknown-linux-$LIBC ;; + esac +- exit ;; ++ ;; + ppc64:Linux:*:*) +- echo powerpc64-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=powerpc64-unknown-linux-$LIBC ++ ;; + ppc:Linux:*:*) +- echo powerpc-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=powerpc-unknown-linux-$LIBC ++ ;; + ppc64le:Linux:*:*) +- echo powerpc64le-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=powerpc64le-unknown-linux-$LIBC ++ ;; + ppcle:Linux:*:*) +- echo powerpcle-unknown-linux-"$LIBC" +- exit ;; +- riscv32:Linux:*:* | riscv64:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=powerpcle-unknown-linux-$LIBC ++ ;; ++ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + s390:Linux:*:* | s390x:Linux:*:*) +- echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ++ ;; + sh64*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + sh*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + sparc:Linux:*:* | sparc64:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + tile*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + vax:Linux:*:*) +- echo "$UNAME_MACHINE"-dec-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-dec-linux-$LIBC ++ ;; + x86_64:Linux:*:*) + set_cc_for_build ++ CPU=$UNAME_MACHINE + LIBCABI=$LIBC +- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then +- if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ +- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ +- grep IS_X32 >/dev/null +- then +- LIBCABI="$LIBC"x32 +- fi ++ if test "$CC_FOR_BUILD" != no_compiler_found; then ++ ABI=64 ++ sed 's/^ //' << EOF > "$dummy.c" ++ #ifdef __i386__ ++ ABI=x86 ++ #else ++ #ifdef __ILP32__ ++ ABI=x32 ++ #endif ++ #endif ++EOF ++ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` ++ eval "$cc_set_abi" ++ case $ABI in ++ x86) CPU=i686 ;; ++ x32) LIBCABI=${LIBC}x32 ;; ++ esac + fi +- echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" +- exit ;; ++ GUESS=$CPU-pc-linux-$LIBCABI ++ ;; + xtensa*:Linux:*:*) +- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ++ ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. +- echo i386-sequent-sysv4 +- exit ;; ++ GUESS=i386-sequent-sysv4 ++ ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. +- echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ++ ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. +- echo "$UNAME_MACHINE"-pc-os2-emx +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-os2-emx ++ ;; + i*86:XTS-300:*:STOP) +- echo "$UNAME_MACHINE"-unknown-stop +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-stop ++ ;; + i*86:atheos:*:*) +- echo "$UNAME_MACHINE"-unknown-atheos +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-atheos ++ ;; + i*86:syllable:*:*) +- echo "$UNAME_MACHINE"-pc-syllable +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-syllable ++ ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) +- echo i386-unknown-lynxos"$UNAME_RELEASE" +- exit ;; ++ GUESS=i386-unknown-lynxos$UNAME_RELEASE ++ ;; + i*86:*DOS:*:*) +- echo "$UNAME_MACHINE"-pc-msdosdjgpp +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-msdosdjgpp ++ ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then +- echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" ++ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL + else +- echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" ++ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL + fi +- exit ;; ++ ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in +@@ -1159,12 +1231,12 @@ EOF + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac +- echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ++ ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 +@@ -1174,11 +1246,11 @@ EOF + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 +- echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" ++ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL + else +- echo "$UNAME_MACHINE"-pc-sysv32 ++ GUESS=$UNAME_MACHINE-pc-sysv32 + fi +- exit ;; ++ ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about +@@ -1186,31 +1258,31 @@ EOF + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. +- echo i586-pc-msdosdjgpp +- exit ;; ++ GUESS=i586-pc-msdosdjgpp ++ ;; + Intel:Mach:3*:*) +- echo i386-pc-mach3 +- exit ;; ++ GUESS=i386-pc-mach3 ++ ;; + paragon:*:*:*) +- echo i860-intel-osf1 +- exit ;; ++ GUESS=i860-intel-osf1 ++ ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then +- echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 ++ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. +- echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 ++ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 + fi +- exit ;; ++ ;; + mini*:CTIX:SYS*5:*) + # "miniframe" +- echo m68010-convergent-sysv +- exit ;; ++ GUESS=m68010-convergent-sysv ++ ;; + mc68k:UNIX:SYSTEM5:3.51m) +- echo m68k-convergent-sysv +- exit ;; ++ GUESS=m68k-convergent-sysv ++ ;; + M680?0:D-NIX:5.3:*) +- echo m68k-diab-dnix +- exit ;; ++ GUESS=m68k-diab-dnix ++ ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) +@@ -1235,116 +1307,119 @@ EOF + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) +- echo m68k-unknown-lynxos"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-unknown-lynxos$UNAME_RELEASE ++ ;; + mc68030:UNIX_System_V:4.*:*) +- echo m68k-atari-sysv4 +- exit ;; ++ GUESS=m68k-atari-sysv4 ++ ;; + TSUNAMI:LynxOS:2.*:*) +- echo sparc-unknown-lynxos"$UNAME_RELEASE" +- exit ;; ++ GUESS=sparc-unknown-lynxos$UNAME_RELEASE ++ ;; + rs6000:LynxOS:2.*:*) +- echo rs6000-unknown-lynxos"$UNAME_RELEASE" +- exit ;; ++ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ++ ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) +- echo powerpc-unknown-lynxos"$UNAME_RELEASE" +- exit ;; ++ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ++ ;; + SM[BE]S:UNIX_SV:*:*) +- echo mips-dde-sysv"$UNAME_RELEASE" +- exit ;; ++ GUESS=mips-dde-sysv$UNAME_RELEASE ++ ;; + RM*:ReliantUNIX-*:*:*) +- echo mips-sni-sysv4 +- exit ;; ++ GUESS=mips-sni-sysv4 ++ ;; + RM*:SINIX-*:*:*) +- echo mips-sni-sysv4 +- exit ;; ++ GUESS=mips-sni-sysv4 ++ ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` +- echo "$UNAME_MACHINE"-sni-sysv4 ++ GUESS=$UNAME_MACHINE-sni-sysv4 + else +- echo ns32k-sni-sysv ++ GUESS=ns32k-sni-sysv + fi +- exit ;; ++ ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says +- echo i586-unisys-sysv4 +- exit ;; ++ GUESS=i586-unisys-sysv4 ++ ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm +- echo hppa1.1-stratus-sysv4 +- exit ;; ++ GUESS=hppa1.1-stratus-sysv4 ++ ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. +- echo i860-stratus-sysv4 +- exit ;; ++ GUESS=i860-stratus-sysv4 ++ ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. +- echo "$UNAME_MACHINE"-stratus-vos +- exit ;; ++ GUESS=$UNAME_MACHINE-stratus-vos ++ ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. +- echo hppa1.1-stratus-vos +- exit ;; ++ GUESS=hppa1.1-stratus-vos ++ ;; + mc68*:A/UX:*:*) +- echo m68k-apple-aux"$UNAME_RELEASE" +- exit ;; ++ GUESS=m68k-apple-aux$UNAME_RELEASE ++ ;; + news*:NEWS-OS:6*:*) +- echo mips-sony-newsos6 +- exit ;; ++ GUESS=mips-sony-newsos6 ++ ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) +- if [ -d /usr/nec ]; then +- echo mips-nec-sysv"$UNAME_RELEASE" ++ if test -d /usr/nec; then ++ GUESS=mips-nec-sysv$UNAME_RELEASE + else +- echo mips-unknown-sysv"$UNAME_RELEASE" ++ GUESS=mips-unknown-sysv$UNAME_RELEASE + fi +- exit ;; ++ ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. +- echo powerpc-be-beos +- exit ;; ++ GUESS=powerpc-be-beos ++ ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. +- echo powerpc-apple-beos +- exit ;; ++ GUESS=powerpc-apple-beos ++ ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. +- echo i586-pc-beos +- exit ;; ++ GUESS=i586-pc-beos ++ ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. +- echo i586-pc-haiku +- exit ;; +- x86_64:Haiku:*:*) +- echo x86_64-unknown-haiku +- exit ;; ++ GUESS=i586-pc-haiku ++ ;; ++ ppc:Haiku:*:*) # Haiku running on Apple PowerPC ++ GUESS=powerpc-apple-haiku ++ ;; ++ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) ++ GUESS=$UNAME_MACHINE-unknown-haiku ++ ;; + SX-4:SUPER-UX:*:*) +- echo sx4-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx4-nec-superux$UNAME_RELEASE ++ ;; + SX-5:SUPER-UX:*:*) +- echo sx5-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx5-nec-superux$UNAME_RELEASE ++ ;; + SX-6:SUPER-UX:*:*) +- echo sx6-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx6-nec-superux$UNAME_RELEASE ++ ;; + SX-7:SUPER-UX:*:*) +- echo sx7-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx7-nec-superux$UNAME_RELEASE ++ ;; + SX-8:SUPER-UX:*:*) +- echo sx8-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx8-nec-superux$UNAME_RELEASE ++ ;; + SX-8R:SUPER-UX:*:*) +- echo sx8r-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sx8r-nec-superux$UNAME_RELEASE ++ ;; + SX-ACE:SUPER-UX:*:*) +- echo sxace-nec-superux"$UNAME_RELEASE" +- exit ;; ++ GUESS=sxace-nec-superux$UNAME_RELEASE ++ ;; + Power*:Rhapsody:*:*) +- echo powerpc-apple-rhapsody"$UNAME_RELEASE" +- exit ;; ++ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ++ ;; + *:Rhapsody:*:*) +- echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ++ ;; + arm64:Darwin:*:*) +- echo aarch64-apple-darwin"$UNAME_RELEASE" +- exit ;; ++ GUESS=aarch64-apple-darwin$UNAME_RELEASE ++ ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in +@@ -1359,7 +1434,7 @@ EOF + else + set_cc_for_build + fi +- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then ++ if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null +@@ -1380,109 +1455,119 @@ EOF + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi +- echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ++ ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi +- echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ++ ;; + *:QNX:*:4*) +- echo i386-pc-qnx +- exit ;; ++ GUESS=i386-pc-qnx ++ ;; + NEO-*:NONSTOP_KERNEL:*:*) +- echo neo-tandem-nsk"$UNAME_RELEASE" +- exit ;; ++ GUESS=neo-tandem-nsk$UNAME_RELEASE ++ ;; + NSE-*:NONSTOP_KERNEL:*:*) +- echo nse-tandem-nsk"$UNAME_RELEASE" +- exit ;; ++ GUESS=nse-tandem-nsk$UNAME_RELEASE ++ ;; + NSR-*:NONSTOP_KERNEL:*:*) +- echo nsr-tandem-nsk"$UNAME_RELEASE" +- exit ;; ++ GUESS=nsr-tandem-nsk$UNAME_RELEASE ++ ;; + NSV-*:NONSTOP_KERNEL:*:*) +- echo nsv-tandem-nsk"$UNAME_RELEASE" +- exit ;; ++ GUESS=nsv-tandem-nsk$UNAME_RELEASE ++ ;; + NSX-*:NONSTOP_KERNEL:*:*) +- echo nsx-tandem-nsk"$UNAME_RELEASE" +- exit ;; ++ GUESS=nsx-tandem-nsk$UNAME_RELEASE ++ ;; + *:NonStop-UX:*:*) +- echo mips-compaq-nonstopux +- exit ;; ++ GUESS=mips-compaq-nonstopux ++ ;; + BS2000:POSIX*:*:*) +- echo bs2000-siemens-sysv +- exit ;; ++ GUESS=bs2000-siemens-sysv ++ ;; + DS/*:UNIX_System_V:*:*) +- echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ++ ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. +- # shellcheck disable=SC2154 +- if test "$cputype" = 386; then ++ if test "${cputype-}" = 386; then + UNAME_MACHINE=i386 +- else +- UNAME_MACHINE="$cputype" ++ elif test "x${cputype-}" != x; then ++ UNAME_MACHINE=$cputype + fi +- echo "$UNAME_MACHINE"-unknown-plan9 +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-plan9 ++ ;; + *:TOPS-10:*:*) +- echo pdp10-unknown-tops10 +- exit ;; ++ GUESS=pdp10-unknown-tops10 ++ ;; + *:TENEX:*:*) +- echo pdp10-unknown-tenex +- exit ;; ++ GUESS=pdp10-unknown-tenex ++ ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) +- echo pdp10-dec-tops20 +- exit ;; ++ GUESS=pdp10-dec-tops20 ++ ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) +- echo pdp10-xkl-tops20 +- exit ;; ++ GUESS=pdp10-xkl-tops20 ++ ;; + *:TOPS-20:*:*) +- echo pdp10-unknown-tops20 +- exit ;; ++ GUESS=pdp10-unknown-tops20 ++ ;; + *:ITS:*:*) +- echo pdp10-unknown-its +- exit ;; ++ GUESS=pdp10-unknown-its ++ ;; + SEI:*:*:SEIUX) +- echo mips-sei-seiux"$UNAME_RELEASE" +- exit ;; ++ GUESS=mips-sei-seiux$UNAME_RELEASE ++ ;; + *:DragonFly:*:*) +- echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" +- exit ;; ++ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` ++ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ++ ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` +- case "$UNAME_MACHINE" in +- A*) echo alpha-dec-vms ; exit ;; +- I*) echo ia64-dec-vms ; exit ;; +- V*) echo vax-dec-vms ; exit ;; ++ case $UNAME_MACHINE in ++ A*) GUESS=alpha-dec-vms ;; ++ I*) GUESS=ia64-dec-vms ;; ++ V*) GUESS=vax-dec-vms ;; + esac ;; + *:XENIX:*:SysV) +- echo i386-pc-xenix +- exit ;; ++ GUESS=i386-pc-xenix ++ ;; + i*86:skyos:*:*) +- echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" +- exit ;; ++ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` ++ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ++ ;; + i*86:rdos:*:*) +- echo "$UNAME_MACHINE"-pc-rdos +- exit ;; +- i*86:AROS:*:*) +- echo "$UNAME_MACHINE"-pc-aros +- exit ;; ++ GUESS=$UNAME_MACHINE-pc-rdos ++ ;; ++ i*86:Fiwix:*:*) ++ GUESS=$UNAME_MACHINE-pc-fiwix ++ ;; ++ *:AROS:*:*) ++ GUESS=$UNAME_MACHINE-unknown-aros ++ ;; + x86_64:VMkernel:*:*) +- echo "$UNAME_MACHINE"-unknown-esx +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-esx ++ ;; + amd64:Isilon\ OneFS:*:*) +- echo x86_64-unknown-onefs +- exit ;; ++ GUESS=x86_64-unknown-onefs ++ ;; + *:Unleashed:*:*) +- echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" +- exit ;; ++ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ++ ;; + esac + ++# Do we have a guess based on uname results? ++if test "x$GUESS" != x; then ++ echo "$GUESS" ++ exit ++fi ++ + # No uname command or uname output not recognized. + set_cc_for_build + cat > "$dummy.c" </dev/null && SYSTEM_NAME=`$dummy` && ++$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + + # Apollos put the system type in the environment. +@@ -1622,7 +1707,7 @@ test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + + echo "$0: unable to guess system type" >&2 + +-case "$UNAME_MACHINE:$UNAME_SYSTEM" in ++case $UNAME_MACHINE:$UNAME_SYSTEM in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 <&2 + exit 1 +@@ -1739,18 +1778,35 @@ esac + # As a final step for OS-related things, validate the OS-kernel combination + # (given a valid OS), if there is a kernel. + case $kernel-$os in +- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) ++ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ ++ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) + ;; +- -dietlibc* | -newlib* | -musl* | -uclibc* ) ++ uclinux-uclibc* ) ++ ;; ++ managarm-mlibc* | managarm-kernel* ) ++ ;; ++ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; ++ -kernel* ) ++ echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 ++ exit 1 ++ ;; ++ *-kernel* ) ++ echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 ++ exit 1 ++ ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; ++ vxworks-simlinux | vxworks-simwindows | vxworks-spe) ++ ;; + nto-qnx*) + ;; ++ os2-emx) ++ ;; + *-eabi* | *-gnueabi*) + ;; + -*) +diff --git a/configure.ac b/configure.ac +index 20f0873..456f836 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1027,7 +1027,8 @@ AS_IF([test x"$supports_shared_libraries" = 'xtrue'], + [aarch64-*-linux*], [natdynlink=true], + [aarch64-*-freebsd*], [natdynlink=true], + [aarch64-*-openbsd*], [natdynlink=true], +- [riscv*-*-linux*], [natdynlink=true])]) ++ [riscv*-*-linux*], [natdynlink=true], ++ [loongarch*-*-linux*], [natdynlink=true])]) + + AS_CASE([$enable_native_toplevel,$natdynlink], + [yes,false], +@@ -1144,7 +1145,9 @@ AS_CASE([$host], + [x86_64-*-cygwin*], + [arch=amd64; system=cygwin], + [riscv64-*-linux*], +- [arch=riscv; model=riscv64; system=linux] ++ [arch=riscv; model=riscv64; system=linux], ++ [loongarch64-*-linux*], ++ [arch=loongarch64; system=linux] + ) + + AS_IF([test x"$enable_native_compiler" = "xno"], +@@ -1239,7 +1242,7 @@ default_aspp="$CC -c" + AS_CASE([$as_target,$ocaml_cv_cc_vendor], + [*-*-linux*,gcc-*], + [AS_CASE([$as_cpu], +- [x86_64|arm*|aarch64*|i[[3-6]]86|riscv*], ++ [x86_64|arm*|aarch64*|i[[3-6]]86|riscv*|loongarch*], + [default_as="${toolpref}as"])], + [i686-pc-windows,*], + [default_as="ml -nologo -coff -Cp -c -Fo" +diff --git a/runtime/caml/stack.h b/runtime/caml/stack.h +index 9c182ee..e49c78d 100644 +--- a/runtime/caml/stack.h ++++ b/runtime/caml/stack.h +@@ -75,6 +75,11 @@ + #define Callback_link(sp) ((struct caml_context *)((sp) + 16)) + #endif + ++#ifdef TARGET_loongarch64 ++#define Saved_return_address(sp) *((intnat *)((sp) - 8)) ++#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) ++#endif ++ + /* Structure of OCaml callback contexts */ + + struct caml_context { +diff --git a/runtime/loongarch64.S b/runtime/loongarch64.S +new file mode 100644 +index 0000000..5034e8a +--- /dev/null ++++ b/runtime/loongarch64.S +@@ -0,0 +1,443 @@ ++ /**************************************************************************/ ++ /* */ ++ /* OCaml */ ++ /* */ ++ /* yala */ ++ /* */ ++ /* Copyright © 2008-2023 LOONGSON */ ++ /* */ ++ /* All rights reserved. This file is distributed under the terms of */ ++ /* the GNU Lesser General Public License version 2.1, with the */ ++ /* special exception on linking described in the file LICENSE. */ ++ /* */ ++ /**************************************************************************/ ++ ++/* Asm part of the runtime system, loongarch64 processor, 64-bit mode */ ++/* Must be preprocessed by cpp */ ++ ++#include "caml/m.h" ++ ++#define ARG_DOMAIN_STATE_PTR $t0 ++#define DOMAIN_STATE_PTR $s8 ++#define TRAP_PTR $s1 ++#define ALLOC_PTR $s7 ++#define TMP $t1 ++#define ARG $t2 ++ ++#define STORE st.d ++#define LOAD ld.d ++ ++#undef ASM_CFI_SUPPORTED ++#if defined(ASM_CFI_SUPPORTED) ++#define CFI_STARTPROC .cfi_startproc ++#define CFI_ENDPROC .cfi_endproc ++#define CFI_ADJUST(n) .cfi_adjust_cfa_offset n ++#define CFI_REGISTER(r1,r2) .cfi_register r1,r2 ++#define CFI_OFFSET(r,n) .cfi_offset r,n ++#else ++#define CFI_STARTPROC ++#define CFI_ENDPROC ++#define CFI_ADJUST(n) ++#define CFI_REGISTER(r1,r2) ++#define CFI_OFFSET(r,n) ++#endif ++ ++ .set domain_curr_field, 0 ++ .set domain_curr_cnt, 0 ++#define DOMAIN_STATE(c_type, name) \ ++ .equ domain_field_caml_##name, domain_curr_field ; \ ++ .set domain_curr_cnt, domain_curr_cnt + 1; \ ++ .set domain_curr_field, domain_curr_cnt*8 ++#include "../runtime/caml/domain_state.tbl" ++#undef DOMAIN_STATE ++ ++#define Caml_state(var) DOMAIN_STATE_PTR, domain_field_caml_##var ++ ++#define FUNCTION(name) \ ++ .align 2; \ ++ .globl name; \ ++ .type name, @function; \ ++name:; \ ++ CFI_STARTPROC ++ ++#define END_FUNCTION(name) \ ++ CFI_ENDPROC; \ ++ .size name, .-name ++ ++#if defined(__PIC__) ++#define PLT(r) %plt(r) ++#else ++#define PLT(r) r ++#endif ++ ++ .section .text ++/* Invoke the garbage collector. */ ++ ++ .globl caml_system__code_begin ++caml_system__code_begin: ++ ++FUNCTION(caml_call_gc) ++.Lcaml_call_gc: ++ /* Record return address */ ++ STORE $ra, Caml_state(last_return_address) ++ /* Record lowest stack address */ ++ STORE $sp, Caml_state(bottom_of_stack) ++ /* Set up stack space, saving return address */ ++ /* (1 reg for RA, 1 reg for FP, 23 allocatable int regs, ++ 20 caller-save float regs) * 8 */ ++ /* + 1 for alignment */ ++ addi.d $sp, $sp, -0x180 ++ CFI_ADJUST(0x180) ++ STORE $ra, $sp, 0x8 ++ CFI_OFFSET(ra, -0x180+8) ++ /* Save allocatable integer registers on the stack, ++ in the order given in proc.ml */ ++ STORE $a0, $sp, 0x10 ++ STORE $a1, $sp, 0x18 ++ STORE $a2, $sp, 0x20 ++ STORE $a3, $sp, 0x28 ++ STORE $a4, $sp, 0x30 ++ STORE $a5, $sp, 0x38 ++ STORE $a6, $sp, 0x40 ++ STORE $a7, $sp, 0x48 ++ STORE $s2, $sp, 0x50 ++ STORE $s3, $sp, 0x58 ++ STORE $s4, $sp, 0x60 ++ STORE $s5, $sp, 0x68 ++ STORE $s6, $sp, 0x70 ++ STORE $t2, $sp, 0x78 ++ STORE $t3, $sp, 0x80 ++ STORE $t4, $sp, 0x88 ++ STORE $t5, $sp, 0x90 ++ STORE $t6, $sp, 0x98 ++ STORE $t7, $sp, 0xa0 ++ STORE $t8, $sp, 0xa8 ++ STORE $s0, $sp, 0xb0 ++ /* Save caller-save floating-point registers on the stack ++ (callee-saves are preserved by caml_garbage_collection) */ ++ fst.d $ft0, $sp, 0xb8 ++ fst.d $ft1, $sp, 0xc0 ++ fst.d $ft2, $sp, 0xc8 ++ fst.d $ft3, $sp, 0xd0 ++ fst.d $ft4, $sp, 0xd8 ++ fst.d $ft5, $sp, 0xe0 ++ fst.d $ft6, $sp, 0xe8 ++ fst.d $ft7, $sp, 0xf0 ++ fst.d $fa0, $sp, 0xf8 ++ fst.d $fa1, $sp, 0x100 ++ fst.d $fa2, $sp, 0x108 ++ fst.d $fa3, $sp, 0x110 ++ fst.d $fa4, $sp, 0x118 ++ fst.d $fa5, $sp, 0x120 ++ fst.d $fa6, $sp, 0x128 ++ fst.d $fa7, $sp, 0x130 ++ fst.d $ft8, $sp, 0x138 ++ fst.d $ft9, $sp, 0x140 ++ fst.d $ft10, $sp, 0x148 ++ fst.d $ft11, $sp, 0x150 ++ fst.d $ft12, $sp, 0x158 ++ fst.d $ft13, $sp, 0x160 ++ fst.d $ft14, $sp, 0x168 ++ fst.d $ft15, $sp, 0x170 ++ /* Store pointer to saved integer registers in caml_gc_regs */ ++ addi.d TMP, $sp, 0x10 ++ STORE TMP, Caml_state(gc_regs) ++ /* Save current allocation pointer for debugging purposes */ ++ STORE ALLOC_PTR, Caml_state(young_ptr) ++ /* Save trap pointer in case an exception is raised during GC */ ++ STORE TRAP_PTR, Caml_state(exception_pointer) ++ /* Call the garbage collector */ ++ bl PLT(caml_garbage_collection) ++ /* Restore registers */ ++ LOAD $a0, $sp, 0x10 ++ LOAD $a1, $sp, 0x18 ++ LOAD $a2, $sp, 0x20 ++ LOAD $a3, $sp, 0x28 ++ LOAD $a4, $sp, 0x30 ++ LOAD $a5, $sp, 0x38 ++ LOAD $a6, $sp, 0x40 ++ LOAD $a7, $sp, 0x48 ++ LOAD $s2, $sp, 0x50 ++ LOAD $s3, $sp, 0x58 ++ LOAD $s4, $sp, 0x60 ++ LOAD $s5, $sp, 0x68 ++ LOAD $s6, $sp, 0x70 ++ LOAD $t2, $sp, 0x78 ++ LOAD $t3, $sp, 0x80 ++ LOAD $t4, $sp, 0x88 ++ LOAD $t5, $sp, 0x90 ++ LOAD $t6, $sp, 0x98 ++ LOAD $t7, $sp, 0xa0 ++ LOAD $t8, $sp, 0xa8 ++ LOAD $s0, $sp, 0xb0 ++ fld.d $ft0, $sp, 0xb8 ++ fld.d $ft1, $sp, 0xc0 ++ fld.d $ft2, $sp, 0xc8 ++ fld.d $ft3, $sp, 0xd0 ++ fld.d $ft4, $sp, 0xd8 ++ fld.d $ft5, $sp, 0xe0 ++ fld.d $ft6, $sp, 0xe8 ++ fld.d $ft7, $sp, 0xf0 ++ fld.d $fa0, $sp, 0xf8 ++ fld.d $fa1, $sp, 0x100 ++ fld.d $fa2, $sp, 0x108 ++ fld.d $fa3, $sp, 0x110 ++ fld.d $fa4, $sp, 0x118 ++ fld.d $fa5, $sp, 0x120 ++ fld.d $fa6, $sp, 0x128 ++ fld.d $fa7, $sp, 0x130 ++ fld.d $ft8, $sp, 0x138 ++ fld.d $ft9, $sp, 0x140 ++ fld.d $ft10, $sp, 0x148 ++ fld.d $ft11, $sp, 0x150 ++ fld.d $ft12, $sp, 0x158 ++ fld.d $ft13, $sp, 0x160 ++ fld.d $ft14, $sp, 0x168 ++ fld.d $ft15, $sp, 0x170 ++ /* Reload new allocation pointer */ ++ LOAD ALLOC_PTR, Caml_state(young_ptr) ++ /* Free stack space and return to caller */ ++ LOAD $ra, $sp, 0x8 ++ addi.d $sp, $sp, 0x180 ++ CFI_ADJUST(-0x180) ++ jr $ra ++END_FUNCTION(caml_call_gc) ++ ++/* Call a C function from OCaml */ ++/* Function to bl is in ARG */ ++ ++FUNCTION(caml_c_call) ++ /* Preserve return address in callee-save register s2 */ ++ move $s2, $ra ++ CFI_REGISTER(ra, s2) ++ /* Record lowest stack address and return address */ ++ STORE $ra, Caml_state(last_return_address) ++ STORE $sp, Caml_state(bottom_of_stack) ++ /* Make the exception handler alloc ptr available to the C code */ ++ STORE ALLOC_PTR, Caml_state(young_ptr) ++ STORE TRAP_PTR, Caml_state(exception_pointer) ++ /* Call the function */ ++ jirl $ra, ARG, 0 ++ /* Reload alloc ptr */ ++ LOAD ALLOC_PTR, Caml_state(young_ptr) ++ /* Return */ ++ jr $s2 ++END_FUNCTION(caml_c_call) ++ ++/* Raise an exception from OCaml */ ++FUNCTION(caml_raise_exn) ++ /* Test if backtrace is active */ ++ LOAD TMP, Caml_state(backtrace_active) ++ bnez TMP, 2f ++1: /* Cut stack at current trap handler */ ++ move $sp, TRAP_PTR ++ /* Pop previous handler and jump to it */ ++ LOAD TMP, $sp, 8 ++ LOAD TRAP_PTR, $sp, 0 ++ addi.d $sp, $sp, 16 ++ CFI_ADJUST(-16) ++ jr TMP ++2: /* Preserve exception bucket in callee-save register s2 */ ++ move $s2, $a0 ++ /* Stash the backtrace */ ++ move $a1, $ra ++ move $a2, $sp ++ move $a3, TRAP_PTR ++ bl PLT(caml_stash_backtrace) ++ /* Restore exception bucket and raise */ ++ move $a0, $s2 ++ b 1b ++END_FUNCTION(caml_raise_exn) ++ ++ .globl caml_reraise_exn ++ .type caml_reraise_exn, @function ++ ++/* Raise an exception from C */ ++ ++FUNCTION(caml_raise_exception) ++ move DOMAIN_STATE_PTR, $a0 ++ move $a0, $a1 ++ LOAD TRAP_PTR, Caml_state(exception_pointer) ++ LOAD ALLOC_PTR, Caml_state(young_ptr) ++ LOAD TMP, Caml_state(backtrace_active) ++ bnez TMP, 2f ++1: /* Cut stack at current trap handler */ ++ move $sp, TRAP_PTR ++ LOAD TMP, $sp, 8 ++ LOAD TRAP_PTR, $sp, 0 ++ addi.d $sp, $sp, 16 ++ CFI_ADJUST(-16) ++ jr TMP ++2: /* Preserve exception bucket in callee-save register s2 */ ++ move $s2, $a0 ++ LOAD $a1, Caml_state(last_return_address) ++ LOAD $a2, Caml_state(bottom_of_stack) ++ move $a3, TRAP_PTR ++ bl PLT(caml_stash_backtrace) ++ move $a0, $s2 ++ b 1b ++END_FUNCTION(caml_raise_exception) ++ ++/* Start the OCaml program */ ++ ++FUNCTION(caml_start_program) ++ move ARG_DOMAIN_STATE_PTR, $a0 ++ la.global ARG, caml_program ++ /* Code shared with caml_callback* */ ++ /* Address of OCaml code to bl is in ARG */ ++ /* Arguments to the OCaml code are in a0 ... a7 */ ++.Ljump_to_caml: ++ /* Set up stack frame and save callee-save registers */ ++ addi.d $sp, $sp, -0xa0 ++ CFI_ADJUST(0xa0) ++ STORE $ra, $sp, 0x90 ++ CFI_OFFSET(ra, -0xa0+0xb0) ++ STORE $s0, $sp, 0x0 ++ STORE $s1, $sp, 0x8 ++ STORE $s2, $sp, 0x10 ++ STORE $s3, $sp, 0x18 ++ STORE $s4, $sp, 0x20 ++ STORE $s5, $sp, 0x28 ++ STORE $s6, $sp, 0x30 ++ STORE $s7, $sp, 0x38 ++ STORE $s8, $sp, 0x40 ++ fst.d $fs0, $sp, 0x48 ++ fst.d $fs1, $sp, 0x50 ++ fst.d $fs2, $sp, 0x58 ++ fst.d $fs3, $sp, 0x60 ++ fst.d $fs4, $sp, 0x68 ++ fst.d $fs5, $sp, 0x70 ++ fst.d $fs6, $sp, 0x78 ++ fst.d $fs7, $sp, 0x80 ++ addi.d $sp, $sp, -32 ++ CFI_ADJUST(32) ++ /* Load domain state pointer from argument */ ++ move DOMAIN_STATE_PTR, ARG_DOMAIN_STATE_PTR ++ /* Setup a callback link on the stack */ ++ LOAD TMP, Caml_state(bottom_of_stack) ++ STORE TMP, $sp, 0 ++ LOAD TMP, Caml_state(last_return_address) ++ STORE TMP, $sp, 8 ++ LOAD TMP, Caml_state(gc_regs) ++ STORE TMP, $sp, 16 ++ /* set up a trap frame */ ++ addi.d $sp, $sp, -16 ++ CFI_ADJUST(16) ++ LOAD TMP, Caml_state(exception_pointer) ++ STORE TMP, $sp, 0 ++ la.local TMP, .Ltrap_handler ++ STORE TMP, $sp, 8 ++ move TRAP_PTR, $sp ++ LOAD ALLOC_PTR, Caml_state(young_ptr) ++ STORE $zero, Caml_state(last_return_address) ++ jirl $ra, ARG, 0 ++.Lcaml_retaddr: /* pop trap frame, restoring caml_exception_pointer */ ++ LOAD TMP, $sp, 0 ++ STORE TMP, Caml_state(exception_pointer) ++ addi.d $sp, $sp, 16 ++ CFI_ADJUST(-16) ++.Lreturn_result: /* pop callback link, restoring global variables */ ++ LOAD TMP, $sp, 0 ++ STORE TMP, Caml_state(bottom_of_stack) ++ LOAD TMP, $sp, 8 ++ STORE TMP, Caml_state(last_return_address) ++ LOAD TMP, $sp, 16 ++ STORE TMP, Caml_state(gc_regs) ++ addi.d $sp, $sp, 32 ++ CFI_ADJUST(-32) ++ /* Update allocation pointer */ ++ STORE ALLOC_PTR, Caml_state(young_ptr) ++ /* reload callee-save registers and return */ ++ LOAD $ra, $sp, 0x90 ++ LOAD $s0, $sp, 0x0 ++ LOAD $s1, $sp, 0x8 ++ LOAD $s2, $sp, 0x10 ++ LOAD $s3, $sp, 0x18 ++ LOAD $s4, $sp, 0x20 ++ LOAD $s5, $sp, 0x28 ++ LOAD $s6, $sp, 0x30 ++ LOAD $s7, $sp, 0x38 ++ LOAD $s8, $sp, 0x40 ++ fld.d $fs0, $sp, 0x48 ++ fld.d $fs1, $sp, 0x50 ++ fld.d $fs2, $sp, 0x58 ++ fld.d $fs3, $sp, 0x60 ++ fld.d $fs4, $sp, 0x68 ++ fld.d $fs5, $sp, 0x70 ++ fld.d $fs6, $sp, 0x78 ++ fld.d $fs7, $sp, 0x80 ++ addi.d $sp, $sp, 0xa0 ++ CFI_ADJUST(-0xa0) ++ jr $ra ++ .type .Lcaml_retaddr, @function ++ .size .Lcaml_retaddr, .-.Lcaml_retaddr ++END_FUNCTION(caml_start_program) ++ ++ .align 2 ++.Ltrap_handler: ++ CFI_STARTPROC ++ STORE TRAP_PTR, Caml_state(exception_pointer) ++ ori $a0, $a0, 2 ++ b .Lreturn_result ++ .type .Ltrap_handler, @function ++END_FUNCTION(.Ltrap_handler) ++ ++/* Callback from C to OCaml */ ++ ++FUNCTION(caml_callback_asm) ++ /* Initial shuffling of arguments */ ++ /* a0 = Caml_state, a1 = closure, (a2) = args */ ++ move ARG_DOMAIN_STATE_PTR, $a0 ++ LOAD $a0, $a2, 0 /* a0 = first arg */ ++ /* a1 = closure environment */ ++ LOAD ARG, $a1, 0 /* code pointer */ ++ b .Ljump_to_caml ++END_FUNCTION(caml_callback_asm) ++ ++FUNCTION(caml_callback2_asm) ++ /* Initial shuffling of arguments */ ++ /* a0 = Caml_state, a1 = closure, (a2) = args */ ++ move ARG_DOMAIN_STATE_PTR, $a0 ++ move TMP, $a1 ++ LOAD $a0, $a2, 0 ++ LOAD $a1, $a2, 8 ++ move $a2, TMP ++ la.global ARG, caml_apply2 ++ b .Ljump_to_caml ++END_FUNCTION(caml_callback2_asm) ++ ++FUNCTION(caml_callback3_asm) ++ /* Initial shuffling of arguments */ ++ /* a0 = Caml_state, a1 = closure, (a2) = args */ ++ move ARG_DOMAIN_STATE_PTR, $a0 ++ move $a3, $a1 ++ LOAD $a0, $a2, 0 ++ LOAD $a1, $a2, 8 ++ LOAD $a2, $a2, 16 ++ la.global ARG, caml_apply3 ++ b .Ljump_to_caml ++END_FUNCTION(caml_callback3_asm) ++ ++FUNCTION(caml_ml_array_bound_error) ++ /* Load address of [caml_array_bound_error] in ARG */ ++ la.global ARG, caml_array_bound_error ++ /* Call that function */ ++ b caml_c_call ++END_FUNCTION(caml_ml_array_bound_error) ++ ++ .globl caml_system__code_end ++caml_system__code_end: ++ ++/* GC roots for callback */ ++ ++ .section .data ++ .align 3 ++ .globl caml_system__frametable ++ .type caml_system__frametable, @object ++caml_system__frametable: ++ .quad 1 /* one descriptor */ ++ .quad .Lcaml_retaddr /* return address into callback */ ++ .short -1 /* negative frame size => use callback link */ ++ .short 0 /* no roots */ ++ .align 3 ++ .size caml_system__frametable, .-caml_system__frametable +diff --git a/testsuite/tools/asmgen_loongarch64.S b/testsuite/tools/asmgen_loongarch64.S +new file mode 100644 +index 0000000..ca5ef1b +--- /dev/null ++++ b/testsuite/tools/asmgen_loongarch64.S +@@ -0,0 +1,75 @@ ++/**************************************************************************/ ++/* */ ++/* OCaml */ ++/* */ ++/* Nicolas Ojeda Bar */ ++/* */ ++/* Copyright 2019 Institut National de Recherche en Informatique et */ ++/* en Automatique. */ ++/* */ ++/* All rights reserved. This file is distributed under the terms of */ ++/* the GNU Lesser General Public License version 2.1, with the */ ++/* special exception on linking described in the file LICENSE. */ ++/* */ ++/**************************************************************************/ ++ ++#define STORE st.d ++#define LOAD ld.d ++ ++ .globl call_gen_code ++ .align 2 ++call_gen_code: ++ /* Set up stack frame and save callee-save registers */ ++ addi.d $sp, $sp, -208 ++ STORE $ra, $sp, 192 ++ STORE $s0, $sp, 0 ++ STORE $s1, $sp, 8 ++ STORE $s2, $sp, 16 ++ STORE $s3, $sp, 24 ++ STORE $s4, $sp, 32 ++ STORE $s5, $sp, 40 ++ STORE $s6, $sp, 48 ++ STORE $s7, $sp, 56 ++ STORE $s8, $sp, 64 ++ fst.d $fs0, $sp, 96 ++ fst.d $fs1, $sp, 104 ++ fst.d $fs2, $sp, 112 ++ fst.d $fs3, $sp, 120 ++ fst.d $fs4, $sp, 128 ++ fst.d $fs5, $sp, 136 ++ fst.d $fs6, $sp, 144 ++ fst.d $fs7, $sp, 152 ++ /* Shuffle arguments */ ++ move $t0, $a0 ++ move $a0, $a1 ++ move $a1, $a2 ++ move $a2, $a3 ++ move $a3, $a4 ++ /* Call generated asm */ ++ jirl $ra, $t0, 0 ++ /* Reload callee-save registers and return address */ ++ LOAD $ra, $sp, 192 ++ LOAD $s0, $sp, 0 ++ LOAD $s1, $sp, 8 ++ LOAD $s2, $sp ,16 ++ LOAD $s3, $sp ,24 ++ LOAD $s4, $sp ,32 ++ LOAD $s5, $sp ,40 ++ LOAD $s6, $sp ,48 ++ LOAD $s7, $sp ,56 ++ LOAD $s8, $sp ,64 ++ fld.d $fs0, $sp, 96 ++ fld.d $fs1, $sp, 104 ++ fld.d $fs2, $sp, 112 ++ fld.d $fs3, $sp, 120 ++ fld.d $fs4, $sp, 128 ++ fld.d $fs5, $sp, 136 ++ fld.d $fs6, $sp, 144 ++ fld.d $fs7, $sp, 152 ++ addi.d $sp, $sp, 208 ++ jr $ra ++ ++ .globl caml_c_call ++ .align 2 ++caml_c_call: ++ jr $t2 +-- +2.42.0 + + diff --git a/ocaml.spec b/ocaml.spec index 2a9252f..4c67073 100644 --- a/ocaml.spec +++ b/ocaml.spec @@ -1,19 +1,11 @@ -%ifnarch loongarch64 %global native_compiler 1 -%else -%global native_compiler 0 -%endif -%ifnarch loongarch64 %global natdynlink 1 -%else -%global natdynlink 0 -%endif Name: ocaml Version: 4.14.1 -Release: 1 +Release: 3 Summary: OCaml compiler and programming environment License: LGPL-2.1-only URL: http://www.ocaml.org @@ -22,11 +14,12 @@ Source0: https://github.com/ocaml/ocaml/archive/refs/tags/%{name}-%{versi Patch0001: 0001-Don-t-add-rpaths-to-libraries.patch Patch0002: 0002-configure-Allow-user-defined-C-compiler-flags.patch Patch0003: 0003-configure-Remove-incorrect-assumption-about-cross-co.patch +Patch0004: 0004-add-loongarch64-native-support.patch BuildRequires: gcc binutils-devel ncurses-devel gdbm-devel gawk perl-interpreter BuildRequires: util-linux chrpath autoconf annobin make -Requires: gcc util-linux openEuler-rpm-config +Requires: gcc util-linux %{_vendor}-rpm-config Provides: bundled(md5-plumb) ocaml(runtime) = %{version} Provides: ocaml(compiler) = %{version} @@ -114,7 +107,7 @@ make -j1 all ||: make install DESTDIR=$RPM_BUILD_ROOT perl -pi -e "s|^%{buildroot}||" %{buildroot}%{_libdir}/ocaml/ld.conf -echo %{version} > %{buildroot}%{_libdir}/ocaml/openEuler-ocaml-release +echo %{version} > %{buildroot}%{_libdir}/ocaml/%{_vendor}-ocaml-release chrpath --delete %{buildroot}%{_libdir}/ocaml/stublibs/*.so @@ -213,7 +206,7 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/ocaml/eventlog_metadata %dir %{_libdir}/ocaml/threads %{_libdir}/ocaml/threads/*.cmi %{_libdir}/ocaml/threads/*.cma -%{_libdir}/ocaml/openEuler-ocaml-release +%{_libdir}/ocaml/%{_vendor}-ocaml-release #ocamldoc @@ -248,6 +241,12 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/ocaml/eventlog_metadata %{_mandir}/man3/* %changelog +* Fri Jun 07 2024 Wenlong Zhang - 4.14.1-3 +- Add LoongArch native support for ocaml + +* Mon Apr 15 2024 yueyuankun - 4.14.1-2 +- Replace openEuler with vendor macros + * Fri Feb 2 2024 Jingwiw - 4.14.1-1 - Upgrade version to 4.14.1 -- Gitee