Conversation
|
|
||
| // Check fstatat returned 0 | ||
| EXPECT_EQ(getGeneralRegister<int64_t>(27), 0); | ||
| EXPECT_EQ(getGeneralRegister<int64_t>(21), 0); |
There was a problem hiding this comment.
@FinnWilkinson @jj16791 I think this test was checking the wrong register. Can you double check?
There was a problem hiding this comment.
If we are wanting to check the newfstatat register, then it sould be 21 yeah. My sme branch has register 21 being checked though so unsure when this happened...
| stateChange.memoryAddressValues.push_back(RegisterValue( | ||
| reinterpret_cast<const uint8_t*>(out.data()), outSize)); |
There was a problem hiding this comment.
The reinterpret_casting throughout this function is alarming and requires further investigation
There was a problem hiding this comment.
Personally I think RegisterValue should have proper move semantics and you should be able to create a blank register of some size and move it into the vector
|
|
||
| // Write data for this buffer in 128-byte chunks | ||
| auto iSrc = reinterpret_cast<const char*>(buffers[i].data()); | ||
| auto iSrc = reinterpret_cast<const uint8_t*>(buffers[i].data()); |
There was a problem hiding this comment.
Not sure about this one
There was a problem hiding this comment.
Comments same as AArch exception handler
| // TODO avoid malloc and copy altogether | ||
| uint8_t* data = (uint8_t*)malloc(size); | ||
| aggrReq->data.getAsVector<char>().copyTo(data, size); | ||
|
|
There was a problem hiding this comment.
Could have a member buffer but not sure what size?
| reinterpret_cast<uint8_t*>(memData.data()), memData.size() * sizeof(uint64_t)); | ||
| index++; | ||
| memData.clear(); | ||
| } | ||
| } | ||
| // Check if final data needs putting into memoryData_ | ||
| if (memData.size() > 0) { | ||
| memoryData_[index] = RegisterValue((char*)memData.data(), | ||
| memoryData_[index] = RegisterValue(reinterpret_cast<uint8_t*>(memData.data()), |
There was a problem hiding this comment.
Could be dangerous
There was a problem hiding this comment.
Reinterpret casts throughout need to be checked for safety
ABenC377
left a comment
There was a problem hiding this comment.
Looks good. A couple of general questions (more for my own understanding than anything else).
|
|
||
| for (int i = 0; i < I; i++) { | ||
| if (isXtn2 & (i < (I / 2))) { | ||
| assert(isXtn2 && "isXtn2 is false so d is not initialised"); |
There was a problem hiding this comment.
Will this assert ever fail? If isXtn2 & anything is true, wont isXtn2 always be true?
There was a problem hiding this comment.
This is layover from when I was having issues previously. No harm in keeping it but happy to remove. Your call
There was a problem hiding this comment.
I think get rid of it, as it doesn't do anything and so might cause momentary confusion for someone reading this bit of code in the future.
| assert(response->data && "unhandled failed read in exception handler"); | ||
| uint8_t bytesRead = response->target.size; | ||
| const uint8_t* data = response->data.getAsVector<uint8_t>(); | ||
| uint8_t* data = (uint8_t*)malloc(bytesRead); |
There was a problem hiding this comment.
Create a block-scoped std::vector<uint8_t> and copy to that instead of malloc/free
| memcpy(dest, ptr, bytes); | ||
| } | ||
|
|
||
| void copyTo(void* dest, const size_t bytes, const uint64_t offset) { |
There was a problem hiding this comment.
This method should be const too?
| stateChange.memoryAddressValues.push_back(RegisterValue( | ||
| reinterpret_cast<const uint8_t*>(out.data()), outSize)); |
There was a problem hiding this comment.
Personally I think RegisterValue should have proper move semantics and you should be able to create a blank register of some size and move it into the vector
| uint8_t bytesRead = response->target.size; | ||
| const uint8_t* data = response->data.getAsVector<uint8_t>(); | ||
| // TODO clean up malloc | ||
| uint8_t* data = (uint8_t*)malloc(bytesRead); |
There was a problem hiding this comment.
See comment about using scoped vector
| initialStackFrame.push_back(commandLine_.size()); // argc | ||
| for (size_t i = 0; i < commandLine_.size(); i++) { | ||
| char* argvi = commandLine_[i].data(); | ||
| uint8_t* argvi = reinterpret_cast<uint8_t*>(commandLine_[i].data()); |
There was a problem hiding this comment.
use auto on lhs if rhs is reinterpret_cast
| return "+sve,+lse"; | ||
| #elif SIMENG_LLVM_VERSION < 18 | ||
| return "+sve,+lse,+sve2,+sme,+sme-f64"; | ||
| return "+sve,+lse,+sve2,+sme,+sme-f64,+sme-i64"; |
There was a problem hiding this comment.
Should this be part of the PR?
| #include <algorithm> | ||
| #include <cassert> | ||
| #include <cstring> | ||
| #include <iostream> |
| struct safePointer { | ||
| public: | ||
| explicit safePointer(const uint8_t* ptr) : ptr(ptr) {} | ||
| explicit safePointer() : ptr(nullptr) {} |
There was a problem hiding this comment.
do we need a null safePointer? Is it still safe if calling anything on it is UB? also, might want to assert in the ctor above if the build is debug
Fixes #426 among other errors.
Add a safe pointer struct to remove undefined behaviour caused by reinterpret casting in the
RegisterValue. The safe pointer hides the underlying pointer toRegisterValuedata. This enforces immutability and fixes UB by converting unsafereinterpret_casts to safememcpys.