On Sun, May 19, 2019 at 5:22 AM Andreas Schwab <sch...@linux-m68k.org> wrote: > ../../../libgo/go/runtime/mbitmap.go: In function > ‘runtime.setMarked.runtime.markBits’: > ../../../libgo/go/runtime/mbitmap.go:291:9: internal compiler error: > Segmentation fault > 291 | atomic.Or8(m.bytep, m.mask) > | ^
This is failing for RISC-V because __atomic_or_fetch_1 isn't a built-in function that can be expanded inline. You have to call the library function in libatomic. The C front-end is registering all of the built-in functions, but it looks like the go front-end is only registering functions it thinks it needs and this list is incomplete. In expand_builtin, case BUILT_IN_ATOMIC_OR_FETCH_1, the external library call for this gets set to BUILT_IN_ATOMIC_FETCH_OR_1. Then in expand_builtin_atomic_fetch_op when we call builtin_decl_explicit (ext_call) it returns NULL. This is because the go front end registered BUILT_IN_ATOMIC_OR_FETCH_1 as a built-in, but did not register BUILT_IN_ATOMIC_FETCH_OR_1 as a built-in. The NULL return from builtin_decl_explicit gives us an ADDR_EXPR with a NULL operand which eventually causes the internal compiler error. It looks like the same thing is done with all of the op_fetch built-ins, so use of any of them means that the fetch_op built-in also has to be registered. I verified with a quick hack that I need both BUILT_IN_ATOMIC_FETCH_OR_1 and BUILT_IN_ATOMIC_FETCH_AND_1 defined as built-ins to make a RISC-V go build work. I haven't done any testing yet. Jim
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 1b26f2bac93..91043b51463 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -871,6 +871,8 @@ Gcc_backend::Gcc_backend() NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", NULL, t, false, false); + this->define_builtin(BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL, + t, false, false); t = build_function_type_list(unsigned_char_type_node, ptr_type_node, @@ -879,6 +881,8 @@ Gcc_backend::Gcc_backend() NULL_TREE); this->define_builtin(BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, t, false, false); + this->define_builtin(BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, + t, false, false); } // Get an unnamed integer type.