blob: a7e79438cb2027b3c89c548d5b3861fe02cdeca7 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
//
// This file contains the implementations for ::preCodeGen and ::codeGen
// for the item expression subclasses related to flow control. This
// currently includes ItmDoWhileFunction, ItmBlockFunction,
// ItmPersistentExpressionVar and ItmWhileFunction.
//
// Includes
//
#include "ItemExpr.h"
#include "ItmFlowControlFunction.h"
#include "Generator.h"
#include "GenExpGenerator.h"
#include "exp_clause_derived.h"
// ItmDoWhileFunction::preCodeGen
//
// Nothing to do in preCodeGen for DoWhile.
//
ItemExpr *ItmDoWhileFunction::preCodeGen(Generator *generator) {
return ItemExpr::preCodeGen(generator);
}
// ItmDoWhileFunction::codeGen
//
// The DoWhile function executes the code represented by child(0) until
// the condition represented by child(1) becomes false. The result of
// the DoWhile is the final value of child(0).
//
// The looping is accomplished by inserting a NOOP/BRANCH pair. The NOOP
// is inserted before generating the code for either child and serves as a
// branch target. The BRANCH is inserted after generating the code for
// both children and is targeted at the NOOP clause based on the result of
// child(1). Between the NOOP and the BRANCH the body of the loop (child(0))
// and the termination condition (child(1)) are repeatedly evaluated. After
// the branch the final result of the loop body is assigned as the result
// of the DoWhile.
//
short ItmDoWhileFunction::codeGen(Generator * generator) {
// Get local handles...
//
Attributes **attr;
Space* space = generator->getSpace();
CollHeap *wHeap = generator->wHeap();
ExpGenerator *exp = generator->getExpGenerator();
// If this DoWhile has already been codeGenned, then bug out...
// Otherwise, allocate space for the result if necessary and set
// attr[0] to point to the result attribute data. Also, mark this
// node as codeGenned.
//
if (exp->genItemExpr(this, &attr, 2, 0) == 1)
return 0;
// Insert the NOOP clause to use as the branch target for the
// start of the loop body.
//
ex_clause * branchTarget = new(space) ex_noop_clause();
exp->linkClause(this, branchTarget);
// CodeGen the body of the loop.
//
child(0)->codeGen(generator);
// The result of the DoWhile is the result of the body of the loop. Set
// the src attribute for the convert (added below) to be the body of
// the while loop. The dst attribute has already been set in genItemExpr().
//
attr[1] = generator->getMapInfo
(child(0)->castToItemExpr()->getValueId())->getAttr();
// CodeGen the loop termination condition.
//
child(1)->codeGen(generator);
// Construct a BRANCH clause to loop back and repeat the expression
// and condition if the condition evaluates to TRUE.
//
Attributes ** branchAttrs = new(wHeap) Attributes*[2];
Attributes *boolAttr = generator->getMapInfo
(child(1)->castToItemExpr()->getValueId())->getAttr();
branchAttrs[0] = boolAttr->newCopy(wHeap);
branchAttrs[1] = boolAttr->newCopy(wHeap);
// branchAttrs[0]->copyLocationAttrs(boolAttr);
// branchAttrs[1]->copyLocationAttrs(boolAttr);
branchAttrs[0]->resetShowplan();
ex_branch_clause * branchClause
= new(space) ex_branch_clause(ITM_OR, branchAttrs, space);
branchClause->set_branch_clause(branchTarget);
// Insert the branch clause into the expression.
//
exp->linkClause(this, branchClause);
// Allocate a convert clause to move the result from child(0) to the
// result of this node. This move is necessary so that future
// side-effects of the result of child(0) -- if it is a local variable,
// for instance -- will not change the result of the DoWhile.
//
ex_conv_clause * convClause =
new(generator->getSpace()) ex_conv_clause
(getOperatorType(), attr, space);
exp->linkClause(this, convClause);
return 0;
}
// ItmBlockFunction::preCodeGen
//
// Nothing to do in preCodeGen for Block.
//
ItemExpr *ItmBlockFunction::preCodeGen(Generator *generator) {
return ItemExpr::preCodeGen(generator);
}
// ItmBlockFunction::codeGen
//
// The Block function executes the code represented by both its children and
// then returns the result of the right child (child(1)).
//
short ItmBlockFunction::codeGen(Generator * generator) {
// Get local handles...
//
Attributes **attr;
Space* space = generator->getSpace();
CollHeap *heap = generator->wHeap();
ExpGenerator *exp = generator->getExpGenerator();
// If this Block has already been codeGenned, then bug out...
// Otherwise, allocate space for the result if necessary and set
// attr[0] to point to the result attribute data. Also, mark this
// node as codeGenned.
//
if (exp->genItemExpr(this, &attr, 2, 0) == 1)
return 0;
// CodeGen the left child.
//
child(0)->codeGen(generator);
// CodeGen the right child.
//
child(1)->codeGen(generator);
// The result of the Block is the result of the right child. Set
// the src attribute for the convert (added below) to be the right child
// The dst attribute has already been set in genItemExpr().
//
attr[1] = generator->getMapInfo
(child(1)->castToItemExpr()->getValueId())->getAttr();
// Allocate a convert clause to move the result from child(1) to the
// result of this node. This move is necessary so that future
// side-effects of the result of child(1) -- if it is a local variable,
// for instance -- will not change the result of the Block.
//
ex_conv_clause * convClause =
new(generator->getSpace()) ex_conv_clause
(getOperatorType(), attr, space);
generator->getExpGenerator()->linkClause(this, convClause);
return 0;
}
// ItmPersistentExpressionVar::codeGen
//
// Adds the persistent variable to the expression generator.
//
short ItmPersistentExpressionVar::codeGen(Generator * generator) {
// If the variable has already been codeGenned, bug out...
//
MapInfo * mi = generator->getMapInfoAsIs(getValueId());
if (mi && mi->isCodeGenerated()) return 0;
// Otherwise, generate the code and add it to the map table.
//
generator->getExpGenerator()->addPersistent(getValueId(),
generator->getMapTable());
// Add the initial value to the persistent list in the ExpGenerator.
//
generator->getExpGenerator()->linkPersistent(this);
// ok...
//
return 0;
}
// ItmWhileFunction::preCodeGen
//
// Nothing to do in preCodeGen for While.
//
ItemExpr *ItmWhileFunction::preCodeGen(Generator *generator) {
return ItemExpr::preCodeGen(generator);
}
// ItmWhileFunction::codeGen
//
// The While function is for loops that must have their condition evaluated
// before any executions of the body.
//
// The While function evaluates the condition represented by child(1) and if it is true
// it executes the code represented by child(0). The loop is repeated as long as
// child(1) is true. The result of the While is the final value of child(0).
//
// The looping is accomplished by inserting a NOOP/unconditional BRANCH pair, and a
// NOOP/BRANCH pair. The unconditional branch is evaluated only once and branches
// immediately to the loop condition for evaluation.
// The NOOPs are inserted before generating the code for each child and serve
// as branch targets for the loop branch and the undonditional brnach, repsecitevly.
// Between the first NOOP and the BRANCH the body of the loop (child(0))
// and the termination condition (child(1)) are repeatedly evaluated.
//
// Before code gen:
//
// child(0) <--- loop body
// child(1) <--- loop condition
//
// After Code gen:
//
// -----<-unconditional branch
// | |
// | --->branchTarget (noop)
// | | |
// | | child(0) <--- loop body
// | | |
// - -|-> branchTarget2 (noop)
// | |
// --<-child(1) <--- loop condition
//
short ItmWhileFunction::codeGen(Generator * generator) {
// Get local handles...
//
Attributes **attr;
Space* space = generator->getSpace();
CollHeap *wHeap = generator->wHeap();
ExpGenerator *exp = generator->getExpGenerator();
// If this While has already been codeGenned, then bug out...
// Otherwise, allocate space for the result if necessary and set
// attr[0] to point to the result attribute data. Also, mark this
// node as codeGenned.
//
if (exp->genItemExpr(this, &attr, 2, 0) == 1)
return 0;
// Insert the unconditional branch to evaluate the condition
// before entering the loop.
//
ex_branch_clause * startBranchClause
= new(space) ex_branch_clause(ITM_RETURN_TRUE, space);
exp->linkClause(this, startBranchClause);
// Insert the NOOP clause to use as the branch target for the
// start of the loop body.
//
ex_clause * branchTarget = new(space) ex_noop_clause();
exp->linkClause(this, branchTarget);
// CodeGen the body of the loop.
//
child(0)->codeGen(generator);
// The result of the While is the result of the body of the loop. Set
// the src attribute for the convert (added below) to be the body of
// the while loop. The dst attribute has already been set in genItemExpr().
//
attr[1] = generator->getMapInfo
(child(0)->castToItemExpr()->getValueId())->getAttr();
// Insert the NOOP clause to use as the branch target for the
// unconditional branch to the loop condition.
//
ex_clause * branchTarget2 = new(space) ex_noop_clause();
exp->linkClause(this, branchTarget2);
// CodeGen the loop termination condition.
//
child(1)->codeGen(generator);
// Construct a BRANCH clause to loop back and repeat the expression
// and condition if the condition evaluates to TRUE.
//
Attributes ** branchAttrs = new(wHeap) Attributes*[2];
Attributes *boolAttr = generator->getMapInfo
(child(1)->castToItemExpr()->getValueId())->getAttr();
branchAttrs[0] = boolAttr->newCopy(wHeap);
branchAttrs[1] = boolAttr->newCopy(wHeap);
// branchAttrs[0]->copyLocationAttrs(boolAttr);
// branchAttrs[1]->copyLocationAttrs(boolAttr);
branchAttrs[0]->resetShowplan();
ex_branch_clause * branchClause
= new(space) ex_branch_clause(ITM_OR, branchAttrs, space);
branchClause->set_branch_clause(branchTarget);
//
// set the target of the unconditional branch to be the branch clause
//
startBranchClause->set_branch_clause(branchTarget2);
// Insert the branch clause into the expression.
//
exp->linkClause(this, branchClause);
// Allocate a convert clause to move the result from child(0) to the
// result of this node. This move is necessary so that future
// side-effects of the result of child(0) -- if it is a local variable,
// for instance -- will not change the result of the While.
//
ex_conv_clause * convClause =
new(generator->getSpace()) ex_conv_clause
(getOperatorType(), attr, space);
exp->linkClause(this, convClause);
return 0;
}