Add support for the `freeze` instruction
dpaoliello opened this issue · 2 comments
Looking at LLVM IR for some Rust code, I noticed the freeze
instruction that LLVM-CBE doesn't currently support: https://llvm.org/docs/LangRef.html#freeze-instruction
I've been thinking about how we should handle this, but have run into a few issues:
- I'm not sure how to write a trivial C/C++ program that emits this instruction.
- I'm not sure how to indicate to a C compiler how to copy an undef/poison value and NOT mark the new value as undef/poison - could we use
memcpy
or a "black box" function that duplicates the value?
Is it actually possible to express this in C at all? I think undefined behaviours in C are global.
Is it actually possible to express this in C at all? I think undefined behaviours in C are global.
I'm not sure.
One option is to avoid undef and poison values altogether, for example we could always initialize variables, thus freeze
becomes a no-op.
If I'm reading cppref correctly, there we may be able to safely access it via a char*
.
From https://en.cppreference.com/w/c/language/initialization
objects with automatic storage duration are initialized to indeterminate values (which may be trap representations)
From https://en.cppreference.com/w/c/language/object
If an object representation does not represent any value of the object type, it is known as trap representation. Accessing a trap representation in any way other than reading it through an lvalue expression of character type is undefined behavior. The value of a structure or union is never a trap representation even if any particular member is one.
I do have a test for this now, unfortunately it doesn't seem like casting to char*
helped...
// Compile with clang -S test.c -emit-llvm -O3
#include <string.h>
#include <stdio.h>
int main(int argc, char** argv) {
int i;
int j /* = freeze i */;
// Insert "freeze" operation here...
char* tmp = (char*)&i;
memcpy(&j, tmp, sizeof(int));
// If j is correctly frozen, then k and j must have the same value.
int k = j;
// If j isn't frozen, then printf is called with `i32 undef, i32 undef`
printf("%d, %d", j, k);
return 0;
}