How to change a pointers address?

When creating a variable with llvm::GlobalVariable, this will result in a pointer, which of course requires me to use load/store to access/write it’s value.

Let’s say I’m creating two global variables A and B.
Now I want to have a third variable C, which dynamically can reference A or B at runtime and also change, what it references at runtime. So I can directly use a load/store operation on C to access the value of A or B (depending on what it currently references).

Or would C need to be a Pointer, which would result in a pointer to a pointer, since global variables are pointers. But then I would have to, always use a load operation, to dereference the pointers address and then have another load/store operation to read/write the actual referenced value. This possible seems as if this would be unnecessary overhead?

Maybe I’m completely off or missing something here?

One way to do this would be to implement the runtime behavior in C. You can implement your logic in a C function in a separate C file and use it as your ‘run-time library’.
You will insert calls to this function in the LLVM-IR and pass the pointers (LLVM Global Variables) you want to manipulate to this function. You can then link your ‘run-time library’ and transformed code to get the final executable.
See this: https://www.cs.cornell.edu/~asampson/blog/llvm.html#:~:text=Linking%20With%20a%20Runtime%20Library

Or would C need to be a Pointer, which would result in a pointer to a pointer, since global variables are pointers.

You can insert a global variable of same type as your variable A and B in LLVM-IR, and pass it to the function just like it’s mentioned above.

Sorry, I probably didn’t explain it well enough.

I’m doing stuff with the variables in llvm already, I was just wondering, since a pointer points to a memory address, if it at all was possible to change that address it points to.
This is probably a misconception on my part and a pointer always points to a specific address and I won’t be able to change the address it points to?

Here is a some code to illustrate what I’m trying to do:

auto variableA = new llvm::GlobalVariable(
        context,
        llvm::Type::getInt32Ty(context),
        false,
        llvm::GlobalValue::ExternalLinkage,
        llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0),
        "variable1"
);

auto variableC = // How to make this to point to the same address as variableA does? (if even possible?)

// The other solution I can think of, would be to have a pointer pointer, which points to variableA,
// but then to read/store to tis variable i would have to first create a load for the pointer to variableA,
// and then again to load/store the variable itself. Which i kind of would want to avoid.
auto variableD = new llvm::GlobalVariable(
        context,
        llvm::PointerType::get(llvm::Type::getInt32Ty(context), 0),
        false,
        llvm::GlobalValue::ExternalLinkage,
        variable1_pointer,
        "variableD"
);

Maybe what I’m trying to do is not even possible or I’m missing something here, but it seems to be a little bit of overhead to have a pointer to a pointer, especially to have to do two loads just to get the actual value?

Hope this helps for clarification! :slight_smile:

Ok so I think I probably got the answer to it, by just emitting the LLVM IR from a c++ application.

C++ file:

int variableA;
int variableB;
int variableC;
int *pointer;

int main() {
    variableA = 3000;
    variableB = 6000;

    pointer = &variableA;
    variableC = *pointer;

    pointer = &variableB;
    variableC = *pointer;
}

LLVM IR

@variableA = dso_local global i32 0, align 4
@variableB = dso_local global i32 0, align 4
@variableC = dso_local global i32 0, align 4
@pointer = dso_local global ptr null, align 8

; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
define dso_local noundef i32 @main() #0 {
  store i32 3000, ptr @variableA, align 4
  store i32 6000, ptr @variableB, align 4
  store ptr @variableA, ptr @pointer, align 8
  %1 = load ptr, ptr @pointer, align 8
  %2 = load i32, ptr %1, align 4
  store i32 %2, ptr @variableC, align 4
  store ptr @variableB, ptr @pointer, align 8
  %3 = load ptr, ptr @pointer, align 8
  %4 = load i32, ptr %3, align 4
  store i32 %4, ptr @variableC, align 4
  ret i32 0
}

So it appears, that the 2nd one is the case, where a pointer to a pointer is required, which then requires two load operations to load. Guess there is no way around that?

I think that’s right if C has to be a global. But if the value (the ptr to A or B) is only needed within main, it can be in %C, being a ptr. Maybe select the value of %C from A or B with IR select. But yes if you are going to store the ptr somewhere, I think that location will be a ptr ptr.