1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9/*
10 * @f run_adder
11 * @a The ROX Team
12 * @+ Dynamic Statement Generation Example
13 *
14 * we have a function: adder.generate(target, batch)
15 * that is recognized by this scheduler.
16 * @example
17 * x := 0;
18 * x := adder.generate(10,2)
19 * io.print(x);
20 * @end example
21 * should produce on first iteration
22 * @example
23 * x := 0;
24 * x := calc.+(x,1);
25 * x := calc.+(x,1);
26 * x := adder.generate(8,2)
27 * io.print(x);
28 * @end example
29 * next when generate() is found:
30 * @example
31 * x := calc.+(x,1);
32 * x := calc.+(x,1);
33 * x := adder.generate(6,2)
34 * io.print(x);
35 * @end example
36 * etc, until x = base
37 *
38 */
39/*
40 * @+ Adder implementation
41 * The code below is a mixture of generic routines and
42 * sample implementations to run the tests.
43 */
44#include "monetdb_config.h"
45#include "mal_builder.h"
46#include "opt_prelude.h"
47#include "run_adder.h"
48
49/*
50 * @-
51 * THe choice operator first searches the next one to identify
52 * the fragment to be optimized and to gain access to the variables
53 * without the need to declare them upfront.
54 */
55/* helper routine that at runtime propagates values to the stack */
56static void adder_addval(MalBlkPtr mb, MalStkPtr stk, int i) {
57 ValPtr rhs, lhs = &stk->stk[i];
58 if (isVarConstant(mb,i) > 0 ){
59 rhs = &getVarConstant(mb,i);
60 VALcopy(lhs,rhs);
61 } else {
62 lhs->vtype = getVarGDKType(mb,i);
63 lhs->val.pval = 0;
64 lhs->len = 0;
65 }
66}
67
68str
69RUNadder(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
70{
71 int total;
72 int batch;
73 int size;
74 int i,pc;
75 InstrPtr q, *old;
76 int oldtop;
77
78 (void) cntxt;
79 pc = getPC(mb,p);
80 total = *getArgReference_int(stk,p,1);
81 batch = *getArgReference_int(stk,p,2);
82 if (total == 0) return MAL_SUCCEED;
83
84 old = mb->stmt;
85 oldtop= mb->stop;
86 size = ((mb->stop+batch) < mb->ssize)? mb->ssize:(mb->stop+batch);
87 mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr));
88 if (mb->stmt == NULL) {
89 mb->stmt = old;
90 throw(MAL, "adder.generate", SQLSTATE(HY001) MAL_MALLOC_FAIL);
91 }
92 mb->ssize = size;
93 memcpy( mb->stmt, old, sizeof(InstrPtr)*(pc+1));
94 mb->stop = pc+1;
95
96 if (batch > total) total = batch;
97 for (i=0; i<batch; i++) {
98 /* tmp := calc.+(x,1) */
99 q = newStmt(mb, calcRef, plusRef);
100 getArg(q,0) = getArg(p,0);
101 q = pushArgument(mb, q, getArg(p, 0));
102 q = pushInt(mb, q, 1);
103 adder_addval(mb, stk, getArg(q,2));
104 }
105 total -= batch;
106 *getArgReference_int(stk,p,1) = total;
107 getVar(mb,getArg(p,1))->value.val.ival = total; /* also set in symbol table */
108 if (total > 0) {
109 if ((q = copyInstruction(p)) == NULL) {
110 for(i=0; i<mb->stop; i++)
111 if( mb->stmt[i])
112 freeInstruction(mb->stmt[i]);
113 GDKfree(mb->stmt);
114 mb->stmt = old;
115 throw(MAL, "adder.generate", SQLSTATE(HY001) MAL_MALLOC_FAIL);
116 }
117 pushInstruction(mb, q);
118 }
119 memcpy(mb->stmt+mb->stop, old+pc+1, sizeof(InstrPtr) * (oldtop-pc)-1);
120 mb->stop += (oldtop-pc)-1;
121
122 /* check new statments for sanity */
123 chkTypes(cntxt->usermodule, mb, FALSE);
124 chkFlow(mb);
125 chkDeclarations(mb);
126
127 GDKfree(old);
128 return MAL_SUCCEED;
129}
130