blob: 261e0eca17bc335f441e9b4e83d097ea7f863244 [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 @@@
**********************************************************************/
/* -*-C++-*-
****************************************************************************
*
* File: ExpPCode.h
* Description:
*
* Created: 8/25/97
* Language: C++
*
*
*
****************************************************************************
*/
#ifndef ExpPCode_h
#define ExpPCode_h
// ExpPCode.h (PCodeInstructionMap, PCode)
//
// PCodeInstruction and PCI list classes
//
#include "ExpPCodeInstruction.h"
#include "ExpPCodeList.h"
#include "exp_tuple_desc.h"
// This pcode version number is attached to the beginning of the pcode byte
// code. Checking of version compatibility is done at fixup time
// Increment this counter everytime pcode instructions are added/deleted/
// modified. PCode is now stored on disk, so we need to know whether the
// current executables can be used with the pcode stored in previously-
// compiled user programs
#define PC_eyeCatcher "PC 1"
#define PC_eyeCatcherSize 4 // number of BYTES
#define PC_fillerSize 16 //for a total of 16 * sizeof(Int32) bytes filler
//Opcode map defines
#define OPCODE_MAP_FIRSTSIX_BITS 0x000000000000003F
/* #ifdef NA_DEBUG_C_RUNTIME
#ifdef _DEBUG
#ifdef _EID
#if !defined(NA_NSK)
#define DEBUG_PCODE
#endif // NA_WINNT
#else // _EID
#define DEBUG_PCODE
#endif // _EID
#endif // _DEBUG
#endif */
#ifdef NA_DEBUG_C_RUNTIME
#include <stdio.h>
#endif
struct pc_eye_catcher {
char name_[4];
};
// Internal forward declarations
//
class PCode;
struct PCodeInstructionMap;
// External forward declarations
//
// Attributes - Pointers to Attributes appear in the function declarations
// of the helper functions that are used to generate PCode for common
// operations (i.e. loadValue, loadNullInd, etc). These functions must access
// the Attributes class to figure out what PCI's to perform.
//
// Space - Pointers to space apprear in the function declarations
// of the helper functions that are used to generate PCode for common
// operations (i.e. loadValue, loadNullInd, etc). These functions must use
// the Space object to allocate space for the PCI's that are stored with
// clauses and expressions.
//
class ex_clause;
class Attributes;
// RMI reduction typedef's
//
typedef PCodeInstructionMap PCIMap;
#ifndef uLong
#define uLong ULng32
#endif
// PCodeInstructionMap
//
// The PCodeInstructionMap class is used to hold pairs of corresponding
// instructions and opcodes. This class purposely operates like a structure.
// All of the members are public and only convenient constructors are
// provided.
//
struct PCodeInstructionMap {
public:
Int64 instruction;
Int32 opcode;
const char * opcodeString;
Int32 length;
Int32 numAmodes;
};
//#if defined( __EID ) && defined( NA_NSK )
//#pragma class_functions PCodeInstructionMap (resident)
//#endif
// class PCodeSegment
//
// this class contains the actual byte code
#pragma warning ( disable : 4251 )
class SQLEXP_LIB_FUNC PCodeSegment : public NAVersionedObject {
public:
PCodeSegment(PCodeBinary* pcode = 0);
PCodeBinary *getPCodeBinary() {return (PCodeBinary*)pCodeSegment_.getPointer();}
void setPCodeBinary(PCodeBinary* pcode) {pCodeSegment_ = pcode;}
// Takes pointer out of PCodeBinary sequences
// Now a macro, see exp/ExpPCodeInstruction.h
// Long getPCodeBinaryAsPtr(PCodeBinary *pcode, Int32 idx)
// Adds pointer to PCodeBinary sequences and advance idx
Int32 setPtrAsPCodeBinary(PCodeBinary *pcode, Int32 idx, Long ptr)
{
#ifdef NA_64BIT
*(Long*)&(pcode[idx]) = ptr;
#else
pcode[idx] = (PCodeBinary) ptr;
#endif
return (sizeof(ptr)/sizeof(PCodeBinary));
}
unsigned char getClassVersionID();
void populateImageVersionIDArray() {
setImageVersionID(0, getClassVersionID());
}
// Checks version of pcode byte string, not PCodeSegment object.
NABoolean versionOK () { return (str_cmp (eyeCatcher_.name_, PC_eyeCatcher, PC_eyeCatcherSize) == 0); }
Int32 getPCodeSegmentSize();
void setPCodeSegmentSize(Int32 size);
short getClassSize();
Long pack(void *);
Lng32 unpack(void *, void * reallocator);
void replaceAttributesPtr(ex_clause* clauses, Space* space);
void replaceClauseEvalPtr(ex_clause* oldClause, ex_clause* newClause);
//change all the addresses embedded in PCode to offsets for packing
void convAddrToOffsetInPCode(void *space);
//reverse
void convOffsetToAddrInPCode(void *base);
NABoolean containsClauseEval() { return (flags_ & CONTAINS_CLAUSE_EVAL) != 0; };
void setContainsClauseEval(NABoolean v)
{
(v ? flags_ |= CONTAINS_CLAUSE_EVAL : flags_ &= ~CONTAINS_CLAUSE_EVAL);
}
private:
enum
{
// if set, indicates that there is atleast one clause_eval
// pcode instruction. A clause_eval pcode instr is evaluated
// by called a non-pcode ex_clause::eval method at runtime.
CONTAINS_CLAUSE_EVAL = 0x0001
};
pc_eye_catcher eyeCatcher_; // 00-03
UInt32 flags_; // 04-07
Int32 filler_[PC_fillerSize]; // 08-71
Int32 pCodeSegmentSize_; // 72-75
char fillerPCodeSegmentSize_[4]; // 76-79
Int32Ptr pCodeSegment_; // 80-87
};
#pragma warning ( default : 4251 )
// PCode
//
// The PCode class is used to hold a list of PCode Instructions (PCIs). The
// PCI's typically represent the code for either a single clause
// (exp_clause) or an expression (exp_expr) which has a list of clauses.
// PCode encapsulates access to the PCI's and also a set of helper functions
// which perform common operations such as generating code for loading
// attributes or NULL indicators. In addition, the PCode class has minimal
// support for storing profile information associated with a list of PCI's.
//
// Most of the helper functions are static member functions and don't need
// direct access to a PCode object. They are included in the PCode class
// in order to provide one-stop shopping and a uniform name space for the
// functions that operate on PCI's.
//
//
class SQLEXP_LIB_FUNC PCode {
public:
// Construction/Destruction
//
PCode(CollHeap *heap, Space *space);
~PCode();
// Manipulating the PCodeInstruction List
//
void setPCIList(PCIList pciList) { pciList_ = pciList; };
PCIList getPCIList() { return pciList_; };
// Accessors
//
Int32 size();
static PCIT::Instruction getInstruction(PCI *pci);
const PCIMap &getMapEntry (Int32 i);
static Int32 getOpCodeMapElements(Int32 opcode,
PCIT::Operation &operation,
PCIT::AddressingMode am[],
Int32 &numAModes);
static Int32 isInstructionRangeType( PCIT::Instruction instruction);
// Generating byte code
//
PCodeBinary * generateCodeSegment(Int32 length,
Int32 *atpCode,
Int32 *atpIndexCode,
Int32 *codeSize);
// Translating PCI's to ID's and vice versa. Each PCI is identified
// by a unique ID. Currently, this is simply the address of the PCI.
// This works because the PCI's are ALWAYS manipulated on non-intrusive
// lists which refer to the PCI's by pointer and the PCI's are allocated
// from a Space object which doesn't garbage collect.
//
static PCIID getId(PCI *pci) { return (PCIID)pci; };
static PCI* getPCI(PCIID pciId) { return (PCI*)pciId; };
// Profiling
//
Int32 profileInit();
Int32 profilePrint();
Int32 isProfilingOn() { return profileCounts_ != 0; };
Int32 *profileCounts() { return profileCounts_; };
Int32 *profileTimes() { return profileTimes_; };
static Int32 IsBranchOrTarget(PCI *);
static Int32 IsTemporaryStore(PCI *);
static Int32 IsTemporaryLoad(PCI *);
static Int32 IsTemporaryAccess(PCI *);
static Int32 ComputeTemporaryAccess(PCI *, Int32&, int&, Int32);
static Int32 IsBranchInstruction(PCI *);
static Int32 IsTargetInstruction(PCI *);
static Int32 IsClauseEvalInstruction(PCI *);
static Int32 *getEmbeddedAddresses(Int32 opcode, Int32 addr[]);
static Int32 getInstructionLength(PCodeBinary * pcode);
static const char * getOpcodeString(Int32 opcode);
// Helper functions to generate PCode segments for common operations
//
// Loading addresses of attributes (and VC and NULL indicators)
//
static PCIList loadVoaAddress(Attributes *attr, CollHeap *heap);
static PCIList loadVoaValue(Attributes *attr, CollHeap *heap);
static PCIList loadVCLenIndAddress(Attributes *attr, CollHeap *heap);
static PCIList loadNullIndAddress(Attributes *attr, CollHeap *heap);
static PCIList loadAddress(Attributes *attr, CollHeap *heap);
static PCIList loadAddress(Attributes *attr, uLong offset, CollHeap *heap);
// Loading attributes (and VC and NULL indicators)
//
static PCIList loadOpDataNullBitmapAddress(Attributes *attr, Int32 loc,CollHeap *heap);
static PCIList loadOpDataNullAddress(Attributes *attr, Int32 loc,CollHeap *heap);
static PCIList loadOpDataVCAddress(Attributes *attr, Int32 loc,CollHeap *heap);
static PCIList loadOpDataDataAddress(Attributes *attr, Int32 loc, CollHeap *heap);
static PCIList loadOpDataAddress(Attributes *attr, Int32 offset, Int32 loc,
CollHeap *heap);
static PCIList loadOpDataNullBitmap(Attributes *attr, Int32 loc, CollHeap *heap);
static PCIList loadOpDataNull(Attributes *attr, Int32 loc, CollHeap *heap);
static PCIList loadVCLenIndValue(Attributes *attr, CollHeap *heap);
static PCIList loadNullIndValue(Attributes *attr, CollHeap *heap);
static PCIList loadValue(Attributes *attr, CollHeap *heap);
static PCIList loadValue(Attributes *attr, uLong offset, CollHeap *heap,
PCIType::AddressingMode =PCIType::AM_NONE);
// Storing attributes (and VC and NULL indicators)
//
// For SQLMX_ALIGNED_FORMAT all offsets are shorts rather than longs.
static PCIList storeShortVoa(Attributes *attr, CollHeap *heap);
static PCIList storeShortValue(UInt32 value,
Attributes *attr,
UInt32 voaOffset,
CollHeap *heap);
static PCIList storeVoa(Attributes *attr, CollHeap *heap);
static PCIList storeVoaValue(Attributes *attr,
uLong voaOffset,
uLong value,
CollHeap *heap,
short varOnly = 0);
static PCIList storeValue(Int32 value, Attributes *attr,
CollHeap *heap);
static PCIList storeValue(Int32 value, Attributes *attr,
uLong offset, CollHeap *heap);
static PCIList updateRowLen(Attributes *attr, CollHeap *heap, UInt32 f);
// Moving attributes (and NULL indicators)
//
static PCIList moveValue(Attributes *dst, Attributes *src, CollHeap *heap);
static PCIList moveVarcharValue(Attributes *dst, Attributes *src, CollHeap *heap);
static PCIList moveVarcharFixedValue(Attributes *dst, Attributes *src, CollHeap *heap);
static PCIList moveFixedVarcharValue(Attributes *dst, Attributes *src, CollHeap *heap);
static PCIList convertVarcharPtrToTarget(Attributes *dst,Attributes *src,CollHeap *heap);
static PCIList copyVarRow(Attributes *dst,
Attributes *src,
UInt32 lastVOAoffset,
Int16 lastVcIndicatorLength,
Int16 lastNullIndicatorLength,
Int16 alignment,
CollHeap *heap);
static PCIID zeroFillNullValue(Attributes *dst,
PCIList& code,
PCIID notNullBranch,
Int32 genUncondJump = -1);
static PCIID generateJumpAndBranch(Attributes *dst,
PCIList& code,
PCIID notNullBranch,
Int32 genUncondJump = -1);
// Testing for NULL or NOT NULL
//
static PCIList isNull(Attributes *attrDst, Attributes *attrSrc,
CollHeap *heap);
static PCIList isNotNull(Attributes *attrDst, Attributes *attrSrc,
CollHeap *heap);
// Generating code to handle NULL in NULL out operations
//
static PCIID nullBranch(ex_clause*, PCIList&, AttributesPtr*);
static PCIID nullBranchHelper(AttributesPtr *attrs,
Attributes *attrA,
Attributes *attrB,
PCIList& code);
static PCIID nullBranchHelperForComp(AttributesPtr *attrs,
Attributes *attrA,
Attributes *attrB,
NABoolean isSpecialNulls,
PCIList& code);
static PCIID nullBranchHelperForHash(AttributesPtr *attrs,
Attributes *attrA,
Attributes *attrB,
PCIList& code);
// Pre/Post generate startup and cleanup PCI's
//
static void preClausePCI(ex_clause *clause, PCIList& code);
static void postClausePCI(ex_clause *clause, PCIList& code);
// Print PCODE (can only be used in Master EXE)
//
static void print(PCIList pciList);
#ifndef __EID
// Used by SHOWPLAN to display PCI's
//
static void displayContents(PCIList pciList, Space *space);
static void displayContents(PCodeBinary* pCode, Space *space);
#endif
// for debug
static Int32 dumpContents(PCIList pciList, char *buf, Int32 bufLen);
static void dumpContents(PCodeBinary* pCode, char *buf, Int32 bufLen);
private:
// pciList_ - The list of PCI's for this PCode object.
//
PCIList pciList_;
// space_ - The allocator to use when operating with the PCode object.
//
CollHeap *heap_;
Space *space_;
Int32 *profileCounts_, *profileTimes_;
};
// For null processing, this struct stores the three tuple formats
// as chars. It also computes the size of the pcode. Size of this
// struct has to be Int32 so that it can be passed as a parameter.
typedef struct PCodeTupleFormats {
char op1Fmt_;
char op2Fmt_;
char op3Fmt_;
char size_;
// do not add anything here. Size needs to be 32 bits.
// constructors
PCodeTupleFormats(char op1Fmt, char op2Fmt, char op3Fmt) {
op1Fmt_ = op1Fmt;
op2Fmt_ = op2Fmt;
op3Fmt_ = op3Fmt;
// 3 operands x (atp, offset, nullbitIndx) + tupleFormat + branch slot
size_ = (3 * 3) + 1 + 1;
}
PCodeTupleFormats(char op1Fmt, char op2Fmt) {
op1Fmt_ = op1Fmt;
op2Fmt_ = op2Fmt;
op3Fmt_ = NULL;
// 2 operands x (atp, offset, nullbitIndx) + tupleFormat + branch slot
size_ = (2 * 3) + 1 + 1;
}
} PCodeTupleFormats;
// The runtime code maps the address of a pcode to this struct
// to enable direct symbolic access to its fields. The EXPAND_
// macros are kept here to ensure they are in sync with the fields defined
// in this struct.
typedef struct{
PCodeTupleFormats fmt_;
Int32 op1NullBitIndex_;
Int32 op2NullBitIndex_;
Int32 op3NullBitIndex_;
#define EXPAND_PCODEATTRNULL3(tpf, op1, op2, op3) \
tpf, op1->getNullBitIndex(), op2->getNullBitIndex(), op3->getNullBitIndex()
#define EXPAND_PCODEATTRNULL2(tpf, op1, op2) \
tpf, op1->getNullBitIndex(), op2->getNullBitIndex()
}PCodeAttrNull;
#endif