diff --git a/lib/cext/include/ruby/internal/intern/time.h b/lib/cext/include/ruby/internal/intern/time.h index 1d23fc27410a..32f5337e415f 100644 --- a/lib/cext/include/ruby/internal/intern/time.h +++ b/lib/cext/include/ruby/internal/intern/time.h @@ -142,15 +142,7 @@ void rb_tr_time_timeval(VALUE time, struct timeval *result); * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. * @return A struct that represents the identical time to `num`. */ -#ifdef TRUFFLERUBY -static inline struct timeval rb_time_timeval(VALUE time) { - struct timeval result; - rb_tr_time_timeval(time, &result); - return result; -} -#else struct timeval rb_time_timeval(VALUE time); -#endif #ifdef TRUFFLERUBY void rb_tr_time_timespec(VALUE time, struct timespec *result); @@ -163,15 +155,7 @@ void rb_tr_time_timespec(VALUE time, struct timespec *result); * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. * @return A struct that represents the identical time to `num`. */ -#ifdef TRUFFLERUBY -static inline struct timespec rb_time_timespec(VALUE time) { - struct timespec result; - rb_tr_time_timespec(time, &result); - return result; -} -#else struct timespec rb_time_timespec(VALUE time); -#endif /** * Identical to rb_time_interval(), except for return type. diff --git a/lib/cext/include/truffleruby/truffleruby-abi-version.h b/lib/cext/include/truffleruby/truffleruby-abi-version.h index f8e9f8e4395a..b97f6cb1741d 100644 --- a/lib/cext/include/truffleruby/truffleruby-abi-version.h +++ b/lib/cext/include/truffleruby/truffleruby-abi-version.h @@ -20,6 +20,6 @@ // $RUBY_VERSION must be the same as TruffleRuby.LANGUAGE_VERSION. // $ABI_NUMBER starts at 1 and is incremented for every ABI-incompatible change. -#define TRUFFLERUBY_ABI_VERSION "3.2.2.10" +#define TRUFFLERUBY_ABI_VERSION "3.2.2.11" #endif diff --git a/src/main/c/cext/time.c b/src/main/c/cext/time.c index 140b1a1e47f0..8577a969daa8 100644 --- a/src/main/c/cext/time.c +++ b/src/main/c/cext/time.c @@ -43,6 +43,20 @@ void rb_tr_time_timespec(VALUE time_val, struct timespec *result) { result->tv_nsec = polyglot_as_i64(RUBY_INVOKE_NO_WRAP(time, "tv_nsec")); } +// Only used with --cexts-sulong +struct timeval rb_time_timeval(VALUE time) { + struct timeval result; + rb_tr_time_timeval(time, &result); + return result; +} + +// Only used with --cexts-sulong +struct timespec rb_time_timespec(VALUE time) { + struct timespec result; + rb_tr_time_timespec(time, &result); + return result; +} + VALUE rb_time_timespec_new(const struct timespec *ts, int offset) { void* is_utc = rb_tr_unwrap(rb_boolean(offset == INT_MAX-1)); void* is_local = rb_tr_unwrap(rb_boolean(offset == INT_MAX)); diff --git a/test/truffle/cexts/no_timespec/bin/no_timespec b/test/truffle/cexts/no_timespec/bin/no_timespec new file mode 100755 index 000000000000..7b162eda03b9 --- /dev/null +++ b/test/truffle/cexts/no_timespec/bin/no_timespec @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby + +require 'no_timespec/no_timespec' diff --git a/test/truffle/cexts/no_timespec/expected.txt b/test/truffle/cexts/no_timespec/expected.txt new file mode 100644 index 000000000000..10ddd6d257e0 --- /dev/null +++ b/test/truffle/cexts/no_timespec/expected.txt @@ -0,0 +1 @@ +Hello! diff --git a/test/truffle/cexts/no_timespec/ext/no_timespec/extconf.rb b/test/truffle/cexts/no_timespec/ext/no_timespec/extconf.rb new file mode 100644 index 000000000000..567b264b9dc9 --- /dev/null +++ b/test/truffle/cexts/no_timespec/ext/no_timespec/extconf.rb @@ -0,0 +1,3 @@ +require 'mkmf' +$CFLAGS += ' --std=c99' +create_makefile('no_timespec') diff --git a/test/truffle/cexts/no_timespec/ext/no_timespec/no_timespec.c b/test/truffle/cexts/no_timespec/ext/no_timespec/no_timespec.c new file mode 100644 index 000000000000..ab3ae8dee3a6 --- /dev/null +++ b/test/truffle/cexts/no_timespec/ext/no_timespec/no_timespec.c @@ -0,0 +1,9 @@ +// Include time.h before ruby.h, this has the effect together with --std=c99 to not define struct timespec +#include +#include + +void Init_no_timespec() { + // This would fail but what we want to test is that including ruby.h works in this situation + // struct timespec t; + printf("Hello!\n"); +} diff --git a/test/truffle/cexts/no_timespec/lib/no_timespec/.keep b/test/truffle/cexts/no_timespec/lib/no_timespec/.keep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tool/generate-cext-trampoline.rb b/tool/generate-cext-trampoline.rb index f7b360d66463..56a535330970 100755 --- a/tool/generate-cext-trampoline.rb +++ b/tool/generate-cext-trampoline.rb @@ -32,6 +32,11 @@ rb_tr_not_implemented ] +RETURN_STRUCT_BY_VALUE = { + 'rb_time_timeval' => 'rb_tr_time_timeval', + 'rb_time_timespec' => 'rb_tr_time_timespec', +} + type_regexp = /\b(?:(?:const|unsigned|volatile|struct|enum)\s+)*\w+\b(?:\s+const)?(?:\s*\*+\s*)?/ function_pointer_arg_regexp = /\b\w+\s*\(\*(\w+)\)\s*\([^)]*?\)/ argument_regexp = /\bvoid\b|\.\.\.|#{type_regexp}\s*(\w+)(?:\[\d*\])?|#{function_pointer_arg_regexp}/ @@ -65,7 +70,7 @@ def struct_by_value?(type) if declaration.include? "\n" abort "This declaration includes newlines but should not:\n#{declaration}\n\n" end - if struct_by_value? return_type + if struct_by_value?(return_type) and !RETURN_STRUCT_BY_VALUE.include?(function_name) abort "Returning a struct by value from Sulong to NFI is not supported for:\n#{declaration}" end end @@ -183,12 +188,15 @@ def struct_by_value?(type) f.puts "\n// Functions\n\n" functions.each do |declaration, return_type, function_name, argument_types| + next if RETURN_STRUCT_BY_VALUE.include?(function_name) f.puts "#undef #{function_name}" f.puts "static #{declaration.sub(/\{$/, '').rstrip.sub(function_name, "(*impl_#{function_name})")};" end f.puts functions.each do |declaration, return_type, function_name, argument_types| + next if RETURN_STRUCT_BY_VALUE.include?(function_name) + argument_names = argument_types.delete_prefix('(').delete_suffix(')') argument_names = argument_names.scan(/(?:^|,)\s*(#{argument_regexp})\s*(?=,|$)/o) argument_names = argument_names.map { |full_arg, name1, name2| @@ -237,13 +245,32 @@ def struct_by_value?(type) f.puts end + f.puts <getTruffleContext(env); C functions.each do |declaration, return_type, function_name, argument_types| + next if RETURN_STRUCT_BY_VALUE.include?(function_name) f.puts " impl_#{function_name} = get_libtruffleruby_function(\"#{function_name}\");" end f.puts "}" diff --git a/tool/jt.rb b/tool/jt.rb index 609b22515688..886e948b89c2 100755 --- a/tool/jt.rb +++ b/tool/jt.rb @@ -1415,7 +1415,7 @@ def retag(*args) ALL_CEXTS_TESTS = %w[ tools postinstallhook - minimum module method globals backtraces xopenssl werror stripped + minimum module method globals backtraces xopenssl werror no_timespec stripped oily_png psd_native puma sqlite3 unf_ext json grpc RubyInline msgpack ] @@ -1442,7 +1442,7 @@ def retag(*args) # Test tools run_ruby 'test/truffle/cexts/test_preprocess.rb' - when 'minimum', 'module', 'method', 'globals', 'backtraces', 'xopenssl', 'werror', 'stripped' + when 'minimum', 'module', 'method', 'globals', 'backtraces', 'xopenssl', 'werror', 'no_timespec', 'stripped' # Test that we can compile and run some very basic C extensions output_file = 'cext-output.txt' dir = "test/truffle/cexts/#{test_name}"