This code doesn't do what you think it does. Here are some of the issues:
The first is noted above by el supremo, so I won't belabor it.
The function definitionvoid shiftleft(int tbs, int shiftamount){
shows that the input value tbs is passed by value. That means that the final value of tbs will be discarded when the function exits. When you send x to shiftleft(), x doesn't change. There are a few ways to fix it:
One: Change the function definition to return a byte, add a line to the function to return the final value of tbs, and assign the return value of the function to x in loop().
Two: Using C conventions, change the function definition and the call to pass tbs / x by reference, like this:void shiftleft(int* tbs, int shiftamount){
and change the references to tbs to *tbs. That passes the address of tbs to the function, and the function then operates on the value that the address points to, and stores the results when it terminates.
Three: Using C++ conventions, change the function definition to pass tbs by reference, and, except as noted below, leave the rest of the code alone, like this:void shiftleft(int &tbs, int shiftamount){
That tells the compiler that tbs will be an address rather than a value, and C++ will treat is that way throughout the function.
I like the C conventions better, because it's always clear to me what kind of objects the function arguments really are. The C++ convention seems to obfuscate that information, in my view. But, I learned C first, so that may just reflect my bias.
You'll need to make sure that x and tbs are the same type to pass by reference. The compiler treats various kinds of integer data as compatible when they're passed by value, but seems to insist on a strict match when they're passed as pointers.
The variable newbyte isn't initialized in the function. Because it's a local automatic variable, it won't be initialized to zero, and it will have whatever value was lying around in memory when the function executes. That will garble the final value. I think that you want to set the value of newbyte to zero when you declare it, but I'm not sure.
The function reads bits from tbs, and it writes bits to tbs. The only things it writes to newbyte are zeros, so, if you initialize newbyte to zero, it will always be zero. I think that you intended to read from tbs, and write to newbyte. But, I'm not sure.
When I make all those corrections, the code seems to work.
I think that you're laboring under the misconception that leading zeros somehow disappear when they're shifted. It may be that all you need is a routine to print a number in binary that shows leading zeros. Serial.print() doesn't show them. I think that you could write a routine that prints bitRead() of the leftmost bit, and works its way down to the least significant bit, printing bitRead() of each in turn. I think, but can't tell for sure, that you'd be satisfied with the results. Then you could just use the operator <<.