-
Notifications
You must be signed in to change notification settings - Fork 166
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
Do not load CPtr #2440
Do not load CPtr #2440
Conversation
This seems to be the correct fix for the concerned program
But fails for |
Consider the following
The above change would disturb this simple block that works on master. I think there's a type mismatch happens while storing elements into the
The error
|
I tried some workarounds to support both but unfortunately both the cases contradict each other. |
The failure file has the following relevant ASR (after all passes): l1:
(Variable
3
l1
[]
Local
()
()
Default
(List
(CPtr)
)
()
Source
Public
Required
.false.
),
...
(=
(Var 3 l1)
(ListConstant
[(Var 3 stack0)]
(List
(CPtr)
)
)
()
) We are assigning a list of CPtr. The ASR looks correct, but the generated code is incorrect. A similar test with ints: def test_extraction_of_elements():
l1: list[i32] = [5]
test_extraction_of_elements() Produces l1:
(Variable
3
l1
[]
Local
()
()
Default
(List
(Integer 4)
)
()
Source
Public
Required
.false.
)
...
[(=
(Var 3 l1)
(ListConstant
[(IntegerConstant 5 (Integer 4))]
(List
(Integer 4)
)
)
()
)] And the corresponding LLVM is: define void @__module___main___test_extraction_of_elements() {
.entry:
%l1 = alloca %list, align 8
%0 = call i8* (i32, ...) @_lfortran_malloc(i32 4)
%1 = bitcast i8* %0 to i32*
%2 = getelementptr %list, %list* %l1, i32 0, i32 2
store i32* %1, i32** %2, align 8
%3 = getelementptr %list, %list* %l1, i32 0, i32 0
store i32 0, i32* %3, align 4
%4 = getelementptr %list, %list* %l1, i32 0, i32 1
store i32 1, i32* %4, align 4
%const_list = alloca %list, align 8
%5 = call i8* (i32, ...) @_lfortran_malloc(i32 4)
%6 = bitcast i8* %5 to i32*
%7 = getelementptr %list, %list* %const_list, i32 0, i32 2
store i32* %6, i32** %7, align 8
%8 = getelementptr %list, %list* %const_list, i32 0, i32 0
store i32 1, i32* %8, align 4
%9 = getelementptr %list, %list* %const_list, i32 0, i32 1
store i32 1, i32* %9, align 4
%10 = getelementptr %list, %list* %const_list, i32 0, i32 2
%11 = load i32*, i32** %10, align 8
%12 = getelementptr inbounds i32, i32* %11, i32 0
store i32 5, i32* %12, align 4
%13 = getelementptr %list, %list* %const_list, i32 0, i32 0
%14 = load i32, i32* %13, align 4
%15 = getelementptr %list, %list* %const_list, i32 0, i32 1
%16 = load i32, i32* %15, align 4
%17 = getelementptr %list, %list* %l1, i32 0, i32 0
%18 = getelementptr %list, %list* %l1, i32 0, i32 1
store i32 %14, i32* %17, align 4
store i32 %16, i32* %18, align 4
%19 = getelementptr %list, %list* %const_list, i32 0, i32 2
%20 = load i32*, i32** %19, align 8
%21 = mul i32 4, %16
%22 = call i8* (i32, ...) @_lfortran_malloc(i32 %21)
%23 = bitcast i8* %22 to i32*
%24 = bitcast i32* %23 to i8*
%25 = bitcast i32* %20 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %24, i8* %25, i32 %21, i1 false)
%26 = getelementptr %list, %list* %l1, i32 0, i32 2
store i32* %23, i32** %26, align 8
br label %return
return: ; preds = %.entry
ret void
} And that works. This is to be compared with CPtr: %25 = call i8* (i32, ...) @_lfortran_malloc(i32 %24)
%26 = bitcast i8* %25 to void**
%27 = bitcast void** %26 to i8*
%28 = bitcast void** %23 to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %27, i8* %28, i32 %24, i1 false)
%29 = getelementptr %list, %list* %l1, i32 0, i32 2
store void** %26, void*** %29, align 8
%30 = load void*, void** %stack0, align 8
call void @basic_free_stack(void* %30)
br label %return The line In master, it works: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %28, i8* %29, i32 %25, i1 false)
%30 = getelementptr %list, %list* %l1, i32 0, i32 2
store void** %27, void*** %30, align 8
%31 = load void*, void** %stack0, align 8
call void @basic_free_stack(void* %31)
br label %return |
ptr_loads = 0; | ||
} else { | ||
ptr_loads = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue here is that if x.m_args[i]
is an argument, then we want ptr_loads=0
, but if it is pi
(as in the other example), where it is a local (or global) variable, we want ptr_loads = 1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to keep ptr_loads = 1;
for all other types as well as for CPtr if it is a local/global variable. Only if it is CPtr and a function argument, then we want to use ptr_loads = 0;
.
Good:
bad:
|
bool is_argument = false; | ||
ASR::expr_t *var = x.m_args[i]; | ||
if (is_a<ASR::Var_t>(*var)) { | ||
ASR::symbol_t *var_sym = ASR::down_cast<ASR::Var_t>(var) | ||
->m_v; | ||
if (is_a<ASR::Variable_t>(*var_sym)) { | ||
ASR::Variable_t *v = down_cast<ASR::Variable_t>(var_sym); | ||
if (v->m_intent == intent_local || | ||
v->m_intent == intent_return_var || | ||
!v->m_intent) { | ||
is_argument = false; | ||
} else { | ||
is_argument = true; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole code here should be refactored into a function that should be put into ASRUtils. We might already have a function for this.
Fix the above comment, and add a test. |
The solution in this commit should be simplified.
ed35dd0
to
84d73e7
Compare
I lack some experience working on shared branches but I was aware of how to use a branch (as in use the commits from it) and then build on top of it and finally raise a PR for the same. Hence I ended making #2453 which works as expected |
I now realized why even after pushing on the same branch, it created a new PR.
I realized long back but I made the switch just today to something like
And though I can use my previous branches, github would end up creating a new branch out of then as I switched my origin. Luckily I don't have lot of open branches :) |
Just use |
No description provided.