1 //===-- IRForTarget.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_IRForTarget_h_ 11 #define liblldb_IRForTarget_h_ 12 13 #include "lldb/lldb-public.h" 14 #include "lldb/Core/ConstString.h" 15 #include "lldb/Core/Error.h" 16 #include "lldb/Core/Stream.h" 17 #include "lldb/Core/StreamString.h" 18 #include "lldb/Symbol/TaggedASTType.h" 19 #include "llvm/Pass.h" 20 21 #include <map> 22 #include <functional> 23 24 namespace llvm { 25 class BasicBlock; 26 class CallInst; 27 class Constant; 28 class ConstantInt; 29 class Function; 30 class GlobalValue; 31 class GlobalVariable; 32 class Instruction; 33 class IntegerType; 34 class Module; 35 class StoreInst; 36 class DataLayout; 37 class Type; 38 class Value; 39 } 40 41 namespace lldb_private { 42 class ClangExpressionDeclMap; 43 class IRExecutionUnit; 44 class IRMemoryMap; 45 } 46 47 //---------------------------------------------------------------------- 48 /// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" 49 /// @brief Transforms the IR for a function to run in the target 50 /// 51 /// Once an expression has been parsed and converted to IR, it can run 52 /// in two contexts: interpreted by LLDB as a DWARF location expression, 53 /// or compiled by the JIT and inserted into the target process for 54 /// execution. 55 /// 56 /// IRForTarget makes the second possible, by applying a series of 57 /// transformations to the IR which make it relocatable. These 58 /// transformations are discussed in more detail next to their relevant 59 /// functions. 60 //---------------------------------------------------------------------- 61 class IRForTarget : public llvm::ModulePass 62 { 63 public: 64 enum class LookupResult { 65 Success, 66 Fail, 67 Ignore 68 }; 69 70 //------------------------------------------------------------------ 71 /// Constructor 72 /// 73 /// @param[in] decl_map 74 /// The list of externally-referenced variables for the expression, 75 /// for use in looking up globals and allocating the argument 76 /// struct. See the documentation for ClangExpressionDeclMap. 77 /// 78 /// @param[in] resolve_vars 79 /// True if the external variable references (including persistent 80 /// variables) should be resolved. If not, only external functions 81 /// are resolved. 82 /// 83 /// @param[in] execution_policy 84 /// Determines whether an IR interpreter can be used to statically 85 /// evaluate the expression. 86 /// 87 /// @param[in] const_result 88 /// This variable is populated with the statically-computed result 89 /// of the function, if it has no side-effects and the result can 90 /// be computed statically. 91 /// 92 /// @param[in] execution_unit 93 /// The holder for raw data associated with the expression. 94 /// 95 /// @param[in] error_stream 96 /// If non-NULL, a stream on which errors can be printed. 97 /// 98 /// @param[in] func_name 99 /// The name of the function to prepare for execution in the target. 100 //------------------------------------------------------------------ 101 IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, 102 bool resolve_vars, 103 lldb_private::IRExecutionUnit &execution_unit, 104 lldb_private::Stream *error_stream, 105 const char* func_name = "$__lldb_expr"); 106 107 //------------------------------------------------------------------ 108 /// Destructor 109 //------------------------------------------------------------------ 110 virtual ~IRForTarget(); 111 112 //------------------------------------------------------------------ 113 /// Run this IR transformer on a single module 114 /// 115 /// Implementation of the llvm::ModulePass::runOnModule() function. 116 /// 117 /// @param[in] llvm_module 118 /// The module to run on. This module is searched for the function 119 /// $__lldb_expr, and that function is passed to the passes one by 120 /// one. 121 /// 122 /// @param[in] interpreter_error 123 /// An error. If the expression fails to be interpreted, this error 124 /// is set to a reason why. 125 /// 126 /// @return 127 /// True on success; false otherwise 128 //------------------------------------------------------------------ 129 virtual bool 130 runOnModule (llvm::Module &llvm_module); 131 132 //------------------------------------------------------------------ 133 /// Interface stub 134 /// 135 /// Implementation of the llvm::ModulePass::assignPassManager() 136 /// function. 137 //------------------------------------------------------------------ 138 virtual void 139 assignPassManager (llvm::PMStack &pass_mgr_stack, 140 llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager); 141 142 //------------------------------------------------------------------ 143 /// Returns PMT_ModulePassManager 144 /// 145 /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() 146 /// function. 147 //------------------------------------------------------------------ 148 virtual llvm::PassManagerType 149 getPotentialPassManagerType() const; 150 151 private: 152 //------------------------------------------------------------------ 153 /// Ensures that the current function's linkage is set to external. 154 /// Otherwise the JIT may not return an address for it. 155 /// 156 /// @param[in] llvm_function 157 /// The function whose linkage is to be fixed. 158 /// 159 /// @return 160 /// True on success; false otherwise. 161 //------------------------------------------------------------------ 162 bool 163 FixFunctionLinkage (llvm::Function &llvm_function); 164 165 //------------------------------------------------------------------ 166 /// A module-level pass to replace all function pointers with their 167 /// integer equivalents. 168 //------------------------------------------------------------------ 169 170 //------------------------------------------------------------------ 171 /// The top-level pass implementation 172 /// 173 /// @param[in] llvm_module 174 /// The module currently being processed. 175 /// 176 /// @param[in] llvm_function 177 /// The function currently being processed. 178 /// 179 /// @return 180 /// True on success; false otherwise. 181 //------------------------------------------------------------------ 182 bool 183 HasSideEffects (llvm::Function &llvm_function); 184 185 //------------------------------------------------------------------ 186 /// A function-level pass to check whether the function has side 187 /// effects. 188 //------------------------------------------------------------------ 189 190 //------------------------------------------------------------------ 191 /// Get the address of a function, and a location to put the complete 192 /// Value of the function if one is available. 193 /// 194 /// @param[in] function 195 /// The function to find the location of. 196 /// 197 /// @param[out] ptr 198 /// The location of the function in the target. 199 /// 200 /// @param[out] name 201 /// The resolved name of the function (matters for intrinsics). 202 /// 203 /// @param[out] value_ptr 204 /// A variable to put the function's completed Value* in, or NULL 205 /// if the Value* shouldn't be stored anywhere. 206 /// 207 /// @return 208 /// The pointer. 209 //------------------------------------------------------------------ 210 LookupResult 211 GetFunctionAddress (llvm::Function *function, 212 uint64_t &ptr, 213 lldb_private::ConstString &name, 214 llvm::Constant **&value_ptr); 215 216 //------------------------------------------------------------------ 217 /// Build a function pointer given a type and a raw pointer. 218 /// 219 /// @param[in] type 220 /// The type of the function pointer to be built. 221 /// 222 /// @param[in] ptr 223 /// The value of the pointer. 224 /// 225 /// @return 226 /// The pointer. 227 //------------------------------------------------------------------ 228 llvm::Constant * 229 BuildFunctionPointer (llvm::Type *type, 230 uint64_t ptr); 231 232 void 233 RegisterFunctionMetadata (llvm::LLVMContext &context, 234 llvm::Value *function_ptr, 235 const char *name); 236 237 //------------------------------------------------------------------ 238 /// The top-level pass implementation 239 /// 240 /// @param[in] llvm_function 241 /// The function currently being processed. 242 /// 243 /// @return 244 /// True if the function has side effects (or if this cannot 245 /// be determined); false otherwise. 246 //------------------------------------------------------------------ 247 bool 248 ResolveFunctionPointers (llvm::Module &llvm_module); 249 250 //------------------------------------------------------------------ 251 /// A function-level pass to take the generated global value 252 /// $__lldb_expr_result and make it into a persistent variable. 253 /// Also see ASTResultSynthesizer. 254 //------------------------------------------------------------------ 255 256 //------------------------------------------------------------------ 257 /// Find the NamedDecl corresponding to a Value. This interface is 258 /// exposed for the IR interpreter. 259 /// 260 /// @param[in] module 261 /// The module containing metadata to search 262 /// 263 /// @param[in] global 264 /// The global entity to search for 265 /// 266 /// @return 267 /// The corresponding variable declaration 268 //------------------------------------------------------------------ 269 public: 270 static clang::NamedDecl * 271 DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); 272 private: 273 clang::NamedDecl * 274 DeclForGlobal (llvm::GlobalValue *global); 275 276 //------------------------------------------------------------------ 277 /// Set the constant result variable m_const_result to the provided 278 /// constant, assuming it can be evaluated. The result variable 279 /// will be reset to NULL later if the expression has side effects. 280 /// 281 /// @param[in] initializer 282 /// The constant initializer for the variable. 283 /// 284 /// @param[in] name 285 /// The name of the result variable. 286 /// 287 /// @param[in] type 288 /// The Clang type of the result variable. 289 //------------------------------------------------------------------ 290 void 291 MaybeSetConstantResult (llvm::Constant *initializer, 292 const lldb_private::ConstString &name, 293 lldb_private::TypeFromParser type); 294 295 //------------------------------------------------------------------ 296 /// If the IR represents a cast of a variable, set m_const_result 297 /// to the result of the cast. The result variable will be reset to 298 /// NULL latger if the expression has side effects. 299 /// 300 /// @param[in] type 301 /// The Clang type of the result variable. 302 //------------------------------------------------------------------ 303 void 304 MaybeSetCastResult (lldb_private::TypeFromParser type); 305 306 //------------------------------------------------------------------ 307 /// The top-level pass implementation 308 /// 309 /// @param[in] llvm_function 310 /// The function currently being processed. 311 /// 312 /// @return 313 /// True on success; false otherwise 314 //------------------------------------------------------------------ 315 bool 316 CreateResultVariable (llvm::Function &llvm_function); 317 318 //------------------------------------------------------------------ 319 /// A module-level pass to find Objective-C constant strings and 320 /// transform them to calls to CFStringCreateWithBytes. 321 //------------------------------------------------------------------ 322 323 //------------------------------------------------------------------ 324 /// Rewrite a single Objective-C constant string. 325 /// 326 /// @param[in] NSStr 327 /// The constant NSString to be transformed 328 /// 329 /// @param[in] CStr 330 /// The constant C string inside the NSString. This will be 331 /// passed as the bytes argument to CFStringCreateWithBytes. 332 /// 333 /// @return 334 /// True on success; false otherwise 335 //------------------------------------------------------------------ 336 bool 337 RewriteObjCConstString (llvm::GlobalVariable *NSStr, 338 llvm::GlobalVariable *CStr); 339 340 //------------------------------------------------------------------ 341 /// The top-level pass implementation 342 /// 343 /// @return 344 /// True on success; false otherwise 345 //------------------------------------------------------------------ 346 bool 347 RewriteObjCConstStrings (); 348 349 //------------------------------------------------------------------ 350 /// A basic block-level pass to find all Objective-C method calls and 351 /// rewrite them to use sel_registerName instead of statically allocated 352 /// selectors. The reason is that the selectors are created on the 353 /// assumption that the Objective-C runtime will scan the appropriate 354 /// section and prepare them. This doesn't happen when code is copied 355 /// into the target, though, and there's no easy way to induce the 356 /// runtime to scan them. So instead we get our selectors from 357 /// sel_registerName. 358 //------------------------------------------------------------------ 359 360 //------------------------------------------------------------------ 361 /// Replace a single selector reference 362 /// 363 /// @param[in] selector_load 364 /// The load of the statically-allocated selector. 365 /// 366 /// @return 367 /// True on success; false otherwise 368 //------------------------------------------------------------------ 369 bool 370 RewriteObjCSelector (llvm::Instruction* selector_load); 371 372 //------------------------------------------------------------------ 373 /// The top-level pass implementation 374 /// 375 /// @param[in] basic_block 376 /// The basic block currently being processed. 377 /// 378 /// @return 379 /// True on success; false otherwise 380 //------------------------------------------------------------------ 381 bool 382 RewriteObjCSelectors (llvm::BasicBlock &basic_block); 383 384 //------------------------------------------------------------------ 385 /// A basic block-level pass to find all newly-declared persistent 386 /// variables and register them with the ClangExprDeclMap. This 387 /// allows them to be materialized and dematerialized like normal 388 /// external variables. Before transformation, these persistent 389 /// variables look like normal locals, so they have an allocation. 390 /// This pass excises these allocations and makes references look 391 /// like external references where they will be resolved -- like all 392 /// other external references -- by ResolveExternals(). 393 //------------------------------------------------------------------ 394 395 //------------------------------------------------------------------ 396 /// Handle a single allocation of a persistent variable 397 /// 398 /// @param[in] persistent_alloc 399 /// The allocation of the persistent variable. 400 /// 401 /// @return 402 /// True on success; false otherwise 403 //------------------------------------------------------------------ 404 bool 405 RewritePersistentAlloc (llvm::Instruction *persistent_alloc); 406 407 //------------------------------------------------------------------ 408 /// The top-level pass implementation 409 /// 410 /// @param[in] basic_block 411 /// The basic block currently being processed. 412 //------------------------------------------------------------------ 413 bool 414 RewritePersistentAllocs (llvm::BasicBlock &basic_block); 415 416 //------------------------------------------------------------------ 417 /// A function-level pass to find all external variables and functions 418 /// used in the IR. Each found external variable is added to the 419 /// struct, and each external function is resolved in place, its call 420 /// replaced with a call to a function pointer whose value is the 421 /// address of the function in the target process. 422 //------------------------------------------------------------------ 423 424 //------------------------------------------------------------------ 425 /// Write an initializer to a memory array of assumed sufficient 426 /// size. 427 /// 428 /// @param[in] data 429 /// A pointer to the data to write to. 430 /// 431 /// @param[in] initializer 432 /// The initializer itself. 433 /// 434 /// @return 435 /// True on success; false otherwise 436 //------------------------------------------------------------------ 437 bool 438 MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); 439 440 //------------------------------------------------------------------ 441 /// Move an internal variable into the static allocation section. 442 /// 443 /// @param[in] global_variable 444 /// The variable. 445 /// 446 /// @return 447 /// True on success; false otherwise 448 //------------------------------------------------------------------ 449 bool 450 MaterializeInternalVariable (llvm::GlobalVariable *global_variable); 451 452 //------------------------------------------------------------------ 453 /// Handle a single externally-defined variable 454 /// 455 /// @param[in] value 456 /// The variable. 457 /// 458 /// @return 459 /// True on success; false otherwise 460 //------------------------------------------------------------------ 461 bool 462 MaybeHandleVariable (llvm::Value *value); 463 464 //------------------------------------------------------------------ 465 /// Handle a single externally-defined symbol 466 /// 467 /// @param[in] symbol 468 /// The symbol. 469 /// 470 /// @return 471 /// True on success; false otherwise 472 //------------------------------------------------------------------ 473 bool 474 HandleSymbol (llvm::Value *symbol); 475 476 //------------------------------------------------------------------ 477 /// Handle a single externally-defined Objective-C class 478 /// 479 /// @param[in] classlist_reference 480 /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" 481 /// where n (if present) is an index. 482 /// 483 /// @return 484 /// True on success; false otherwise 485 //------------------------------------------------------------------ 486 bool 487 HandleObjCClass(llvm::Value *classlist_reference); 488 489 //------------------------------------------------------------------ 490 /// Handle all the arguments to a function call 491 /// 492 /// @param[in] C 493 /// The call instruction. 494 /// 495 /// @return 496 /// True on success; false otherwise 497 //------------------------------------------------------------------ 498 bool 499 MaybeHandleCallArguments (llvm::CallInst *call_inst); 500 501 //------------------------------------------------------------------ 502 /// Resolve variable references in calls to external functions 503 /// 504 /// @param[in] basic_block 505 /// The basic block currently being processed. 506 /// 507 /// @return 508 /// True on success; false otherwise 509 //------------------------------------------------------------------ 510 bool 511 ResolveCalls (llvm::BasicBlock &basic_block); 512 513 //------------------------------------------------------------------ 514 /// Remove calls to __cxa_atexit, which should never be generated by 515 /// expressions. 516 /// 517 /// @param[in] call_inst 518 /// The call instruction. 519 /// 520 /// @return 521 /// True if the scan was successful; false if some operation 522 /// failed 523 //------------------------------------------------------------------ 524 bool 525 RemoveCXAAtExit (llvm::BasicBlock &basic_block); 526 527 //------------------------------------------------------------------ 528 /// The top-level pass implementation 529 /// 530 /// @param[in] basic_block 531 /// The function currently being processed. 532 /// 533 /// @return 534 /// True on success; false otherwise 535 //------------------------------------------------------------------ 536 bool 537 ResolveExternals (llvm::Function &llvm_function); 538 539 //------------------------------------------------------------------ 540 /// A basic block-level pass to excise guard variables from the code. 541 /// The result for the function is passed through Clang as a static 542 /// variable. Static variables normally have guard variables to 543 /// ensure that they are only initialized once. 544 //------------------------------------------------------------------ 545 546 //------------------------------------------------------------------ 547 /// Rewrite a load to a guard variable to return constant 0. 548 /// 549 /// @param[in] guard_load 550 /// The load instruction to zero out. 551 //------------------------------------------------------------------ 552 void 553 TurnGuardLoadIntoZero(llvm::Instruction* guard_load); 554 555 //------------------------------------------------------------------ 556 /// The top-level pass implementation 557 /// 558 /// @param[in] basic_block 559 /// The basic block currently being processed. 560 /// 561 /// @return 562 /// True on success; false otherwise 563 //------------------------------------------------------------------ 564 bool 565 RemoveGuards (llvm::BasicBlock &basic_block); 566 567 //------------------------------------------------------------------ 568 /// A module-level pass to allocate all string literals in a separate 569 /// allocation and redirect references to them. 570 //------------------------------------------------------------------ 571 572 //------------------------------------------------------------------ 573 /// The top-level pass implementation 574 /// 575 /// @return 576 /// True on success; false otherwise 577 //------------------------------------------------------------------ 578 bool 579 ReplaceStrings (); 580 581 //------------------------------------------------------------------ 582 /// A basic block-level pass to find all literals that will be 583 /// allocated as statics by the JIT (in contrast to the Strings, 584 /// which already are statics) and synthesize loads for them. 585 //------------------------------------------------------------------ 586 587 //------------------------------------------------------------------ 588 /// The top-level pass implementation 589 /// 590 /// @param[in] basic_block 591 /// The basic block currently being processed. 592 /// 593 /// @return 594 /// True on success; false otherwise 595 //------------------------------------------------------------------ 596 bool 597 ReplaceStaticLiterals (llvm::BasicBlock &basic_block); 598 599 //------------------------------------------------------------------ 600 /// A function-level pass to make all external variable references 601 /// point at the correct offsets from the void* passed into the 602 /// function. ClangExpressionDeclMap::DoStructLayout() must be called 603 /// beforehand, so that the offsets are valid. 604 //------------------------------------------------------------------ 605 606 //------------------------------------------------------------------ 607 /// The top-level pass implementation 608 /// 609 /// @param[in] llvm_function 610 /// The function currently being processed. 611 /// 612 /// @return 613 /// True on success; false otherwise 614 //------------------------------------------------------------------ 615 bool 616 ReplaceVariables (llvm::Function &llvm_function); 617 618 //------------------------------------------------------------------ 619 /// A module-level pass to remove all global variables from the 620 /// module since it no longer should export or import any symbols. 621 //------------------------------------------------------------------ 622 623 //------------------------------------------------------------------ 624 /// The top-level pass implementation 625 /// 626 /// @param[in] llvm_module 627 /// The module currently being processed. 628 /// 629 /// @return 630 /// True on success; false otherwise 631 //------------------------------------------------------------------ 632 bool 633 StripAllGVs (llvm::Module &llvm_module); 634 635 class StaticDataAllocator { 636 public: 637 StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); GetStream()638 lldb_private::StreamString &GetStream() 639 { 640 return m_stream_string; 641 } 642 lldb::addr_t Allocate(); 643 644 lldb::TargetSP 645 GetTarget(); 646 private: 647 lldb_private::IRExecutionUnit &m_execution_unit; 648 lldb_private::StreamString m_stream_string; 649 lldb::addr_t m_allocation; 650 }; 651 652 /// Flags 653 bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved 654 std::string m_func_name; ///< The name of the function to translate 655 lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) 656 lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. 657 llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. 658 std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the module being processed, or NULL if there is no module. 659 lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls 660 StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings 661 llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type 662 llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type 663 llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. 664 lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed 665 666 llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. 667 bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) 668 669 llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. 670 671 //------------------------------------------------------------------ 672 /// UnfoldConstant operates on a constant [Old] which has just been 673 /// replaced with a value [New]. We assume that new_value has 674 /// been properly placed early in the function, in front of the 675 /// first instruction in the entry basic block 676 /// [FirstEntryInstruction]. 677 /// 678 /// UnfoldConstant reads through the uses of Old and replaces Old 679 /// in those uses with New. Where those uses are constants, the 680 /// function generates new instructions to compute the result of the 681 /// new, non-constant expression and places them before 682 /// FirstEntryInstruction. These instructions replace the constant 683 /// uses, so UnfoldConstant calls itself recursively for those. 684 /// 685 /// @param[in] llvm_function 686 /// The function currently being processed. 687 /// 688 /// @return 689 /// True on success; false otherwise 690 //------------------------------------------------------------------ 691 692 class FunctionValueCache { 693 public: 694 typedef std::function <llvm::Value *(llvm::Function *)> Maker; 695 696 FunctionValueCache (Maker const &maker); 697 ~FunctionValueCache (); 698 llvm::Value *GetValue (llvm::Function *function); 699 private: 700 Maker const m_maker; 701 typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; 702 FunctionValueMap m_values; 703 }; 704 705 FunctionValueCache m_entry_instruction_finder; 706 707 static bool 708 UnfoldConstant (llvm::Constant *old_constant, 709 FunctionValueCache &value_maker, 710 FunctionValueCache &entry_instruction_finder); 711 712 //------------------------------------------------------------------ 713 /// Construct a reference to m_reloc_placeholder with a given type 714 /// and offset. This typically happens after inserting data into 715 /// m_data_allocator. 716 /// 717 /// @param[in] type 718 /// The type of the value being loaded. 719 /// 720 /// @param[in] offset 721 /// The offset of the value from the base of m_data_allocator. 722 /// 723 /// @return 724 /// The Constant for the reference, usually a ConstantExpr. 725 //------------------------------------------------------------------ 726 llvm::Constant * 727 BuildRelocation(llvm::Type *type, 728 uint64_t offset); 729 730 //------------------------------------------------------------------ 731 /// Commit the allocation in m_data_allocator and use its final 732 /// location to replace m_reloc_placeholder. 733 /// 734 /// @param[in] module 735 /// The module that m_data_allocator resides in 736 /// 737 /// @return 738 /// True on success; false otherwise 739 //------------------------------------------------------------------ 740 bool 741 CompleteDataAllocation (); 742 743 }; 744 745 #endif 746