ConstantFolder.h revision baf3c404409d5e47b13984a7f95bfbd6d1f2e79e
11e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- C++ -*-===//
21e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//
31e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//                     The LLVM Compiler Infrastructure
41e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//
51e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// This file is distributed under the University of Illinois Open Source
61e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands// License. See LICENSE.TXT for details.
71e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//
81e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===----------------------------------------------------------------------===//
91e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//
1020df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// This file defines the ConstantFolder class, a helper for IRBuilder.
1120df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// It provides IRBuilder with a set of methods for creating constants
1220df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// with minimal folding.  For general constant creation and folding,
1320df07ba22c0b7e907c1a7912b5d3d1d2fb948dbDuncan Sands// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h.
141e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//
151e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands//===----------------------------------------------------------------------===//
161e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
171e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H
181e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#define LLVM_SUPPORT_CONSTANTFOLDER_H
191e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
201e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#include "llvm/Constants.h"
2145524c58fd5f77b6a3f6e77d43fba85b36ec0b08Owen Anderson#include "llvm/LLVMContext.h"
221e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
231e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandsnamespace llvm {
2445524c58fd5f77b6a3f6e77d43fba85b36ec0b08Owen Anderson
251e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands/// ConstantFolder - Create constants with minimum, target independent, folding.
261e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandsclass ConstantFolder {
2745524c58fd5f77b6a3f6e77d43fba85b36ec0b08Owen Anderson  LLVMContext &Context;
2845524c58fd5f77b6a3f6e77d43fba85b36ec0b08Owen Anderson
291e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sandspublic:
3045524c58fd5f77b6a3f6e77d43fba85b36ec0b08Owen Anderson  ConstantFolder(LLVMContext &C) : Context(C) { }
311e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
321e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
331e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Binary Operators
341e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
351e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
361e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateAdd(Constant *LHS, Constant *RHS) const {
37baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getAdd(LHS, RHS);
381e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
39ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
40baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFAdd(LHS, RHS);
41ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  }
421e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateSub(Constant *LHS, Constant *RHS) const {
43baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getSub(LHS, RHS);
441e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
45ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
46baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFSub(LHS, RHS);
47ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  }
481e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateMul(Constant *LHS, Constant *RHS) const {
49baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getMul(LHS, RHS);
501e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
51ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
52baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFMul(LHS, RHS);
53ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  }
541e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateUDiv(Constant *LHS, Constant *RHS) const {
55baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getUDiv(LHS, RHS);
561e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
571e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateSDiv(Constant *LHS, Constant *RHS) const {
58baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getSDiv(LHS, RHS);
591e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
601e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateFDiv(Constant *LHS, Constant *RHS) const {
61baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFDiv(LHS, RHS);
621e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
631e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateURem(Constant *LHS, Constant *RHS) const {
64baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getURem(LHS, RHS);
651e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
661e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateSRem(Constant *LHS, Constant *RHS) const {
67baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getSRem(LHS, RHS);
681e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
691e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateFRem(Constant *LHS, Constant *RHS) const {
70baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFRem(LHS, RHS);
711e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
721e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateShl(Constant *LHS, Constant *RHS) const {
73baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getShl(LHS, RHS);
741e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
751e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateLShr(Constant *LHS, Constant *RHS) const {
76baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getLShr(LHS, RHS);
771e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
781e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateAShr(Constant *LHS, Constant *RHS) const {
79baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getAShr(LHS, RHS);
801e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
811e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateAnd(Constant *LHS, Constant *RHS) const {
82baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getAnd(LHS, RHS);
831e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
841e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateOr(Constant *LHS, Constant *RHS) const {
85baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getOr(LHS, RHS);
861e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
871e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateXor(Constant *LHS, Constant *RHS) const {
88baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getXor(LHS, RHS);
891e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
901e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
911e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateBinOp(Instruction::BinaryOps Opc,
921e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                        Constant *LHS, Constant *RHS) const {
93baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::get(Opc, LHS, RHS);
941e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
951e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
961e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
971e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Unary Operators
981e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
991e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1001e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateNeg(Constant *C) const {
101baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getNeg(C);
1021e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
103ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  Constant *CreateFNeg(Constant *C) const {
104baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getFNeg(C);
105ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman  }
1061e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateNot(Constant *C) const {
107baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getNot(C);
1081e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1091e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1101e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1111e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Memory Instructions
1121e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1131e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1141e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList,
1151e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                                unsigned NumIdx) const {
116baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx);
1171e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1181e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList,
1191e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                                unsigned NumIdx) const {
120baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx);
1211e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1221e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1231e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1241e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Cast/Conversion Operators
1251e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1261e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1271e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateCast(Instruction::CastOps Op, Constant *C,
1281e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                       const Type *DestTy) const {
129baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getCast(Op, C, DestTy);
1301e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1311e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateIntCast(Constant *C, const Type *DestTy,
1321e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                          bool isSigned) const {
133baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getIntegerCast(C, DestTy, isSigned);
1341e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1351e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1361e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateBitCast(Constant *C, const Type *DestTy) const {
1371e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands    return CreateCast(Instruction::BitCast, C, DestTy);
1381e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1391e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const {
1401e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands    return CreateCast(Instruction::IntToPtr, C, DestTy);
1411e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1421e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const {
1431e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands    return CreateCast(Instruction::PtrToInt, C, DestTy);
1441e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1451e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const {
146baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getTruncOrBitCast(C, DestTy);
1471e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1481e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1491e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1501e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Compare Instructions
1511e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1521e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
153fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands  Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS,
154fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands                       Constant *RHS) const {
155baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getCompare(P, LHS, RHS);
156fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands  }
157fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands  Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS,
158fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands                       Constant *RHS) const {
159baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getCompare(P, LHS, RHS);
160fe24bd3a89c44f9a16e3cbcf60c119dac88fad40Duncan Sands  }
1611e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1621e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1631e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  // Other Instructions
1641e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  //===--------------------------------------------------------------------===//
1651e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1661e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const {
167baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getSelect(C, True, False);
1681e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1691e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1701e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const {
171baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getExtractElement(Vec, Idx);
1721e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1731e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1741e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateInsertElement(Constant *Vec, Constant *NewElt,
1751e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                                Constant *Idx) const {
176baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getInsertElement(Vec, NewElt, Idx);
1771e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1781e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1791e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateShuffleVector(Constant *V1, Constant *V2,
1801e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                                Constant *Mask) const {
181baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getShuffleVector(V1, V2, Mask);
1821e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1831e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1841e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList,
1851e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                               unsigned NumIdx) const {
186baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getExtractValue(Agg, IdxList, NumIdx);
1871e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1881e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1891e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  Constant *CreateInsertValue(Constant *Agg, Constant *Val,
1901e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands                              const unsigned *IdxList, unsigned NumIdx) const {
191baf3c404409d5e47b13984a7f95bfbd6d1f2e79eOwen Anderson    return ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx);
1921e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands  }
1931e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands};
1941e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1951e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands}
1961e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands
1971e7f7865ebd3b47c93dc8867abe5baae0df0ebceDuncan Sands#endif
198