Browse Source

src: Fix the syscall intrinsic code generation for Linux and Windows

The old assembly generated for the syscall intrinsic did not specify
clobber constraints.  This adds RCX and R11 (that are clobbered by
the instruction itself), and memory (that is clobbered by some
system calls) to the assembly constraints.

Note: This is still incorrect on FreeBSD, which clobbers more registers
and uses the carry flag instead of -errno in rax to indicate an error.
Yawning Angel 3 years ago
parent
commit
c430a82721
1 changed files with 16 additions and 1 deletions
  1. 16 1
      src/llvm_backend_proc.cpp

+ 16 - 1
src/llvm_backend_proc.cpp

@@ -2002,7 +2002,22 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
 						constraints = gb_string_appendc(constraints, regs[i]);
 						constraints = gb_string_appendc(constraints, "}");
 					}
-					
+
+					// The SYSCALL instruction stores the address of the
+					// following instruction into RCX, and RFLAGS in R11.
+					//
+					// RSP is not saved, but at least on Linux it appears
+					// that the kernel system-call handler does the right
+					// thing.
+					//
+					// Some but not all system calls will additionally
+					// clobber memory.
+					//
+					// TODO: FreeBSD is different and will also clobber
+					// R8, R9, and R10.  Additionally CF is used to
+					// indicate an error instead of -errno.
+					constraints = gb_string_appendc(constraints, ",~{rcx},~{r11},~{memory}");
+
 					inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
 				}
 				break;