LLVM API Documentation

MCAsmInfo.h
Go to the documentation of this file.
00001 //===-- llvm/MC/MCAsmInfo.h - Asm info --------------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains a class to be used as the basis for target specific
00011 // asm writers.  This class primarily takes care of global printing constants,
00012 // which are used in very similar ways across all targets.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_MC_MCASMINFO_H
00017 #define LLVM_MC_MCASMINFO_H
00018 
00019 #include "llvm/MC/MCDirectives.h"
00020 #include "llvm/MC/MCDwarf.h"
00021 #include "llvm/MC/MachineLocation.h"
00022 #include <cassert>
00023 #include <vector>
00024 
00025 namespace llvm {
00026   class MCExpr;
00027   class MCSection;
00028   class MCStreamer;
00029   class MCSymbol;
00030   class MCContext;
00031 
00032   namespace ExceptionHandling {
00033     enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 };
00034   }
00035 
00036   namespace LCOMM {
00037     enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment };
00038   }
00039 
00040   /// MCAsmInfo - This class is intended to be used as a base class for asm
00041   /// properties and features specific to the target.
00042   class MCAsmInfo {
00043   protected:
00044     //===------------------------------------------------------------------===//
00045     // Properties to be set by the target writer, used to configure asm printer.
00046     //
00047 
00048     /// PointerSize - Pointer size in bytes.
00049     ///               Default is 4.
00050     unsigned PointerSize;
00051 
00052     /// CalleeSaveStackSlotSize - Size of the stack slot reserved for
00053     ///                           callee-saved registers, in bytes.
00054     ///                           Default is same as pointer size.
00055     unsigned CalleeSaveStackSlotSize;
00056 
00057     /// IsLittleEndian - True if target is little endian.
00058     ///                  Default is true.
00059     bool IsLittleEndian;
00060 
00061     /// StackGrowsUp - True if target stack grow up.
00062     ///                Default is false.
00063     bool StackGrowsUp;
00064 
00065     /// HasSubsectionsViaSymbols - True if this target has the MachO
00066     /// .subsections_via_symbols directive.
00067     bool HasSubsectionsViaSymbols;           // Default is false.
00068 
00069     /// HasMachoZeroFillDirective - True if this is a MachO target that supports
00070     /// the macho-specific .zerofill directive for emitting BSS Symbols.
00071     bool HasMachoZeroFillDirective;               // Default is false.
00072 
00073     /// HasMachoTBSSDirective - True if this is a MachO target that supports
00074     /// the macho-specific .tbss directive for emitting thread local BSS Symbols
00075     bool HasMachoTBSSDirective;                 // Default is false.
00076 
00077     /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should
00078     /// emit a ".reference .constructors_used" or ".reference .destructors_used"
00079     /// directive after the a static ctor/dtor list.  This directive is only
00080     /// emitted in Static relocation model.
00081     bool HasStaticCtorDtorReferenceInStaticMode;  // Default is false.
00082 
00083     /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and
00084     /// requires that the debug_line section be of a minimum size. In practice
00085     /// such a linker requires a non-empty line sequence if a file is present.
00086     bool LinkerRequiresNonEmptyDwarfLines; // Default to false.
00087 
00088     /// MaxInstLength - This is the maximum possible length of an instruction,
00089     /// which is needed to compute the size of an inline asm.
00090     unsigned MaxInstLength;                  // Defaults to 4.
00091 
00092     /// MinInstAlignment - Every possible instruction length is a multiple of
00093     /// this value.  Factored out in .debug_frame and .debug_line.
00094     unsigned MinInstAlignment;                  // Defaults to 1.
00095 
00096     /// DollarIsPC - The '$' token, when not referencing an identifier or
00097     /// constant, refers to the current PC.
00098     bool DollarIsPC;                         // Defaults to false.
00099 
00100     /// SeparatorString - This string, if specified, is used to separate
00101     /// instructions from each other when on the same line.
00102     const char *SeparatorString;             // Defaults to ';'
00103 
00104     /// CommentString - This indicates the comment character used by the
00105     /// assembler.
00106     const char *CommentString;               // Defaults to "#"
00107 
00108     /// LabelSuffix - This is appended to emitted labels.
00109     const char *LabelSuffix;                 // Defaults to ":"
00110 
00111     /// LabelSuffix - This is appended to emitted labels.
00112     const char *DebugLabelSuffix;                 // Defaults to ":"
00113 
00114     /// This prefix is used for globals like constant pool entries that are
00115     /// completely private to the .s file and should not have names in the .o
00116     /// file.
00117     const char *PrivateGlobalPrefix;         // Defaults to "L"
00118 
00119     /// This prefix is used for symbols that should be passed through the
00120     /// assembler but be removed by the linker.  This is 'l' on Darwin,
00121     /// currently used for some ObjC metadata.
00122     /// The default of "" meast that for this system a plain private symbol
00123     /// should be used.
00124     const char *LinkerPrivateGlobalPrefix;    // Defaults to "".
00125 
00126     /// InlineAsmStart/End - If these are nonempty, they contain a directive to
00127     /// emit before and after an inline assembly statement.
00128     const char *InlineAsmStart;              // Defaults to "#APP\n"
00129     const char *InlineAsmEnd;                // Defaults to "#NO_APP\n"
00130 
00131     /// Code16Directive, Code32Directive, Code64Directive - These are assembly
00132     /// directives that tells the assembler to interpret the following
00133     /// instructions differently.
00134     const char *Code16Directive;             // Defaults to ".code16"
00135     const char *Code32Directive;             // Defaults to ".code32"
00136     const char *Code64Directive;             // Defaults to ".code64"
00137 
00138     /// AssemblerDialect - Which dialect of an assembler variant to use.
00139     unsigned AssemblerDialect;               // Defaults to 0
00140 
00141     /// \brief This is true if the assembler allows @ characters in symbol
00142     /// names. Defaults to false.
00143     bool AllowAtInName;
00144 
00145     /// UseDataRegionDirectives - This is true if data region markers should
00146     /// be printed as ".data_region/.end_data_region" directives. If false,
00147     /// use "$d/$a" labels instead.
00148     bool UseDataRegionDirectives;
00149 
00150     //===--- Data Emission Directives -------------------------------------===//
00151 
00152     /// ZeroDirective - this should be set to the directive used to get some
00153     /// number of zero bytes emitted to the current section.  Common cases are
00154     /// "\t.zero\t" and "\t.space\t".  If this is set to null, the
00155     /// Data*bitsDirective's will be used to emit zero bytes.
00156     const char *ZeroDirective;               // Defaults to "\t.zero\t"
00157 
00158     /// AsciiDirective - This directive allows emission of an ascii string with
00159     /// the standard C escape characters embedded into it.
00160     const char *AsciiDirective;              // Defaults to "\t.ascii\t"
00161 
00162     /// AscizDirective - If not null, this allows for special handling of
00163     /// zero terminated strings on this target.  This is commonly supported as
00164     /// ".asciz".  If a target doesn't support this, it can be set to null.
00165     const char *AscizDirective;              // Defaults to "\t.asciz\t"
00166 
00167     /// DataDirectives - These directives are used to output some unit of
00168     /// integer data to the current section.  If a data directive is set to
00169     /// null, smaller data directives will be used to emit the large sizes.
00170     const char *Data8bitsDirective;          // Defaults to "\t.byte\t"
00171     const char *Data16bitsDirective;         // Defaults to "\t.short\t"
00172     const char *Data32bitsDirective;         // Defaults to "\t.long\t"
00173     const char *Data64bitsDirective;         // Defaults to "\t.quad\t"
00174 
00175     /// GPRel64Directive - if non-null, a directive that is used to emit a word
00176     /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword
00177     /// on Mips.
00178     const char *GPRel64Directive;            // Defaults to NULL.
00179 
00180     /// GPRel32Directive - if non-null, a directive that is used to emit a word
00181     /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword
00182     /// on Mips or .gprel32 on Alpha.
00183     const char *GPRel32Directive;            // Defaults to NULL.
00184 
00185     /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun
00186     /// Style" syntax for section switching ("#alloc,#write" etc) instead of the
00187     /// normal ELF syntax (,"a,w") in .section directives.
00188     bool SunStyleELFSectionSwitchSyntax;     // Defaults to false.
00189 
00190     /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF
00191     /// '.section' directive before the '.bss' one. It's used for PPC/Linux
00192     /// which doesn't support the '.bss' directive only.
00193     bool UsesELFSectionDirectiveForBSS;      // Defaults to false.
00194 
00195     bool NeedsDwarfSectionOffsetDirective;
00196 
00197     //===--- Alignment Information ----------------------------------------===//
00198 
00199     /// AlignmentIsInBytes - If this is true (the default) then the asmprinter
00200     /// emits ".align N" directives, where N is the number of bytes to align to.
00201     /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte
00202     /// boundary.
00203     bool AlignmentIsInBytes;                 // Defaults to true
00204 
00205     /// TextAlignFillValue - If non-zero, this is used to fill the executable
00206     /// space created as the result of a alignment directive.
00207     unsigned TextAlignFillValue;             // Defaults to 0
00208 
00209     //===--- Global Variable Emission Directives --------------------------===//
00210 
00211     /// GlobalDirective - This is the directive used to declare a global entity.
00212     ///
00213     const char *GlobalDirective;             // Defaults to NULL.
00214 
00215     /// HasSetDirective - True if the assembler supports the .set directive.
00216     bool HasSetDirective;                    // Defaults to true.
00217 
00218     /// HasAggressiveSymbolFolding - False if the assembler requires that we use
00219     /// Lc = a - b
00220     /// .long Lc
00221     /// instead of
00222     /// .long a - b
00223     bool HasAggressiveSymbolFolding;           // Defaults to true.
00224 
00225     /// COMMDirectiveAlignmentIsInBytes - True is .comm's and .lcomms optional
00226     /// alignment is to be specified in bytes instead of log2(n).
00227     bool COMMDirectiveAlignmentIsInBytes;    // Defaults to true;
00228 
00229     /// LCOMMDirectiveAlignment - Describes if the .lcomm directive for the
00230     /// target supports an alignment argument and how it is interpreted.
00231     LCOMM::LCOMMType LCOMMDirectiveAlignmentType; // Defaults to NoAlignment.
00232 
00233     /// HasDotTypeDotSizeDirective - True if the target has .type and .size
00234     /// directives, this is true for most ELF targets.
00235     bool HasDotTypeDotSizeDirective;         // Defaults to true.
00236 
00237     /// HasSingleParameterDotFile - True if the target has a single parameter
00238     /// .file directive, this is true for ELF targets.
00239     bool HasSingleParameterDotFile;          // Defaults to true.
00240 
00241     /// hasIdentDirective - True if the target has a .ident directive, this is
00242     /// true for ELF targets.
00243     bool HasIdentDirective;                  // Defaults to false.
00244 
00245     /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip
00246     /// directive.
00247     bool HasNoDeadStrip;                     // Defaults to false.
00248 
00249     /// WeakRefDirective - This directive, if non-null, is used to declare a
00250     /// global as being a weak undefined symbol.
00251     const char *WeakRefDirective;            // Defaults to NULL.
00252 
00253     /// True if we have a directive to declare a global as being a weak
00254     /// defined symbol.
00255     bool HasWeakDefDirective;                // Defaults to false.
00256 
00257     /// True if we have a directive to declare a global as being a weak
00258     /// defined symbol that can be hidden (unexported).
00259     bool HasWeakDefCanBeHiddenDirective;     // Defaults to false.
00260 
00261     /// True if we have a .linkonce directive.  This is used on cygwin/mingw.
00262     bool HasLinkOnceDirective;               // Defaults to false.
00263 
00264     /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to
00265     /// declare a symbol as having hidden visibility.
00266     MCSymbolAttr HiddenVisibilityAttr;       // Defaults to MCSA_Hidden.
00267 
00268     /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid,
00269     /// is used to declare an undefined symbol as having hidden visibility.
00270     MCSymbolAttr HiddenDeclarationVisibilityAttr;   // Defaults to MCSA_Hidden.
00271 
00272 
00273     /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used
00274     /// to declare a symbol as having protected visibility.
00275     MCSymbolAttr ProtectedVisibilityAttr;    // Defaults to MCSA_Protected
00276 
00277     //===--- Dwarf Emission Directives -----------------------------------===//
00278 
00279     /// HasLEB128 - True if target asm supports leb128 directives.
00280     bool HasLEB128;                          // Defaults to false.
00281 
00282     /// SupportsDebugInformation - True if target supports emission of debugging
00283     /// information.
00284     bool SupportsDebugInformation;           // Defaults to false.
00285 
00286     /// SupportsExceptionHandling - True if target supports exception handling.
00287     ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None
00288 
00289     /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally
00290     /// uses relocations for references to other .debug_* sections.
00291     bool DwarfUsesRelocationsAcrossSections;
00292 
00293     /// DwarfFDESymbolsUseAbsDiff - true if DWARF FDE symbol reference
00294     /// relocations should be replaced by an absolute difference.
00295     bool DwarfFDESymbolsUseAbsDiff;
00296 
00297     /// DwarfRegNumForCFI - True if dwarf register numbers are printed
00298     /// instead of symbolic register names in .cfi_* directives.
00299     bool DwarfRegNumForCFI;  // Defaults to false;
00300 
00301     /// UseParensForSymbolVariant - True if target uses parens to indicate the
00302     /// symbol variant instead of @. For example, foo(plt) instead of foo@plt.
00303     bool UseParensForSymbolVariant; // Defaults to false;
00304 
00305     //===--- Prologue State ----------------------------------------------===//
00306 
00307     std::vector<MCCFIInstruction> InitialFrameState;
00308 
00309     //===--- Integrated Assembler State ----------------------------------===//
00310     /// Should we use the integrated assembler?
00311     /// The integrated assembler should be enabled by default (by the
00312     /// constructors) when failing to parse a valid piece of assembly (inline
00313     /// or otherwise) is considered a bug. It may then be overridden after
00314     /// construction (see LLVMTargetMachine::initAsmInfo()).
00315     bool UseIntegratedAssembler;
00316 
00317     /// Compress DWARF debug sections. Defaults to false.
00318     bool CompressDebugSections;
00319 
00320   public:
00321     explicit MCAsmInfo();
00322     virtual ~MCAsmInfo();
00323 
00324     /// getPointerSize - Get the pointer size in bytes.
00325     unsigned getPointerSize() const {
00326       return PointerSize;
00327     }
00328 
00329     /// getCalleeSaveStackSlotSize - Get the callee-saved register stack slot
00330     /// size in bytes.
00331     unsigned getCalleeSaveStackSlotSize() const {
00332       return CalleeSaveStackSlotSize;
00333     }
00334 
00335     /// isLittleEndian - True if the target is little endian.
00336     bool isLittleEndian() const {
00337       return IsLittleEndian;
00338     }
00339 
00340     /// isStackGrowthDirectionUp - True if target stack grow up.
00341     bool isStackGrowthDirectionUp() const {
00342       return StackGrowsUp;
00343     }
00344 
00345     bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; }
00346 
00347     // Data directive accessors.
00348     //
00349     const char *getData8bitsDirective() const {
00350       return Data8bitsDirective;
00351     }
00352     const char *getData16bitsDirective() const {
00353       return Data16bitsDirective;
00354     }
00355     const char *getData32bitsDirective() const {
00356       return Data32bitsDirective;
00357     }
00358     const char *getData64bitsDirective() const {
00359       return Data64bitsDirective;
00360     }
00361     const char *getGPRel64Directive() const { return GPRel64Directive; }
00362     const char *getGPRel32Directive() const { return GPRel32Directive; }
00363 
00364     /// getNonexecutableStackSection - Targets can implement this method to
00365     /// specify a section to switch to if the translation unit doesn't have any
00366     /// trampolines that require an executable stack.
00367     virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const{
00368       return nullptr;
00369     }
00370 
00371     virtual const MCExpr *
00372     getExprForPersonalitySymbol(const MCSymbol *Sym,
00373                                 unsigned Encoding,
00374                                 MCStreamer &Streamer) const;
00375 
00376     virtual const MCExpr *
00377     getExprForFDESymbol(const MCSymbol *Sym,
00378                         unsigned Encoding,
00379                         MCStreamer &Streamer) const;
00380 
00381     bool usesSunStyleELFSectionSwitchSyntax() const {
00382       return SunStyleELFSectionSwitchSyntax;
00383     }
00384 
00385     bool usesELFSectionDirectiveForBSS() const {
00386       return UsesELFSectionDirectiveForBSS;
00387     }
00388 
00389     bool needsDwarfSectionOffsetDirective() const {
00390       return NeedsDwarfSectionOffsetDirective;
00391     }
00392 
00393     // Accessors.
00394     //
00395     bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; }
00396     bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; }
00397     bool hasStaticCtorDtorReferenceInStaticMode() const {
00398       return HasStaticCtorDtorReferenceInStaticMode;
00399     }
00400     bool getLinkerRequiresNonEmptyDwarfLines() const {
00401       return LinkerRequiresNonEmptyDwarfLines;
00402     }
00403     unsigned getMaxInstLength() const {
00404       return MaxInstLength;
00405     }
00406     unsigned getMinInstAlignment() const {
00407       return MinInstAlignment;
00408     }
00409     bool getDollarIsPC() const {
00410       return DollarIsPC;
00411     }
00412     const char *getSeparatorString() const {
00413       return SeparatorString;
00414     }
00415 
00416     /// This indicates the column (zero-based) at which asm comments should be
00417     /// printed.
00418     unsigned getCommentColumn() const {
00419       return 40;
00420     }
00421 
00422     const char *getCommentString() const {
00423       return CommentString;
00424     }
00425     const char *getLabelSuffix() const {
00426       return LabelSuffix;
00427     }
00428 
00429     const char *getDebugLabelSuffix() const {
00430       return DebugLabelSuffix;
00431     }
00432     const char *getPrivateGlobalPrefix() const {
00433       return PrivateGlobalPrefix;
00434     }
00435     bool hasLinkerPrivateGlobalPrefix() const {
00436       return LinkerPrivateGlobalPrefix[0] != '\0';
00437     }
00438     const char *getLinkerPrivateGlobalPrefix() const {
00439       if (hasLinkerPrivateGlobalPrefix())
00440         return LinkerPrivateGlobalPrefix;
00441       return getPrivateGlobalPrefix();
00442     }
00443     const char *getInlineAsmStart() const {
00444       return InlineAsmStart;
00445     }
00446     const char *getInlineAsmEnd() const {
00447       return InlineAsmEnd;
00448     }
00449     const char *getCode16Directive() const {
00450       return Code16Directive;
00451     }
00452     const char *getCode32Directive() const {
00453       return Code32Directive;
00454     }
00455     const char *getCode64Directive() const {
00456       return Code64Directive;
00457     }
00458     unsigned getAssemblerDialect() const {
00459       return AssemblerDialect;
00460     }
00461     bool doesAllowAtInName() const {
00462       return AllowAtInName;
00463     }
00464     bool doesSupportDataRegionDirectives() const {
00465       return UseDataRegionDirectives;
00466     }
00467     const char *getZeroDirective() const {
00468       return ZeroDirective;
00469     }
00470     const char *getAsciiDirective() const {
00471       return AsciiDirective;
00472     }
00473     const char *getAscizDirective() const {
00474       return AscizDirective;
00475     }
00476     bool getAlignmentIsInBytes() const {
00477       return AlignmentIsInBytes;
00478     }
00479     unsigned getTextAlignFillValue() const {
00480       return TextAlignFillValue;
00481     }
00482     const char *getGlobalDirective() const {
00483       return GlobalDirective;
00484     }
00485     bool hasSetDirective() const { return HasSetDirective; }
00486     bool hasAggressiveSymbolFolding() const {
00487       return HasAggressiveSymbolFolding;
00488     }
00489     bool getCOMMDirectiveAlignmentIsInBytes() const {
00490       return COMMDirectiveAlignmentIsInBytes;
00491     }
00492     LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const {
00493       return LCOMMDirectiveAlignmentType;
00494     }
00495     bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;}
00496     bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
00497     bool hasIdentDirective() const { return HasIdentDirective; }
00498     bool hasNoDeadStrip() const { return HasNoDeadStrip; }
00499     const char *getWeakRefDirective() const { return WeakRefDirective; }
00500     bool hasWeakDefDirective() const { return HasWeakDefDirective; }
00501     bool hasWeakDefCanBeHiddenDirective() const {
00502       return HasWeakDefCanBeHiddenDirective;
00503     }
00504     bool hasLinkOnceDirective() const { return HasLinkOnceDirective; }
00505 
00506     MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;}
00507     MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
00508       return HiddenDeclarationVisibilityAttr;
00509     }
00510     MCSymbolAttr getProtectedVisibilityAttr() const {
00511       return ProtectedVisibilityAttr;
00512     }
00513     bool hasLEB128() const {
00514       return HasLEB128;
00515     }
00516     bool doesSupportDebugInformation() const {
00517       return SupportsDebugInformation;
00518     }
00519     bool doesSupportExceptionHandling() const {
00520       return ExceptionsType != ExceptionHandling::None;
00521     }
00522     ExceptionHandling::ExceptionsType getExceptionHandlingType() const {
00523       return ExceptionsType;
00524     }
00525     bool isExceptionHandlingDwarf() const {
00526       return
00527         (ExceptionsType == ExceptionHandling::DwarfCFI ||
00528          ExceptionsType == ExceptionHandling::ARM ||
00529          ExceptionsType == ExceptionHandling::Win64);
00530     }
00531     bool doesDwarfUseRelocationsAcrossSections() const {
00532       return DwarfUsesRelocationsAcrossSections;
00533     }
00534     bool doDwarfFDESymbolsUseAbsDiff() const {
00535       return DwarfFDESymbolsUseAbsDiff;
00536     }
00537     bool useDwarfRegNumForCFI() const {
00538       return DwarfRegNumForCFI;
00539     }
00540     bool useParensForSymbolVariant() const {
00541       return UseParensForSymbolVariant;
00542     }
00543 
00544     void addInitialFrameState(const MCCFIInstruction &Inst) {
00545       InitialFrameState.push_back(Inst);
00546     }
00547 
00548     const std::vector<MCCFIInstruction> &getInitialFrameState() const {
00549       return InitialFrameState;
00550     }
00551 
00552     /// Return true if assembly (inline or otherwise) should be parsed.
00553     bool useIntegratedAssembler() const { return UseIntegratedAssembler; }
00554 
00555     /// Set whether assembly (inline or otherwise) should be parsed.
00556     virtual void setUseIntegratedAssembler(bool Value) {
00557       UseIntegratedAssembler = Value;
00558     }
00559 
00560     bool compressDebugSections() const { return CompressDebugSections; }
00561 
00562     void setCompressDebugSections(bool CompressDebugSections) {
00563       this->CompressDebugSections = CompressDebugSections;
00564     }
00565   };
00566 }
00567 
00568 #endif