-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTodo.xml
More file actions
1802 lines (1514 loc) · 49.8 KB
/
Todo.xml
File metadata and controls
1802 lines (1514 loc) · 49.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="Admin/XSL/Todo.xsl" ?>
<topics xmlns:r="http://www.r-project.org" xmlns:c="http://www.c.org">
<topic>
<title>Tools</title>
<items>
<item>
See tests/forVector.R
Should be able to determine that ctr = 0 is a double since we return ctr and we know the return type.
Should do this in Type Inference.
</item>
<item status="verify">
Check we haven't broken anything else. Fixed getMathOpType to use the @ref pointers for comparing the types.
<br/>
Comparing double to Int32Type
See tests/compareDiffTypes.R
It seems like we end up with two elements in convert.i and so the subsetting vars[[convert.i]] is hierarchical.
<br/>
isIntType is false.
Importantly, targetType is NULL. So neither operand types will match.
So
<r:code>
getMathOpType(types, call[-1])
</r:code>
is responsible.
<br/>
Does this have anything to do with the Int1Type for the return type?
</item>
<item>
Put better names for variables in multiSubset.R
</item>
<item status="done">
Compilation of code in Rllvm/tests/walkblocks.R (the part in the FALSE section) fails.
Seems to have wrong types in the fcmp.
<br/>
Same issue with the enums overloaded for Add and Sub (in this case Sub).
</item>
<item status="done">
The addition instruction isn't being added.
<r:code>
library(RLLVMCompile)
g = function(x, y) x[1] + y[1]
i.ptr = pointerType(Int32Type)#, 0L)
#debug(RLLVMCompile:::mathHandler)
gc = compileFunction(g, Int32Type, list(i.ptr, i.ptr), optimize = FALSE)
showModule(gc)
<r:output><![CDATA[
define i32 @g(i32* readonly %x, i32* readonly %y) {
entry:
%0 = getelementptr i32, i32* %x, i64 0
%1 = load i32, i32* %0
%2 = getelementptr i32, i32* %y, i64 0
%3 = load i32, i32* %2
%"x[1] + y[1]" = ret i32 %1, i32 %3
ret i32 %"x[1] + y[1]"
}
]]></r:output>
</r:code>
<br/>
Enums are overloaded for BinOps and BinaryOps and Add was 1 rather than 11.
</item>
<item>
See getBlockGraph()
<br/>Visualize a module, i.e., the relationships between its blocks, etc.
Allow the user to see the flow and then to click on a block and see the instructions.
</item>
</items>
</topic>
<topic>
<title>Compilation Strategies</title>
<items>
<item>
If code refers to a non-local variable, either capture that variable now
and convert it to a value in the module or insert a call to a routine
to get the variable. We can then generate a routine in the module that
retrieves the current value of the R object from the R interpreter.
<br/>
Add a parameter to compileFunction that controls whether we do this
aggressive capture or lazy lookup at call time.
</item>
<item>
Memory management
</item>
<item>
If a function doesn't modify an input, pass by reference.
</item>
<item>
Deal with closures within a function. Create global variables in the module ?
</item>
<item>
Compile closures with shared state. See R/compileClosures.R
Use RCIndex collectors as examples, or SAX handlers.
First compile the functions, ignoring the global variables and get
them to work.
Use clone() to copy the module for a new instance. In other words,
the call to the generator function is just a call to clone of the
routines.
</item>
<item>
Explore non-standard evaluation.
</item>
</items>
</topic>
<topic>
<title>Code Analysis</title>
<items>
<item status="note">
Started <r:pkg>CodeAnalysis</r:pkg> package. On github too.
</item>
<item status="note">
<r:code>
library(CodeDepends)
library(RLLVMCompile)
sc = new("Script", as.list(body(compileFunction)))
inputs = getInputs(sc)
</r:code>
There are 8 expressions in the function and inputs has 8 elements.
The if() statements, etc. are dealt with as one input and unraveled. So should this be a recursive data structure that gets returned? It is processed recursively, but
the question is whether it should be returned as a recursive data structure.
<br/>
[Check] Need to explore and fix CodeDepends for functions
and in-memory expressions/calls rather than from scripts.
<br/>
Need to turn the expressions into a Script object with new("Script", body(fun)).
That's done.
</item>
<item status="extend">
See constInputs in CodeAnalysis.
<br/>
Identify which inputs/parameters a function doesn't modify.
Can CodeDepends do this for us?
Yes. See explorations/deadVariables.R
<r:code>
sc = readScript("explorations/script.R")
inp = getInputs(sc)
any(sapply(inp, function(node) "x" %in% node@updates)) # true
any(sapply(inp, function(node) "z" %in% node@updates)) # false
</r:code>
</item>
<item status="extend">
See findLoopConcat in CodeAnalysis.
Recognize/identify idioms of the form
<r:code>
x = c()
for(i in z)
x = c(x, f(i))
</r:code>
The key is the declaration of an empty vector and then
concatenating it with a single value.
</item>
</items>
</topic>
<topic>
<title>Callbacks to R</title>
<items>
<!--
<item>
Call R functions from C code.
<br/>
Can construct the expression in the compiled code, if we have access to the routines in R.
Alternatively, compile the R function and just call that.
</item>
-->
<item>
When we can determine that we cannot create the R call object
using create_foo_expression, don't compile that routine.
Also, allow caller to turn this off with an option.
</item>
<item>
What if we have
<r:code>
function(x)
.R(foo(a + x), ...)
</r:code>
Do we substitute the value of x into the expression before calling back to R?
<br/>
Global variables are simply bad. So do we want to support them at all?
It is complicated to walk this expression generally at run-time, i.e. in our compiled code.
(This example is reasonably simple, of course, but generally.)
</item>
<item status="test">
Handle .typeInfo() in getGlobals and ignore.
This also means using getGlobals rather than findGlobals().
And this involves getting the names of the R callable functions, updating them, and so on.
</item>
<item status="test">
Add a .R() to indicate a callback. Add extra information.
See explorations/dotRCallback.R
</item>
<item>
Rather than copying the result back from Rf_eval(),
we could implicitly protect it (i.e. the compiled code would add this) and then unprotect it.
We could identify when the variable is no longer needed
and add code to release it then.
</item>
<item>
Figure out why explorations/conCall.R doesn't give much speed.
</item>
<item status="done">
Fix while loop in conCall.R and then it might work.
</item>
<item status="verify">
When we use R API routines, add their declarations to the module, e.g. R_CHAR, strdup.
</item>
<item>
If we enable the execution engine in compileFunction implicitly, i.e. during the compilation,
can we extract/query it from the Function/module.
i.e. can we do <r:expr>as(Module, "ExecutionEngine")</r:expr>
<br/>
Doesn't seem to be accessible.
</item>
<item status="done">
Variables that we want to find in R are getting promoted to global variables.
See callbacks2.R and pi. Really want to identify that this is a call to an R
function and so variables that are not already declared/defined in the
local function being compiled should be ignored
<br/>
Is this really the case? or is it just that we have pi as a constant.
Yes, this is just pi. But problems with globals.
</item>
<item status="verify">
[callbacks2.R] Named arguments in the call corresponding to local
variables, i.e foo(1, bob, x = a) and we substitute the value of a,
but skip bob. Unfortunately, we use codetools::findGlobals() to find
the globals before we start compiling the code. It finds these in the
R callbacks as these are regular R expressions. So we have to be more
specific than findGlobals and basically find global variables within
each call and then ignore those in R callback functions. We can also
have the caller specify which are R variables and exclude those. This
is not a bad thing to do as it ensures that the caller knows these
must be present in the R session. But it would be nicer to determine
these. So we can adapt codetools or write our own walker. See
R/getGlobals.R.
<item>
Don't include code that is a callback to R in the analysis of global variables and functions.
</item>
<br/>
</item>
<item status="done">
Handle expressions in the call to the R function, e.g. foo(a + 10)
for local variable a.
<br/>
Done for arguments we are filling in, but what about those
we do not provide.
This goes back to needing to be able to get the original call
at compile time and setting that using setCall_foo_expression.
But need it at run-time.
We can collect these as we compile and then when we are finished
compiling all the code, includeing setCall_*_expression, we can
invoke those if we have an ExecutionEngine.
</item>
<item status="done">
Pass SEXP back to R. See callbacks.R
</item>
<item status="done">
callbacks.R not working. Is now.
</item>
<item status="done">
explorations/simpleCallback.R and explorations/conCall.R (FIX this - see above)
</item>
<item status="done">
Get the value of a global variable, specifically the SEXP for the call expression in a callback.
<r:code>
m[["foo_expression", value = TRUE, ee = ee]]
</r:code>
</item>
<item status="done">
Problem with creating the call. Reneable and debug. simpleCallback2.R
<br/>
Needed to convert the elements of the call to their R types by compiling calls to
Rf_ScalarReal, Rf_install(), etc.
</item>
<item status="complete">
Before evaluating the call at run time, insert the local variables in the routine
into to the corresponding positions in the call.
</item>
<item status="done">
Call create_call to create the expression.
<br/>
Need to define it the function first before we can reference it.
Not really, but have to be careful with our compiler when we
reference a function.
</item>
<item status="done">
Protect the call? No need as we have protected it with R_PreserveObject().
If we do, then we have to ensure it is unprotected later.
If called from R, then R will take care of this.
However, if we are doing complicated things in the native code, we may need to catch any error and unprotect.
</item>
<item>
Release the memory for the arguments we added to the particular call.
<br/>
We can add code to set these to R_NilValue.
We can either loop over the call again. Alternatively, we can store the pointers
to set when we walk the first time.
</item>
<item>
[CHECK]
When compiling R expressions in compileCreateCall,
we need to convert literals into calls to ScalarReal, etc.,
i.e. their R objects, not native versions.
Do this when inserting the values into the call, both at run-time and when creating the call.
</item>
<item status="done">
Find way to capture the call at compile time and use it at run-time.
<br/>
Multiple ways.
<ol>
<li>We serialize the call using RDS, store it as a local variable in a routine we compile
and can deserialize by calling that routine.</li>
<li>One can explicitly set the global variable for the expression from within R
either by calling the set_foo_expression routine in the module or by setting the global variable in the module.
To set this, we need the ExecutionEngine. If this is available in the call to <r:func>compileFunction</r:func>,
we set the expression before returning. This is probably the fastest way to do things as we don't have to deserialize.
But that is negligible.
</li>
<li>There is routine that creates the call. This only works in simple cases, i.e.
where there are no arguments in the R call that a) we don't supply, and b) that are complex calls.
In these cases, use either of the other two approaches</li>
</ol>
<br/>
Necessary for complex values that are not local variables.
(Of course, caller could use a closure and call the target function with local variables.)
<br/>
Could embed it in the R wrapper function that then calls set_call.
Alternatively, serialize it into the module and then have an initialization
call or have create_foo_expression deserialize it.
</item>
</items>
</topic>
<topic>
<title>Compiler Structure</title>
<items>
<item>
Consolidate the code in compile.= and call.R for numeric(), etc.
and the isPrimitiveConstructor() and compilePrimitiveConstructor()
and how we rewrite to do the Rf_allocVector in call.R
</item>
<item status="high">
Create a class and constructor to represent the compiler.
(Maybe a reference class).
Then allow this to be reused to compile different functions.
</item>
<item status="done">
Function for resetting the compiler to start new Function, new block,
clear local variables.
<br/>
compilerStartFunction
</item>
<item status="high">
Rather than having the createLoopCode() check to see if
compile.if (or any other compile method) has made the incrBlock
the current insertion block. If it has, then createLoopCode needs to avoid
adding the branch instruction. But really, the other methods should try to
aoid changing the insertion block except into blocks that they created.
<br/>
Same for while that has a break.
</item>
<item>
Check if statement with a continue/next/break inside a loop works correctly.
See inst/examples/repeat.R
</item>
<item>
Really want to be able to distinguish between REALSXPType and INTSXPType, etc.
i.e. not all just SEXPType and same pointer.
<br/>
Sort out a mechanism for dealing with more specific SEXP types
and not matching the types when calling functions with more
specific types.
</item>
<item>
Consolidate the 2 getLimits functions.
</item>
<item status="low">
Think about introducing a run-time package, e.g. RLLVMCompileRT
with C routines to support the generated code, i.e. that the generated code can call.
Since the idea is to use the code immediately in the session
in which we compile it, this code can be in RLLVMCompile itself.
</item>
<item>
Add structured errors to the compiler to identify user errors, compiler errors.
<br/>
See call.R@86 and WrongNumArgs error.
</item>
</items>
</topic>
<topic>
<title>General</title>
<items>
<item>
Deal with calls on LHS of an assignment:
<c:code>
INTEGER(ans)[i] = 2
</c:code>
Arises in Rllvm/explorations/sapply.R
</item>
<item>
In sapply(), deal with strings potentially being passed as CHARSXP to the function being applied
to each element. If it is expecting a char * (i.e., StringType), then we need to access that pointer
before the call.
<br/>
Do we do this in rewriteSApply() or when we compile the resulting expression? Probably the latter.
</item>
<item>
Add Block graph diagrams to show control flow.
And allow the text to flow around these if they are small.
</item>
<item>
<r:code>
fc = compileFunction(function(x, y) x^y, Int32Type, list(Int32Type, Int32Type))
</r:code>
fails because pow is declared for double types.
This works
<r:code>
fc = compileFunction(function(x, y) x^y, DoubleType, list(DoubleType, DoubleType))
</r:code>
</item>
<item status="done">
tests/multiCondIf.R doesn't work. Can't find <![CDATA[&&]]>.
This is missing from <r:func>getCompilerHandlers</r:func>,
as is || and | and &.
<br/>
This is compiled. But the problem is something else.
We end up in the <r:func>createConditionCode</r:func> code.
<br/>
The <r:func>insertReturn</r:func> doesn't seem to be putting the return in the correct place
and that is the problem for the code below:
<r:code><![CDATA[
f = function(x, y) { if(x < y && x > y/2) 3 else 4}
gc = compileFunction(f, Int32Type, list(DoubleType, DoubleType))
]]></r:code>
The following works
<r:code><![CDATA[
gc = compileFunction(function(x, y) { if(x < y && x > y/2) return(3) else return(4)}, Int32Type, list(DoubleType, DoubleType), .insertReturn = FALSE)
]]></r:code>
</item>
<item>
Does the compile.for have to move the counter incrementing code to a separate Block if
there is just a break in the body of the loop, but not a next?
Seems like we could branch to the nextBlock on a break, but still increment the code
at the end of the loop otherwise.
</item>
<item status="no">
Add comments to the code to make it easier to understand.
Can't do it. Use metadata in the IR. But we can't add comments in the IR.
</item>
<item status="finish">
Write functions to visualize the blocks and the jumps.
Create a graph and then use Rgraphviz or igraph to render it.
<br/>
See showBlocks.R and getBlockGraph()
</item>
<item status="high">
Add calls to Rf_protect and Rf_unprotect appropriately in the compiler.
Possibly need to add an .on.exit to the compiler which will generate code
in the final block.
Also, add a counter for the number of protects for cases where it is deterministic at compile time.
</item>
<item status="done">
tests/convolve.R doesn't do the looping correctly.
It goes into an infinite loop. Are we testing the wrong llen variables?
Do we introduce these erroneously since we already have na and nb.
Or are we merging the setup for the two loops (the initialization one for the result, and the actual one that does that the convolution).
<br/>
Problem is that the branch for the <xml:tag>i in 1:na</xml:tag> loop goes to the body or
back to the after <xml:tag>for(k in 1:n)</xml:tag> block which starts things all over again.
So setting the next block is incorrect.
We don't seem to be processing the return expression.
<br/>
We needed to set the afterBlock to NULL after we pop it.
<br/>
Seems like we have the after k block is left on the stack when we enter compiling the i loop.
<br/>
Is it that we initialize i = 1 for the second loop and then branch in that block ("after k....")
<br/>
[No] Is it that we use i in both loops?
</item>
<item status="done">
Get the compilation of a vectorization function of a scalar working.
See vec.R and makeVectorized.R
</item>
<item>
Use CXCursor example (or XML parsing) example to use a customized subsetting
operation, i.e. <r:expr>cursor[[1]]</r:expr> to mean <r:expr>children(x)[[1]]</r:expr>
and in fact to map that to a more explicit function that calculates this.
Currently it does this in RCIndex by visiting all the nodes.
</item>
<item status="done">
For asFunction = TRUE in compileFunction, add ... to the formals of the
function.
</item>
<item status="check">
Fix while loops the way we did for the for() loops,
i.e. nextBlock, nextIterBlock and so on.
</item>
<item status="done">
for() loop with a break doesn't break.
Related to the nextBlock changes we made.
Jump to the incr. block since that is nextBlock.
Need a breakBlock.
<br/>
See tests/forBreak.R
</item>
<item status="done">
Simple if statement is broken!!!
<br/>
See tests/realSimpleIf.R
Problem is that there is no return value in the function and so no
expression following the if statement. Now we get an error.
</item>
<item>
See if we can recover in tests/realSimpleIf.R when return type is VoidType.
See if.R@100
<item>
Handle cases where R doesn't return anything explicitly, i.e. just NULL implicitly, but we need
a particular type, e.g. an integer in
<r:code><![CDATA[
foo = function(x) if(x < 10) 100L
]]></r:code>
At least identify these for the person calling compile and ask for a default
value. <r:na/> can work for certain types.
<br/>
See insertReturn in utils.R.
This will work for simple cases. But not for cases with if, while,
for. Here we will have to jump out of those local blocks and then return
from the routine. So we will need to change the code that would return to assign to a
fixed variable (e.g. .return) and then jump to the end block
</item>
<item>
Check for return - lacking return causes Rllvm to hardcrash, i.e.
<r:code>
function(x) {
if (!x)
return(3L)
}
</r:code>
</item>
</item>
<item status="done">
Make getGlobals() try to understand lazy evaluation, i.e. not evaluating the
default values for formal parameters until they are fist used.
We could do this by rewriting to add the <r:expr>if(missing(x)) x = expr</r:expr>.
<br/>
See substituteDefaultValues() and tests/getGlobals.R
</item>
<item status="done">
Add .debug(), .assert() to indicate conditional code.
</item>
<item>
support testthat and stopifnot and so on for assertions.
</item>
<item status="done">
supress the warning message in callHandler when we invoke mapply()
but the number of targetTypes is less than the number of elements in the call.
This happens, for example, in a varargs routine, e.g.
<r:expr>printf("x = %d, y = %d\n", x, y)</r:expr>
where we have x and y w/o type information.
</item>
<item status="done">
For .assert() and friends, allow a class = c("a", "b")
and then call R_raiseStructuredError().
Need to figure out how to create an array of strings as a global variable.
See err.cpp and the C++ code LLVM generates to do this.
For now, use va_arg.
<br/>
See tests/structuredAssert.R.
</item>
<item status="done">
Raise richer exceptions in the run-time code. Provide a mechanism to specify the classes to raise.
Use stop() or Stop() if not compatible.
See tests/structuredStop.R
</item>
<item status="done">
How to make the global native variable in R R_GlobaEnv
available to the module.
AddSymbol? declare it locally?
<br/>
Seem to need $address rather than just getNativeSymbolInfo().
</item>
<item status="finish">
(Need to pass .targetType down the call stack.)
<br/>
Fix calls of the form foo(1) where 1 is supposed to be Int32Type.
When we know the expected type and have a literal, make it so!
<br/>
tests/checkIntLiteral.R
<br/>
See callHandler and <r:expr>lapply(as.list(call[-1]), compile, .......)</r:expr>
We should put the type information here.
Then we'd have to add, say, a .targetType parameter to each.
</item>
<item status="low">
Generate error or warning when use a wrong variable.
This is not possible, in general.
<br/>
If we change r_ans to rans in callRFunction.R on the LHS of the Rf_eval,
then we just get the wrong answer.
It is legitimate as we created the local variable (why did we need it?)
</item>
<item status="done">
Extend globalCallSEXP.R to process the return value.
<br/>
Now we print it as an R object, and convert it to an int and then print it via LLVM.
</item>
<item status="done">
Get the globalCallSEXP.R sorted out.
Problem with Rcall variable not being resolved.
But the code in globalArray.R does work.
The Rcall declaration has an "external" qualifier.
Is this because it is a pointer? because it has no initializer?
The latter, so use ConstantPointerNull.
</item>
<item status="done">
Compile <r:expr>if(x != NULL)</r:expr>
Type information for NULL.
tests/nullComparison.R
<br/>
See logicOpHandler.R
</item>
<item status="done">
Element subsetting with a data frame.
See dataFrameSubset.R
</item>
<item>
Matrix subsetting for VECSXType. Less common.
</item>
<item status="done">
matrix subsetting for STRSXPType,
Need to add the same sort of code in SEXP.R to multiSubset.R
<br/>
tests/matrixSubset.R
</item>
<item status="done">
Recognize x[i] for a SEXPType and change this to be work on x.els and
compute the pointer first as a local variable.
</item>
<item>
Recognize to compile <r:expr>sapply(v, `[[`, 1)</r:expr>,
i.e. to rewrite this either as a loop over v and insert
<r:expr>el[[i]]</r:expr> or to rewrite this as
<r:expr>sapply(v, function(x) x[[1]])</r:expr>.
The former is nicer as it is essentially inlining the body of the function.
</item>
<item status="done">
Doug Bate's Rgibbs example is giving NaNs
</item>
<item status="done">
[Done but see above]Compile Doug Bate's Rgibbs example
<br/>
It involves matrix subset assignment, and combining values on the RHS of the assignment.
<br/>
Assignment seems to work and looping fine. But the values we get are NaN.
First few are not, but then they go nuts.
</item>
<item>
Add optional bounds checking on <r/> objects when subsetting.
Allow the caller to add hints to the compiler to say check these variables, but not these.
Also, develop static analysis to identify which ones go over bounds, if possible.
<item>
Add an option to perform/eliminate bounds checking on arrays, nrow, ncol, etc.
</item>
<item>inbounds for accessing elements of an array.
Rllvm now has isInBounds methods to query and set.
</item>
</item>
<item status="done">
Test subsetting with a list(). Simple accessing an element. Then assign to an element.
Need to know the type of the element unless we use run-time information.
<br/>
See list2.R
<br/>
Try
<r:code>
x = replicate(N, list(a = 2, b = 3))
sapply(x, function(x) x[[1]])
</r:code>
Don't use names ("a"), but position.
</item>
<item status="done">
Need a SEXP type for lists.
<br/>
Use VECSXPType. Same as getSEXPType("VEC").
</item>
<item status="verify">
[Works now] Error in insertReturn when expecting a return value but none
<r:code>
f = function(x, i) { el = x[[i]]}
fc = compileFunction(f, Int32Type, list(SEXPType, Int32Type))
</r:code>
</item>
<item status="verify">
Constant folding.
Arises in matrix subsetting in SEXP.R around line 60 when we create 2L - 1L.
We know this is 1L.
For 1L -1L convert this to 0 but recognize that we don't have to do the multiplication.
Also, When one operand in multiplication is 1, don't do the multiplication.
When adding, if one of the operands is 0, don't do the addition.
</item>
<item>
When doing constant folding elimination for arithmetic, i.e. remove a mult/dv or an add/sub since it is the same value,
we need to eliminate/remove the previously compiled instructions.
<br/>
We may want to compile the operands sequentially and check after the first one to see if it or the second one is necessary,
in contrast to lapply() to compile them both and then examine.
</item>
<item status="done">
Eliminate dead code. Does LLVM do this for us?
See explorations/deadCodeElim.R.
<br/>
Yes, LLVM can clean up for us with a pass.
<br/>
Is this a case where a compiler pass would be useful.
</item>
<item status="done">
Access a matrix cell.
See tests/checkToIntSubset.R
And check explorations/matrixElAssign.Rdb
</item>
<item status="done">
When doing arithmetic such as 2 - 1L, recognize that the 2 is an integer value
(not type). Add parameter/flag to compile for arithmetic to say make the result an integer.
When computing the index for subsetting, we'd activate this.
So in <r:expr>x[2, i]</r:expr> we want 2 - 1L to be an integer.
<br/>
See tests/checkToIntSubset.R
</item>
<item status="high">
Compute the REAL(x) pointer just once for a matrix.
See matrixElAssign.Rdb.
Similarly, compute Rf_nrow(), etc. just once.
But detect if the value could change.
<br/>
When we have a REALSXPType and access its elements,
create a local variable and initialize it with a call to REAL().
Then use that in place of the REALSXPType variable.
</item>
<item status="high">
Handle the <r:expr>pragma(IfAssign, var, updatedExpressions)</r:expr>
</item>
<item status="check">
Handle assignments from RHS being if-else
<r:code>
z = if(cond) val1 else val2
</r:code>
See 2DRandomWalk.Rdb.
<br/>
Either have the assignment determine that the RHS is complicated
or have the RHS's compile method return information about the two branches.
In either case, this <r:expr>assignHandler = `compile.=` = </r:expr>
method for the compiler needs to understand that this is special and requires
modifying the code. (Same for ifelse).
Need to ensure the types from the two branches are the same.
<br/>
IMPORTANT: we have the ifAssign.R file for rewriting if statements.
[Done] FIX THIS: see inst/examples/ifAssign.R and specifically bar.
And export these functions and use them in compile.
Also, we may want to "declare" variable before the if. But don't know its type there.
But we can go back and set it
</item>
<item status="high">
getBlocks() seg faults.
2DRandomWalk.Rdb in the if handler.
</item>
<item status="news">
Do we have functions in Rllvm to get the current block, i.e. the block with the insertion point?
Yes getInsertBlock()
</item>
<item>
Why are we exiting out of R when a module is not valid? Would like to get an error in R.
See 2DRandomWalk.Rdb.
</item>
<item status="done">byval for parameters when passing a struct object directly to a routine. explorations/clangHandler2.R
<br/>
See call.R::callHandler. Need to determine which argument has a byval attribute.
How do we query this?
<r:code>
arg = mod$clang_CXCursor_getName[[1]]
hasByValAttr(arg)
</r:code>
But it appears we don't need to set this if the declaration of the Function
has this information.
</item>
<item status="verify">
In tests/structByVal.R, if we don't have the return(2L), we get an error about no terminator.
<br/>
This seems to work again. But I saw it in globalArrayAccessors.R once after this.
So perhaps some memory problem in Rllvm.
</item>
<item>
What is .vectorize doing? Does it actually generate vectorized code.
</item>
<item>
tests/ with a XXX or a FIX
vectorize.R character3.R
<br/>
Fixed: structByVal.R globalArrayAccessors.R
</item>
<item>
Add a mechanism to differentiate between integer()
meaning INTSXPType or Int32Type in R code.
<br/>
See explorations/list2.R for one example.
</item>
<item>
Test the other code now that we switched load = TRUE for subsetHandler
</item>
<item status="done">
Compile rw2d
<br/>
See tests/2DRandomWalk.Rdb
<br/>
Didn't we do this for the StatSci paper? Yes, but manually.
</item>
<item>
Compile vectorized fibonacci (Rllvm/explorationts/fib.R)
and compare with closed form solution approach.
</item>
<item>
handle case of serial assignment
<r:code>
xpos = ypos = numeric(n)
</r:code>
to ensure create a new vector.
Do we do this for the SEXP types, i.e. call Rf_duplicate() when assigning? No.
See tests/serialAssign.R.
So need to recognize that assigning a SEXP to a SEXP needs to duplicate to
respect the R semantics.
</item>
<item>
Get native version of nrow(), ncol() that don't
use a SEXP.
Can implement directly ourselves as C routines.
Nice to compile them however.
</item>
<item>
When we call any of the constructor functions, i.e. numeric(), etc.
protect the result and unprotect them at the end.
</item>
<item status="done">
Allocate the variables within a loop outside of the loop just once.
<br/>
Could be smarter about this. Currently doing it for ever variable.
But only needs to be done for a loop.