Skip to content

Commit e5c75f3

Browse files
authored
Embedded LLD Phase 1: Build infrastructure + CRT objects (#4945)
This is the first phase of embedded LLD linking support. It establishes build infrastructure without changing how ponyc links user programs — the legacy system() path remains the only active code path. What's included: - LLD libraries built as part of the vendored LLVM build - LLD libraries linked into ponyc, test, and benchmark targets - libponyc-standalone updated to bundle LLD archives - compiler-rt CRT objects compiled for the host architecture - CRT objects compiled during cross-compilation builds - genexe.c and program.c converted to C++ for future LLD API access - New structured API for library arguments (program_lib_build_args_embedded) What's NOT included: - No LLD functions are called - No changes to how ponyc links user programs - No new CLI options Design: #4942
1 parent 09941a6 commit e5c75f3

File tree

11 files changed

+278
-8
lines changed

11 files changed

+278
-8
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
2525
# We require LLVM, Google Test and Google Benchmark
2626
if(NOT PONY_CROSS_LIBPONYRT)
2727
find_package(LLVM REQUIRED CONFIG PATHS "build/libs/lib/cmake/llvm" "build/libs/lib64/cmake/llvm" NO_DEFAULT_PATH)
28+
find_package(LLD REQUIRED CONFIG PATHS "build/libs/lib/cmake/lld" "build/libs/lib64/cmake/lld" NO_DEFAULT_PATH)
2829
find_package(GTest REQUIRED CONFIG PATHS "build/libs/lib/cmake/GTest" "build/libs/lib64/cmake/GTest" NO_DEFAULT_PATH)
2930
find_package(benchmark REQUIRED CONFIG PATHS "build/libs/lib/cmake/benchmark" "build/libs/lib64/cmake/benchmark" NO_DEFAULT_PATH)
3031
endif()
@@ -215,6 +216,8 @@ if(NOT PONY_CROSS_LIBPONYRT)
215216
216217
llvm_map_components_to_libnames(PONYC_LLVM_LIBS ${LLVM_COMPONENTS})
217218
# message("PONYC_LLVM_LIBS: ${PONYC_LLVM_LIBS}")
219+
220+
set(PONYC_LLD_LIBS lldELF lldMachO lldCOFF lldWasm lldMinGW lldCommon)
218221
endif()
219222
220223
# Required definitions. We use these generators so that the defines are correct for both *nix (where the config applies at configuration time) and Windows (where the config applies at build time).
@@ -294,6 +297,9 @@ set(CMAKE_STATIC_LIBRARY_PREFIX "")
294297
295298
if (PONY_CROSS_LIBPONYRT)
296299
add_subdirectory(src/libponyrt)
300+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
301+
add_subdirectory(src/crt)
302+
endif()
297303
install(TARGETS libponyrt)
298304
else()
299305
add_subdirectory(src/libponyc)
@@ -308,6 +314,10 @@ else()
308314
add_subdirectory(benchmark/libponyc)
309315
add_subdirectory(benchmark/libponyrt)
310316
317+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
318+
add_subdirectory(src/crt)
319+
endif()
320+
311321
add_subdirectory(tools/pony-lsp)
312322
add_subdirectory(tools/pony-lint)
313323
add_subdirectory(tools/pony-doc)

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ crossBuildDir := $(srcDir)/build/$(arch)/build_$(config)
217217
cross-libponyrt:
218218
$(SILENT)mkdir -p $(crossBuildDir)
219219
$(SILENT)cd '$(crossBuildDir)' && env CC=$(CC) CXX=$(CXX) cmake -B '$(crossBuildDir)' -S '$(srcDir)' -DCMAKE_CROSSCOMPILING=true -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=$(arch) -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DPONY_CROSS_LIBPONYRT=true -DCMAKE_BUILD_TYPE=$(config) -DCMAKE_C_FLAGS="$(cross_cflags)" -DCMAKE_CXX_FLAGS="$(cross_cflags)" -DPONY_ARCH=$(arch) -DPONYC_VERSION=$(version) -DLL_FLAGS="$(cross_llc_flags)" $(CMAKE_FLAGS)
220-
$(SILENT)cd '$(crossBuildDir)' && env CC=$(CC) CXX=$(CXX) cmake --build '$(crossBuildDir)' --config $(config) --target libponyrt -- $(build_flags)
220+
$(SILENT)cd '$(crossBuildDir)' && env CC=$(CC) CXX=$(CXX) cmake --build '$(crossBuildDir)' --config $(config) --target libponyrt crt_objects -- $(build_flags)
221221

222222
test: all test-core test-stdlib-release test-examples
223223

@@ -325,6 +325,10 @@ install: build
325325
$(SILENT)if [ -f $(outDir)/libponyc.a ]; then cp $(outDir)/libponyc.a $(ponydir)/lib/$(arch); fi
326326
$(SILENT)if [ -f $(outDir)/libponyc-standalone.a ]; then cp $(outDir)/libponyc-standalone.a $(ponydir)/lib/$(arch); fi
327327
$(SILENT)if [ -f $(outDir)/libponyrt-pic.a ]; then cp $(outDir)/libponyrt-pic.a $(ponydir)/lib/$(arch); fi
328+
$(SILENT)if [ -f $(outDir)/crtbeginS.o ]; then cp $(outDir)/crtbeginS.o $(ponydir)/lib/$(arch); fi
329+
$(SILENT)if [ -f $(outDir)/crtendS.o ]; then cp $(outDir)/crtendS.o $(ponydir)/lib/$(arch); fi
330+
$(SILENT)if [ -f $(outDir)/crtbeginT.o ]; then cp $(outDir)/crtbeginT.o $(ponydir)/lib/$(arch); fi
331+
$(SILENT)if [ -f $(outDir)/crtend.o ]; then cp $(outDir)/crtend.o $(ponydir)/lib/$(arch); fi
328332
$(SILENT)cp $(outDir)/ponyc $(ponydir)/bin
329333
$(SILENT)if [ -f $(outDir)/pony-lsp ]; then cp $(outDir)/pony-lsp $(ponydir)/bin; fi
330334
$(SILENT)if [ -f $(outDir)/pony-lint ]; then cp $(outDir)/pony-lint $(ponydir)/bin; fi

benchmark/libponyc/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
4848
endif()
4949

5050
if(NOT PONY_CROSS_LIBPONYRT)
51-
target_link_libraries(libponyc.benchmarks PRIVATE ${PONYC_LLVM_LIBS})
51+
target_link_libraries(libponyc.benchmarks PRIVATE ${PONYC_LLVM_LIBS} ${PONYC_LLD_LIBS})
5252
endif()

lib/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,6 @@ if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
144144
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -mmacosx-version-min=10.14")
145145
endif()
146146

147+
set(LLVM_ENABLE_PROJECTS "lld" CACHE STRING "ponyc: build LLD as an LLVM sub-project")
148+
147149
add_subdirectory(llvm/src/llvm)

src/crt/CMakeLists.txt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)
2+
3+
project(ponyc_crt LANGUAGES C)
4+
5+
set(CRT_SRC_DIR ${CMAKE_SOURCE_DIR}/lib/llvm/src/compiler-rt/lib/builtins)
6+
set(CRT_COMMON_FLAGS -DCRT_HAS_INITFINI_ARRAY -DEH_USE_FRAME_REGISTRY)
7+
8+
# PIE/shared variants (for dynamic linking — the default)
9+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/crtbeginS.o
10+
COMMAND ${CMAKE_C_COMPILER} -c ${PONY_PIC_FLAG} ${CRT_COMMON_FLAGS}
11+
-o ${CMAKE_CURRENT_BINARY_DIR}/crtbeginS.o
12+
${CRT_SRC_DIR}/crtbegin.c
13+
DEPENDS ${CRT_SRC_DIR}/crtbegin.c
14+
COMMENT "Compiling crtbeginS.o (PIC)")
15+
16+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/crtendS.o
17+
COMMAND ${CMAKE_C_COMPILER} -c ${PONY_PIC_FLAG} ${CRT_COMMON_FLAGS}
18+
-o ${CMAKE_CURRENT_BINARY_DIR}/crtendS.o
19+
${CRT_SRC_DIR}/crtend.c
20+
DEPENDS ${CRT_SRC_DIR}/crtend.c
21+
COMMENT "Compiling crtendS.o (PIC)")
22+
23+
# Static variants (for --static linking)
24+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/crtbeginT.o
25+
COMMAND ${CMAKE_C_COMPILER} -c ${CRT_COMMON_FLAGS}
26+
-o ${CMAKE_CURRENT_BINARY_DIR}/crtbeginT.o
27+
${CRT_SRC_DIR}/crtbegin.c
28+
DEPENDS ${CRT_SRC_DIR}/crtbegin.c
29+
COMMENT "Compiling crtbeginT.o (static)")
30+
31+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/crtend.o
32+
COMMAND ${CMAKE_C_COMPILER} -c ${CRT_COMMON_FLAGS}
33+
-o ${CMAKE_CURRENT_BINARY_DIR}/crtend.o
34+
${CRT_SRC_DIR}/crtend.c
35+
DEPENDS ${CRT_SRC_DIR}/crtend.c
36+
COMMENT "Compiling crtend.o (static)")
37+
38+
add_custom_target(crt_objects ALL
39+
DEPENDS
40+
${CMAKE_CURRENT_BINARY_DIR}/crtbeginS.o
41+
${CMAKE_CURRENT_BINARY_DIR}/crtendS.o
42+
${CMAKE_CURRENT_BINARY_DIR}/crtbeginT.o
43+
${CMAKE_CURRENT_BINARY_DIR}/crtend.o)
44+
45+
# Copy to output directory alongside libponyrt.
46+
set(CRT_FILES
47+
${CMAKE_CURRENT_BINARY_DIR}/crtbeginS.o
48+
${CMAKE_CURRENT_BINARY_DIR}/crtendS.o
49+
${CMAKE_CURRENT_BINARY_DIR}/crtbeginT.o
50+
${CMAKE_CURRENT_BINARY_DIR}/crtend.o)
51+
52+
foreach(CRT_FILE ${CRT_FILES})
53+
add_custom_command(TARGET crt_objects POST_BUILD
54+
COMMAND $<$<CONFIG:Debug>:${CMAKE_COMMAND}> ARGS -E copy ${CRT_FILE} ${CMAKE_BINARY_DIR}/../debug${PONY_OUTPUT_SUFFIX}/
55+
COMMAND $<$<CONFIG:Release>:${CMAKE_COMMAND}> ARGS -E copy ${CRT_FILE} ${CMAKE_BINARY_DIR}/../release${PONY_OUTPUT_SUFFIX}/
56+
COMMAND $<$<CONFIG:RelWithDebInfo>:${CMAKE_COMMAND}> ARGS -E copy ${CRT_FILE} ${CMAKE_BINARY_DIR}/../relwithdebinfo${PONY_OUTPUT_SUFFIX}/
57+
COMMAND $<$<CONFIG:MinSizeRel>:${CMAKE_COMMAND}> ARGS -E copy ${CRT_FILE} ${CMAKE_BINARY_DIR}/../minsizerel${PONY_OUTPUT_SUFFIX}/
58+
)
59+
endforeach()

src/libponyc/CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ add_library(libponyc STATIC
2525
codegen/gencall.c
2626
codegen/gencontrol.c
2727
codegen/gendesc.c
28-
codegen/genexe.c
28+
codegen/genexe.cc
2929
codegen/genexpr.c
3030
codegen/genfun.c
3131
codegen/genheader.c
@@ -72,7 +72,7 @@ add_library(libponyc STATIC
7272
pkg/ifdef.c
7373
pkg/package.c
7474
pkg/platformfuns.c
75-
pkg/program.c
75+
pkg/program.cc
7676
pkg/use.c
7777
platform/paths.c
7878
platform/vcvars.c
@@ -130,12 +130,13 @@ endif (NOT MSVC)
130130
if (MSVC)
131131
# this will not include LLVM-C.lib as it contains lots of duplicated definitions
132132
file(GLOB_RECURSE LLVM_OBJS "${PROJECT_SOURCE_DIR}/../../build/libs/lib/LLVM[!-]*.lib")
133+
file(GLOB_RECURSE LLD_OBJS "${PROJECT_SOURCE_DIR}/../../build/libs/lib/lld*.lib")
133134

134135
set(libponyc_standalone_file "${CMAKE_STATIC_LIBRARY_PREFIX}ponyc-standalone${CMAKE_STATIC_LIBRARY_SUFFIX}")
135136
set(libponyc_standalone_path "${CMAKE_BINARY_DIR}/${libponyc_standalone_file}")
136137
add_custom_target(libponyc-standalone ALL
137138
# CMAKE_AR finds the appropriate version of lib.exe according to desired target and host architecture
138-
COMMAND ${CMAKE_AR} /NOLOGO /VERBOSE /OUT:${libponyc_standalone_path} "$<TARGET_FILE:libponyc>" ${LLVM_OBJS} "${PROJECT_SOURCE_DIR}/../../build/libs/lib/blake2.lib"
139+
COMMAND ${CMAKE_AR} /NOLOGO /VERBOSE /OUT:${libponyc_standalone_path} "$<TARGET_FILE:libponyc>" ${LLVM_OBJS} ${LLD_OBJS} "${PROJECT_SOURCE_DIR}/../../build/libs/lib/blake2.lib"
139140
DEPENDS libponyc)
140141
add_custom_command(TARGET libponyc-standalone POST_BUILD
141142
COMMAND $<$<CONFIG:Debug>:${CMAKE_COMMAND}> ARGS -E copy ${libponyc_standalone_path} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/${libponyc_standalone_file}
@@ -148,8 +149,9 @@ elseif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
148149
# so when we want to use this lib
149150
# we need to additionally link libc++ and libz (for llvm)
150151
file(GLOB_RECURSE LLVM_OBJS "${PROJECT_SOURCE_DIR}/../../build/libs/lib/libLLVM*.a")
152+
file(GLOB_RECURSE LLD_OBJS "${PROJECT_SOURCE_DIR}/../../build/libs/lib/liblld*.a")
151153
add_custom_target(libponyc-standalone ALL
152-
COMMAND libtool -static -o libponyc-standalone.a $<TARGET_FILE:libponyc> ${PROJECT_SOURCE_DIR}/../../build/libs/lib/libblake2.a ${LLVM_OBJS}
154+
COMMAND libtool -static -o libponyc-standalone.a $<TARGET_FILE:libponyc> ${PROJECT_SOURCE_DIR}/../../build/libs/lib/libblake2.a ${LLVM_OBJS} ${LLD_OBJS}
153155
DEPENDS $<TARGET_FILE:libponyc> ${STANDALONE_ARCHIVES}
154156
)
155157
# copy the generated file after it is built
@@ -167,6 +169,7 @@ elseif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "FreeBSD")
167169
COMMAND echo "addlib ${PROJECT_SOURCE_DIR}/../../build/libs/lib/libblake2.a" >> standalone.mri
168170
COMMAND echo "addlib libcpp.a" >> standalone.mri
169171
COMMAND find ${PROJECT_SOURCE_DIR}/../../build/libs/ -name "libLLVM*.a" | xargs -I % -n 1 echo 'addlib %' >> standalone.mri
172+
COMMAND find ${PROJECT_SOURCE_DIR}/../../build/libs/ -name "liblld*.a" | xargs -I % -n 1 echo 'addlib %' >> standalone.mri
170173
COMMAND echo "addlib $<TARGET_FILE:libponyc>" >> standalone.mri
171174
COMMAND echo "save" >> standalone.mri
172175
COMMAND echo "end" >> standalone.mri
@@ -215,6 +218,7 @@ else()
215218
COMMAND echo "addlib ${PROJECT_SOURCE_DIR}/../../build/libs/lib/libblake2.a" >> standalone.mri
216219
COMMAND echo "addlib libstdcpp.a" >> standalone.mri
217220
COMMAND find ${PROJECT_SOURCE_DIR}/../../build/libs/ -name "libLLVM*.a" | xargs -I % -n 1 echo 'addlib %' >> standalone.mri
221+
COMMAND find ${PROJECT_SOURCE_DIR}/../../build/libs/ -name "liblld*.a" | xargs -I % -n 1 echo 'addlib %' >> standalone.mri
218222
COMMAND echo "addlib $<TARGET_FILE:libponyc>" >> standalone.mri
219223
COMMAND echo "save" >> standalone.mri
220224
COMMAND echo "end" >> standalone.mri
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
#include "genexe.h"
2+
3+
#include <lld/Common/Driver.h>
4+
5+
LLD_HAS_DRIVER(elf)
6+
LLD_HAS_DRIVER(macho)
7+
LLD_HAS_DRIVER(coff)
8+
LLD_HAS_DRIVER(mingw)
9+
LLD_HAS_DRIVER(wasm)
10+
211
#include "gencall.h"
312
#include "genfun.h"
413
#include "genname.h"

0 commit comments

Comments
 (0)