From ba71e8d5e3fcfa783edb830fefcf08a88f47cd65 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sat, 23 Mar 2024 22:24:45 -0400 Subject: [PATCH] Add support for building object files from LLVM assembly sources - close #175 --- build_tests/llvm/Rsconscript | 4 ++++ build_tests/llvm/direct.rb | 8 ++++++++ build_tests/llvm/main.c | 6 ++++++ build_tests/llvm/main2.c | 9 +++++++++ build_tests/llvm/one.ll | 9 +++++++++ build_tests/llvm/two.ll | 9 +++++++++ lib/rscons.rb | 1 + lib/rscons/builders/lang/llvm_asm.rb | 10 ++++++++++ lib/rscons/default_construction_variables.rb | 5 +++++ spec/build_tests_spec.rb | 18 ++++++++++++++++++ 10 files changed, 79 insertions(+) create mode 100644 build_tests/llvm/Rsconscript create mode 100644 build_tests/llvm/direct.rb create mode 100644 build_tests/llvm/main.c create mode 100644 build_tests/llvm/main2.c create mode 100644 build_tests/llvm/one.ll create mode 100644 build_tests/llvm/two.ll create mode 100644 lib/rscons/builders/lang/llvm_asm.rb diff --git a/build_tests/llvm/Rsconscript b/build_tests/llvm/Rsconscript new file mode 100644 index 0000000..8782816 --- /dev/null +++ b/build_tests/llvm/Rsconscript @@ -0,0 +1,4 @@ +env do |env| + env["LLVMAS_FLAGS"] += %w[-Wno-override-module] + env.Program("llvmtest.exe", %w[main.c one.ll]) +end diff --git a/build_tests/llvm/direct.rb b/build_tests/llvm/direct.rb new file mode 100644 index 0000000..cbd8349 --- /dev/null +++ b/build_tests/llvm/direct.rb @@ -0,0 +1,8 @@ +configure do + check_c_compiler "clang" +end + +env do |env| + env["LLVMAS_FLAGS"] += %w[-Wno-override-module] + env.Program("llvmtest.exe", %w[one.ll two.ll main2.c], direct: true) +end diff --git a/build_tests/llvm/main.c b/build_tests/llvm/main.c new file mode 100644 index 0000000..5fae79b --- /dev/null +++ b/build_tests/llvm/main.c @@ -0,0 +1,6 @@ +extern int one(void); + +int main(int argc, char * argv[]) +{ + return one(); +} diff --git a/build_tests/llvm/main2.c b/build_tests/llvm/main2.c new file mode 100644 index 0000000..1e6e00d --- /dev/null +++ b/build_tests/llvm/main2.c @@ -0,0 +1,9 @@ +extern int one(void); +extern int two(void); + +int main(int argc, char * argv[]) +{ + one(); + two(); + return 0; +} diff --git a/build_tests/llvm/one.ll b/build_tests/llvm/one.ll new file mode 100644 index 0000000..b67b97f --- /dev/null +++ b/build_tests/llvm/one.ll @@ -0,0 +1,9 @@ +@str = private unnamed_addr constant [12 x i8] c"hello world\00" + +declare i32 @puts(ptr nocapture) nounwind + +define i32 @one() +{ + call i32 @puts(ptr @str) + ret i32 0 +} diff --git a/build_tests/llvm/two.ll b/build_tests/llvm/two.ll new file mode 100644 index 0000000..b51fd4d --- /dev/null +++ b/build_tests/llvm/two.ll @@ -0,0 +1,9 @@ +@str = private unnamed_addr constant [12 x i8] c"hello again\00" + +declare i32 @puts(ptr nocapture) nounwind + +define i32 @two() +{ + call i32 @puts(ptr @str) + ret i32 0 +} diff --git a/lib/rscons.rb b/lib/rscons.rb index b0d38b4..9a09e3c 100644 --- a/lib/rscons.rb +++ b/lib/rscons.rb @@ -156,6 +156,7 @@ require_relative "rscons/builders/lang/asm" require_relative "rscons/builders/lang/c" require_relative "rscons/builders/lang/cxx" require_relative "rscons/builders/lang/d" +require_relative "rscons/builders/lang/llvm_asm" # Unbuffer $stdout $stdout.sync = true diff --git a/lib/rscons/builders/lang/llvm_asm.rb b/lib/rscons/builders/lang/llvm_asm.rb new file mode 100644 index 0000000..e825473 --- /dev/null +++ b/lib/rscons/builders/lang/llvm_asm.rb @@ -0,0 +1,10 @@ +Rscons::Builders::Object.register( + command: "${LLVMAS_CMD}", + direct_command: "${LLVMAS_CMD:direct}", + suffix: "${LLVMAS_SUFFIX}", + short_description: "Assembling") +Rscons::Builders::SharedObject.register( + command: "${LLVMAS_CMD}", + direct_command: "${LLVMAS_CMD:direct}", + suffix: "${LLVMAS_SUFFIX}", + short_description: "Assembling") diff --git a/lib/rscons/default_construction_variables.rb b/lib/rscons/default_construction_variables.rb index d03159d..aa8aa7a 100644 --- a/lib/rscons/default_construction_variables.rb +++ b/lib/rscons/default_construction_variables.rb @@ -58,6 +58,11 @@ module Rscons "LIBPATH" => [], "LIBS" => [], "LIBSUFFIX" => ".a", + "LLVMAS" => "clang", + "LLVMAS_CMD" => %w[${LLVMAS} -c -o ${_TARGET} ${LLVMAS_FLAGS} ${_SOURCES}], + "LLVMAS_CMD:direct" => %w[${LLVMAS} -o ${_TARGET} ${LLVMAS_FLAGS} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}], + "LLVMAS_FLAGS" => [], + "LLVMAS_SUFFIX" => ".ll", "OBJDUMP" => "objdump", "OBJSUFFIX" => %w[.o], "PROGSUFFIX" => on_windows ? ".exe" : "", diff --git a/spec/build_tests_spec.rb b/spec/build_tests_spec.rb index 82c3e61..8d592ab 100644 --- a/spec/build_tests_spec.rb +++ b/spec/build_tests_spec.rb @@ -3408,4 +3408,22 @@ EOF end end + it "supports building LLVM assembly files with the Program builder" do + test_dir "llvm" + result = run_rscons + expect(result.stderr).to eq "" + expect(result.status).to eq 0 + expect(File.exist?("llvmtest.exe")).to be_truthy + expect(`./llvmtest.exe`).to match /hello world/ + end + + it "supports building LLVM assembly files with the Program builder in direct mode" do + test_dir "llvm" + result = run_rscons(args: %w[-f direct.rb]) + expect(result.stderr).to eq "" + expect(result.status).to eq 0 + expect(File.exist?("llvmtest.exe")).to be_truthy + expect(`./llvmtest.exe`).to match /hello again/ + end + end