Difference between `byref` and passing pointer?

Thanks to your guys help I think I’ve got a good implementation for passing Pascal strings to functions. Here’s what I have so far, which does what I want, passes the string by pointer so it can accept strings of different lengths and the makes a copy in the callee so it can mutate the memory without mutating the callers reference to the string.

Now, there is a possibility the param can be constant and thus I don’t need the extra copy using byval. Passing the pointer directly seems to accomplish this but I also read there is a byref attribute which sounds like it does the same thing, so my question what really is the purpose of this and is it preferred over passing the pointer directly?

From the docs:

  The byref argument attribute allows specifying the pointee memory type of an argument. 
  This is similar to byval, but does not imply a copy is made anywhere, or that the argument is 
  passed on the stack. This implies the pointer is dereferenceable up to the storage size of the type.

  It is not generally permissible to introduce a write to an byref pointer. 
  The pointer may have any address space and may be read only.

Sounds like what I want, but also it sounds like a normal pointer so I’m confused what its purpose is.

What my implementation looks like so far. Does this look correct?

define void @PrintMessage(ptr byval([255 x i8]) %0) {
entry:
  %index = getelementptr inbounds [255 x i8], ptr %0, i8 0, i8 1
  store i8 120, ptr %index, align 1
  ret void
}

define i8 @main() {
entry:
  store [12 x i8] c"hello world\00", ptr @s, align 1
  call void @PrintMessage(ptr @s)
  %0 = call i32 (ptr, ...) @printf(ptr @s)
  %1 = load i8, ptr @"$result", align 1
  ret i8 %1
}