8000 [Question] [Homework 2] implementing &(address) or *(Indirection) in IRGen · Issue #580 · kaist-cp/cs420 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[Question] [Homework 2] implementing &(address) or *(Indirection) in IRGen #580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
7dy109 opened this issue Apr 2, 2025 · 6 comments
Closed
Assignees
Labels
homework - irgen src/irgen/mod.rs question Further information is requested

Comments

@7dy109
Copy link
7dy109 commented Apr 2, 2025

Question Summary : Can I get hints for implementing &(address) or *(Indirection) in IRGen?
I am struggling with 'pointer.c' when making IRGen.
I wanted to implement Address and Indirection unary operation in the function "fn translate unary function(..)"
I thought that how I can implement Address is "if operand is identifier, then use lookup_symbol_table, in the other case, use GetElementPtr" and how I can implement Address is using "Load instruction".

I also tried to modifying "fn translate_expr_rvalue" or "fn translate_expr_lvalue" and using only them, after reading #404
it didn't work.

If I insert pointer.c into the IRGen Model Solution in gg
there comes a IR like this(I posted only the IR of main function)

fun i32 @main () {
init:
  bid: b0
  allocations: 
    %l0:i32:a
    %l1:i32*:p
    %l2:i32**:p2
    %l3:i32*:p3

block b0:
  %b0:i0:unit = store 1:i32 %l0:i32*
  %b0:i1:i32 = load %l0:i32*
  %b0:i2:unit = store %l0:i32* %l1:i32**
  %b0:i3:i32* = load %l1:i32**
  %b0:i4:i32* = load %l1:i32**
  %b0:i5:i32* = load %l1:i32**
  %b0:i6:unit = store %l1:i32** %l2:i32***
  %b0:i7:i32* = load %l1:i32**
  %b0:i8:i32* = load %l1:i32**
  %b0:i9:unit = store %b0:i8:i32* %l3:i32**
  %b0:i10:i32** = load %l2:i32***
  %b0:i11:i32* = load %b0:i10:i32**
  %b0:i12:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i11:i32*)
  %b0:i13:i32 = load %b0:i12:i32*
  %b0:i14:i32** = load %l2:i32***
  %b0:i15:i32* = load %b0:i14:i32**
  %b0:i16:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i15:i32*)
  %b0:i17:i32** = load %l2:i32***
  %b0:i18:i32* = load %b0:i17:i32**
  %b0:i19:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i18:i32*)
  %b0:i20:i32 = load %b0:i19:i32*
  %b0:i21:i32** = load %l2:i32***
  %b0:i22:i32* = load %b0:i21:i32**
  %b0:i23:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i22:i32*)
  %b0:i24:i32 = load %b0:i23:i32*
  %b0:i25:i32 = add %b0:i24:i32 1:i32
  %b0:i26:unit = store %b0:i25:i32 %b0:i16:i32*
  %b0:i27:i32* = load %l3:i32**
  %b0:i28:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i27:i32*)
  %b0:i29:i32* = load %l3:i32**
  %b0:i30:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i29:i32*)
  %b0:i31:i32 = load %b0:i30:i32*
  %b0:i32:i32 = add %b0:i31:i32 1:i32
  %b0:i33:unit = store %b0:i32:i32 %b0:i28:i32*
  %b0:i34:i32 = load %l0:i32*
  %b0:i35:u1 = cmp eq %b0:i34:i32 3:i32
  %b0:i36:i32 = typecast %b0:i35:u1 to i32
  ret %b0:i36:i32

block b1:
  ret 0:i32
}

I think from i1 to i2 is int* p = &a;

from i3 to i6 is int** p2 = &*&p;
from i7 to i9 is int* p3 = *&p;
from i10 to i26 is *&*foo(*p2) += 1;
else part is *foo(p3) += 1;

in the part of from i3 to i6, I cannot understand why load %l1:i32** is implemented 3 times in IR
and, also, in the part of i7~i9, load %l1:i32** is implemented 2 times in IR
This seems unnecessary in the IR.
And also, why that call @foo:[ret:i32* params:(i32*)]*(%b0:i11:i32*) is implemented multiple times?
For my solution and thinking the call expression function would be called once at each sentence.

I cannot see the pattern of & or * when seeing IR or pointer.c

I appreciate TA's effort for this class.

And also, Can I used GetElementPtr when implementing & or * in IRGen?

  1. And also, Can I get information of Midterm exam?
    where to take, when to take, the coverage etc...
@7dy109 7dy109 added the question Further information is requested label Apr 2, 2025
@Lee-Janggun Lee-Janggun added the homework - irgen src/irgen/mod.rs label Apr 2, 2025
@Jaewookim08
Copy link
Collaborator
  1. Sorry, I'm a bit busy at the moment, so I may not be able to answer your question right away. I'll try to get back to you by Sunday. Thank you for your patience.
  2. We do not have a midterm this semester. [Announcement] There will be no midterm exam this semester. #581

@Jaewookim08
Copy link
Collaborator
Jaewookim08 commented Apr 6, 2025

Handling address operations

As explained in #404, the address operator (&) should return a register representing a pointer to the given value. This is exactly what translate_expr_lvalue does, and you can use it directly to implement the address operator.

You may want to revisit the Lvalue chapter in the instruction videos.

if operand is identifier, then use lookup_symbol_table, in the other case, use GetElementPtr

This logic is handled in translate_expr_lvalue. Specifically, you'll generate a GetElementPtr instruction for member expressions (&struct.member, &pointer->member) and array indexing (&arr[ind], part of binary operations). Most other expressions—like binary operations (excluding indexing), conditionals, and constants—result in temporaries without memory addresses and don't need to be handled.

Handling indirection operations

I can implement Address is using "Load instruction".

Correct. Indirection can be implemented simply by inserting a load instruction.

About the model solution output of pointer.c

Note: You can comment out parts of the source file to observe which sections are translated into which IR.

I think from i1 to i2 is int* p = &a;
from i3 to i6 is int** p2 = &*&p;
from i7 to i9 is int* p3 = *&p;

That's all correct.

The unused loads exist because the model solution's translation of unary operators always generates IR to compute the operand's value, even when unnecessary. Since most unary operations (+a, -a, ...) require operand evaluation, the same logic is applied to &a, triggering a load to compute the value of a. This simplifies the compiler implementation, but you don't have to follow this approach. You can generate IR without these lines and still pass the test. The same applies to the redundant foo calls.

I might make a patch to the model solution to reduce redundant IR code. I'll let you know if I do.

In later assignments, the compiler will be able to remove such unused code.

@Jaewookim08
Copy link
Collaborator
Jaewookim08 commented Apr 6, 2025

In fact, I think the model solution having more foo calls (induced by both & and +=) is an error, since foo may have side effects. I'll fix this shortly.

@7dy109
Copy link
Author
7dy109 commented Apr 7, 2025

I tried translate_expr_lvalue for implementing address operator before uploading this issue, but It didn't work.
So, I thought that it was because of translate_unary_op. but It was actually because of translate_binary_op (BinaryOperator::AssignPlus)..
I was uncertain that it is correct way to implement this.
Thanks to your clarification, I could be sure that using translate_expr_lvalue is correct way to implement address operator.

Thank you for very kind answer and clarification !!! I really appreciated it.
After TA fixes gg's model solution, I'll close this issue.
If you want to close this issue before that, close this issue please...!

@Jaewookim08
Copy link
Collaborator

We have updated the model solution (#584). The current model output for pointer.c is:

block b0:
  %b0:i0:unit = store 1:i32 %l0:i32*
  %b0:i1:unit = store %l0:i32* %l1:i32**
  %b0:i2:unit = store %l1:i32** %l2:i32***
  %b0:i3:i32* = load %l1:i32**
  %b0:i4:unit = store %b0:i3:i32* %l3:i32**
  %b0:i5:i32** = load %l2:i32***
  %b0:i6:i32* = load %b0:i5:i32**
  %b0:i7:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i6:i32*)
  %b0:i8:i32 = load %b0:i7:i32*
  %b0:i9:i32 = add %b0:i8:i32 1:i32
  %b0:i10:unit = store %b0:i9:i32 %b0:i7:i32*
  %b0:i11:i32* = load %l3:i32**
  %b0:i12:i32* = call @foo:[ret:i32* params:(i32*)]*(%b0:i11:i32*)
  %b0:i13:i32 = load %b0:i12:i32*
  %b0:i14:i32 = add %b0:i13:i32 1:i32
  %b0:i15:unit = store %b0:i14:i32 %b0:i12:i32*
  %b0:i16:i32 = load %l0:i32*
  %b0:i17:u1 = cmp eq %b0:i16:i32 3:i32
  %b0:i18:i32 = typecast %b0:i17:u1 to i32
  ret %b0:i18:i32

Let us know if you encounter any other issues!

@7dy109
Copy link
Author
7dy109 commented Apr 7, 2025

Thank you for your help!
I really appreciate it!!!
I'll close this issue.

@7dy109 7dy109 closed this as completed Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
homework - irgen src/irgen/mod.rs question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants
0