示例#1
0
static bool mustPreserve(const claimed_file &F, int i) {
  if (F.syms[i].resolution == LDPR_PREVAILING_DEF)
    return true;
  if (F.syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
    return CannotBeHidden.count(F.syms[i].name);
  return false;
}
示例#2
0
 bool match(StringRef Query) const {
   if (Strings.count(Query))
     return true;
   if (Trigrams.isDefinitelyOut(Query))
     return false;
   return RegEx && RegEx->match(Query);
 }
示例#3
0
/// Print only DIEs that have a certain name.
static void filterByName(const StringSet<> &Names,
                         DWARFContext::cu_iterator_range CUs, raw_ostream &OS) {
  for (const auto &CU : CUs)
    for (const auto &Entry : CU->dies()) {
      DWARFDie Die = {CU.get(), &Entry};
      if (const char *NamePtr = Die.getName(DINameKind::ShortName)) {
        std::string Name =
            (IgnoreCase && !UseRegex) ? StringRef(NamePtr).lower() : NamePtr;
        // Match regular expression.
        if (UseRegex)
          for (auto Pattern : Names.keys()) {
            Regex RE(Pattern, IgnoreCase ? Regex::IgnoreCase : Regex::NoFlags);
            std::string Error;
            if (!RE.isValid(Error)) {
              errs() << "error in regular expression: " << Error << "\n";
              exit(1);
            }
            if (RE.match(Name))
              Die.dump(OS, 0, getDumpOpts());
          }
        // Match full text.
        else if (Names.count(Name))
          Die.dump(OS, 0, getDumpOpts());
      }
    }

}
示例#4
0
static bool mustPreserve(ld_plugin_symbol &Sym) {
  if (Sym.resolution == LDPR_PREVAILING_DEF)
    return true;
  if (Sym.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
    return CannotBeHidden.count(Sym.name);
  return false;
}
示例#5
0
static bool isSubset(const StringSet& subset, const StringSet& superset)
{
  for (auto e : subset) {
    if (superset.count(e) == 0) {
      return false;
    }
  }
  return true;
}
示例#6
0
/// Run internalization on \p TheModule based on symmary analysis.
void llvm::thinLTOInternalizeModule(Module &TheModule,
                                    const GVSummaryMapTy &DefinedGlobals) {
  // Parse inline ASM and collect the list of symbols that are not defined in
  // the current module.
  StringSet<> AsmUndefinedRefs;
  ModuleSymbolTable::CollectAsmSymbols(
      Triple(TheModule.getTargetTriple()), TheModule.getModuleInlineAsm(),
      [&AsmUndefinedRefs](StringRef Name, object::BasicSymbolRef::Flags Flags) {
        if (Flags & object::BasicSymbolRef::SF_Undefined)
          AsmUndefinedRefs.insert(Name);
      });

  // Declare a callback for the internalize pass that will ask for every
  // candidate GlobalValue if it can be internalized or not.
  auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
    // Can't be internalized if referenced in inline asm.
    if (AsmUndefinedRefs.count(GV.getName()))
      return true;

    // Lookup the linkage recorded in the summaries during global analysis.
    const auto &GS = DefinedGlobals.find(GV.getGUID());
    GlobalValue::LinkageTypes Linkage;
    if (GS == DefinedGlobals.end()) {
      // Must have been promoted (possibly conservatively). Find original
      // name so that we can access the correct summary and see if it can
      // be internalized again.
      // FIXME: Eventually we should control promotion instead of promoting
      // and internalizing again.
      StringRef OrigName =
          ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
      std::string OrigId = GlobalValue::getGlobalIdentifier(
          OrigName, GlobalValue::InternalLinkage,
          TheModule.getSourceFileName());
      const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
      if (GS == DefinedGlobals.end()) {
        // Also check the original non-promoted non-globalized name. In some
        // cases a preempted weak value is linked in as a local copy because
        // it is referenced by an alias (IRLinker::linkGlobalValueProto).
        // In that case, since it was originally not a local value, it was
        // recorded in the index using the original name.
        // FIXME: This may not be needed once PR27866 is fixed.
        const auto &GS = DefinedGlobals.find(GlobalValue::getGUID(OrigName));
        assert(GS != DefinedGlobals.end());
        Linkage = GS->second->linkage();
      } else {
        Linkage = GS->second->linkage();
      }
    } else
      Linkage = GS->second->linkage();
    return !GlobalValue::isLocalLinkage(Linkage);
  };

  // FIXME: See if we can just internalize directly here via linkage changes
  // based on the index, rather than invoking internalizeModule.
  llvm::internalizeModule(TheModule, MustPreserveGV);
}
示例#7
0
bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) {

  ValueToValueMapTy VMap;
  Module *M = CloneModule(BD.getProgram(), VMap).release();

  outs() << "Checking for crash with only these named metadata nodes:";
  unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10);
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    outs() << " " << NamedMDs[i];
  if (NumPrint < NamedMDs.size())
    outs() << "... <" << NamedMDs.size() << " total>";
  outs() << ": ";

  // Make a StringMap for faster lookup
  StringSet<> Names;
  for (const std::string &Name : NamedMDs)
    Names.insert(Name);

  // First collect all the metadata to delete in a vector, then
  // delete them all at once to avoid invalidating the iterator
  std::vector<NamedMDNode *> ToDelete;
  ToDelete.reserve(M->named_metadata_size() - Names.size());
  for (auto &NamedMD : M->named_metadata())
    // Always keep a nonempty llvm.dbg.cu because the Verifier would complain.
    if (!Names.count(NamedMD.getName()) &&
        (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0)))
      ToDelete.push_back(&NamedMD);

  for (auto *NamedMD : ToDelete)
    NamedMD->eraseFromParent();

  // Verify that this is still valid.
  legacy::PassManager Passes;
  Passes.add(createVerifierPass(/*FatalErrors=*/false));
  Passes.run(*M);

  // Try running on the hacked up program...
  if (TestFn(BD, M)) {
    BD.setNewProgram(M); // It crashed, keep the trimmed version...
    return true;
  }
  delete M; // It didn't crash, try something else.
  return false;
}
void DifferenceEngine::diff(Module *L, Module *R) {
  StringSet<> LNames;
  SmallVector<std::pair<Function*,Function*>, 20> Queue;

  for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) {
    Function *LFn = &*I;
    LNames.insert(LFn->getName());

    if (Function *RFn = R->getFunction(LFn->getName()))
      Queue.push_back(std::make_pair(LFn, RFn));
    else
      logf("function %l exists only in left module") << LFn;
  }

  for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) {
    Function *RFn = &*I;
    if (!LNames.count(RFn->getName()))
      logf("function %r exists only in right module") << RFn;
  }

  for (SmallVectorImpl<std::pair<Function*,Function*> >::iterator
         I = Queue.begin(), E = Queue.end(); I != E; ++I)
    diff(I->first, I->second);
}
示例#9
0
 bool match(StringRef Query) const {
   return Strings.count(Query) || (RegEx && RegEx->match(Query));
 }
示例#10
0
		bool isEnabled(const std::string& logName) const
		{
			return enableAll || (enabledLogs.count(logName) != 0);
		}
示例#11
0
文件: config.cpp 项目: Abioy/ardb
    bool ArdbConfig::Parse(const Properties& props)
    {
        conf_props = props;
        conf_get_string(props, "home", home);
        if (home.empty())
        {
            home = "../ardb";
        }
        make_dir(home);
        int err = real_path(home, home);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }
        err = access(home.c_str(), R_OK | W_OK);
        if (0 != err)
        {
            err = errno;
            ERROR_LOG("Invalid 'home' config:%s for reason:%s", home.c_str(), strerror(err));
            return false;
        }

        setenv("ARDB_HOME", home.c_str(), 1);
        replace_env_var(const_cast<Properties&>(props));

        conf_get_string(props, "pidfile", pidfile);

        conf_get_int64(props, "tcp-keepalive", tcp_keepalive);
        conf_get_int64(props, "timeout", timeout);
        conf_get_int64(props, "unixsocketperm", unixsocketperm);
        conf_get_int64(props, "slowlog-log-slower-than", slowlog_log_slower_than);
        conf_get_int64(props, "slowlog-max-len", slowlog_max_len);
        conf_get_int64(props, "maxclients", max_clients);
        Properties::const_iterator listen_it = props.find("listen");
        if (listen_it != props.end())
        {
            const ConfItemsArray& cs = listen_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                if (cs[i].size() != 1)
                {
                    WARN_LOG("Invalid config 'listen'");
                }
                else
                {
                    const std::string& str = cs[i][0];
                    listen_addresses.push_back(str);
                }
            }
        }
        if (listen_addresses.empty())
        {
            listen_addresses.push_back("0.0.0.0:16379");
        }
        Properties::const_iterator tp_it = props.find("thread-pool-size");
        if (tp_it != props.end())
        {
            const ConfItemsArray& cs = tp_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                uint32 size = 0;
                if (cs[i].size() != 1 || !string_touint32(cs[i][0], size))
                {
                    WARN_LOG("Invalid config 'thread-pool-size'");
                }
                else
                {
                    thread_pool_sizes.push_back((int64) size);
                }
            }
        }
        Properties::const_iterator qp_it = props.find("qps-limit");
        if (qp_it != props.end())
        {
            const ConfItemsArray& cs = qp_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                uint32 limit = 0;
                if (cs[i].size() != 1 || !string_touint32(cs[i][0], limit))
                {
                    WARN_LOG("Invalid config 'qps-limit'");
                }
                else
                {
                    qps_limits.push_back((int64) limit);
                }
            }
        }
        thread_pool_sizes.resize(listen_addresses.size());
        qps_limits.resize(listen_addresses.size());

        conf_get_string(props, "data-dir", data_base_path);
        conf_get_string(props, "backup-dir", backup_dir);
        conf_get_string(props, "repl-dir", repl_data_dir);
        make_dir(repl_data_dir);
        make_dir(backup_dir);

        err = real_path(repl_data_dir, repl_data_dir);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'repl-dir' config:%s for reason:%s", repl_data_dir.c_str(), strerror(err));
            return false;
        }

        std::string backup_file_format;
        conf_get_string(props, "backup-file-format", backup_file_format);
        if (!strcasecmp(backup_file_format.c_str(), "redis"))
        {
            backup_redis_format = true;
        }

        conf_get_string(props, "zookeeper-servers", zookeeper_servers);

        conf_get_string(props, "loglevel", loglevel);
        conf_get_string(props, "logfile", logfile);
        conf_get_bool(props, "daemonize", daemonize);

        conf_get_int64(props, "repl-backlog-size", repl_backlog_size);
        conf_get_int64(props, "repl-ping-slave-period", repl_ping_slave_period);
        conf_get_int64(props, "repl-timeout", repl_timeout);
        conf_get_int64(props, "repl-state-persist-period", repl_state_persist_period);
        conf_get_int64(props, "repl-backlog-ttl", repl_backlog_time_limit);
        conf_get_bool(props, "repl-disable-tcp-nodelay", repl_disable_tcp_nodelay);
        conf_get_int64(props, "lua-time-limit", lua_time_limit);

        conf_get_int64(props, "hash-max-ziplist-entries", hash_max_ziplist_entries);
        conf_get_int64(props, "hash_max-ziplist-value", hash_max_ziplist_value);
        conf_get_int64(props, "set-max-ziplist-entries", set_max_ziplist_entries);
        conf_get_int64(props, "set-max-ziplist-value", set_max_ziplist_value);
        conf_get_int64(props, "list-max-ziplist-entries", list_max_ziplist_entries);
        conf_get_int64(props, "list-max-ziplist-value", list_max_ziplist_value);
        conf_get_int64(props, "zset-max-ziplist-entries", zset_max_ziplist_entries);
        conf_get_int64(props, "zset_max_ziplist_value", zset_max_ziplist_value);

        conf_get_int64(props, "L1-zset-max-cache-size", L1_zset_max_cache_size);
        conf_get_int64(props, "L1-set-max-cache-size", L1_set_max_cache_size);
        conf_get_int64(props, "L1-hash-max-cache-size", L1_hash_max_cache_size);
        conf_get_int64(props, "L1-list-max-cache-size", L1_list_max_cache_size);
        conf_get_int64(props, "L1-string-max-cache-size", L1_string_max_cache_size);

        conf_get_bool(props, "L1-zset-read-fill-cache", L1_zset_read_fill_cache);
        conf_get_bool(props, "L1-zset-seek-load-cache", L1_zset_seek_load_cache);
        conf_get_bool(props, "L1-set-read-fill-cache", L1_set_read_fill_cache);
        conf_get_bool(props, "L1-set-seek-load-cache", L1_set_seek_load_cache);
        conf_get_bool(props, "L1-hash-read-fill-cache", L1_hash_read_fill_cache);
        conf_get_bool(props, "L1-hash-seek-load-cache", L1_hash_seek_load_cache);
        conf_get_bool(props, "L1-list-read-fill-cache", L1_list_read_fill_cache);
        conf_get_bool(props, "L1-list-seek-load-cache", L1_list_seek_load_cache);
        conf_get_bool(props, "L1-string-read-fill-cache", L1_string_read_fill_cache);

        conf_get_int64(props, "hll-sparse-max-bytes", hll_sparse_max_bytes);

        conf_get_bool(props, "slave-read-only", slave_readonly);
        conf_get_bool(props, "slave-serve-stale-data", slave_serve_stale_data);
        conf_get_int64(props, "slave-priority", slave_priority);
        conf_get_bool(props, "slave-ignore-expire", slave_ignore_expire);
        conf_get_bool(props, "slave-ignore-del", slave_ignore_del);

        std::string slaveof;
        if (conf_get_string(props, "slaveof", slaveof))
        {
            std::vector<std::string> ss = split_string(slaveof, ":");
            if (ss.size() == 2)
            {
                master_host = ss[0];
                if (!string_touint32(ss[1], master_port))
                {
                    master_host = "";
                    WARN_LOG("Invalid 'slaveof' config.");
                }
            }
            else
            {
                WARN_LOG("Invalid 'slaveof' config.");
            }
        }

        std::string include_dbs, exclude_dbs;
        repl_includes.clear();
        repl_excludes.clear();
        conf_get_string(props, "replicate-include-db", include_dbs);
        conf_get_string(props, "replicate-exclude-db", exclude_dbs);
        if (0 != split_uint32_array(include_dbs, "|", repl_includes))
        {
            ERROR_LOG("Invalid 'replicate-include-db' config.");
            repl_includes.clear();
        }
        if (0 != split_uint32_array(exclude_dbs, "|", repl_excludes))
        {
            ERROR_LOG("Invalid 'replicate-exclude-db' config.");
            repl_excludes.clear();
        }

        if (data_base_path.empty())
        {
            data_base_path = ".";
        }
        make_dir(data_base_path);
        err = real_path(data_base_path, data_base_path);
        if (0 != err)
        {
            ERROR_LOG("Invalid 'data-dir' config:%s for reason:%s", data_base_path.c_str(), strerror(err));
            return false;
        }
        conf_get_string(props, "additional-misc-info", additional_misc_info);

        conf_get_string(props, "requirepass", requirepass);

        Properties::const_iterator fit = props.find("rename-command");
        if (fit != props.end())
        {
            rename_commands.clear();
            StringSet newcmdset;
            const ConfItemsArray& cs = fit->second;
            ConfItemsArray::const_iterator cit = cs.begin();
            while (cit != cs.end())
            {
                if (cit->size() != 2 || newcmdset.count(cit->at(1)) > 0)
                {
                    ERROR_LOG("Invalid 'rename-command' config.");
                }
                else
                {
                    rename_commands[cit->at(0)] = cit->at(1);
                    newcmdset.insert(cit->at(1));
                }
                cit++;
            }
        }

        conf_get_int64(props, "compact-min-interval", compact_min_interval);
        conf_get_int64(props, "compact-max-interval", compact_max_interval);
        conf_get_int64(props, "compact-after-write", compact_trigger_write_count);
        conf_get_bool(props, "compact-enable", compact_enable);

        conf_get_int64(props, "reply-pool-size", reply_pool_size);
        conf_get_bool(props, "replace-all-for-multi-sadd", replace_for_multi_sadd);
        conf_get_bool(props, "replace-all-for-hmset", replace_for_hmset);

        conf_get_int64(props, "slave-client-output-buffer-limit", slave_client_output_buffer_limit);
        conf_get_int64(props, "pubsub-client-output-buffer-limit", pubsub_client_output_buffer_limit);

        conf_get_bool(props, "scan-redis-compatible", scan_redis_compatible);
        conf_get_int64(props, "scan-cursor-expire-after", scan_cursor_expire_after);

        conf_get_int64(props, "max-string-bitset-value", max_string_bitset_value);

        conf_get_int64(props, "databases", maxdb);

        conf_get_bool(props, "lua-exec-atomic", lua_exec_atomic);

        trusted_ip.clear();
        Properties::const_iterator ip_it = props.find("trusted-ip");
        if (ip_it != props.end())
        {
            const ConfItemsArray& cs = ip_it->second;
            for (uint32 i = 0; i < cs.size(); i++)
            {
                trusted_ip.insert(cs[i][0]);
            }
        }
        if (!verify_config(*this))
        {
            return false;
        }

        ArdbLogger::SetLogLevel(loglevel);
        return true;
    }
示例#12
0
static void convertParametersToRegisters(
	const BasicBlockMap& newBlocks, ir::IRKernel& kernel,
	ir::ControlFlowGraph::instruction_iterator callIterator,
	const ir::IRKernel& calledKernel)
{
	typedef std::unordered_map<std::string,	ir::PTXOperand> OperandMap;
	typedef std::unordered_set<std::string> StringSet;

	reportE(REPORT_DETAILS, "   Converting parameters to registers...");
	
	// Get a map from argument name to register in the calling function
	OperandMap  argumentMap;
	StringSet   bitBucketArguments;
	
	auto argument = calledKernel.arguments.begin();
	
	ir::PTXInstruction& call = static_cast<ir::PTXInstruction&>(**callIterator);
	
	for(auto parameter = call.d.array.begin();
		parameter != call.d.array.end(); ++parameter, ++argument)
	{
		if(parameter->addressMode == ir::PTXOperand::BitBucket)
		{
			bitBucketArguments.insert(argument->name);
			continue;
		}

		assert(argument != calledKernel.arguments.end());
		assert(parameter->addressMode == ir::PTXOperand::Register ||
			parameter->addressMode == ir::PTXOperand::Immediate);
		assert(argumentMap.count(argument->name) == 0);
		assert(argument->returnArgument);

		argumentMap.insert(std::make_pair(argument->name, *parameter));
	}

	for(auto parameter = call.b.array.begin();
		parameter != call.b.array.end(); ++parameter, ++argument)
	{
		if(parameter->addressMode == ir::PTXOperand::BitBucket)
		{
			bitBucketArguments.insert(argument->name);
			continue;
		}

		assert(argument != calledKernel.arguments.end());
		assert(parameter->addressMode == ir::PTXOperand::Register ||
			parameter->addressMode == ir::PTXOperand::Immediate);
		assert(argumentMap.count(argument->name) == 0);
		assert(!argument->returnArgument);

		argumentMap.insert(std::make_pair(argument->name, *parameter));
	}
	
	// Convert all stores to that parameter to moves to the associated register
	for(auto block = newBlocks.begin(); block != newBlocks.end(); ++block)
	{
		for(auto instruction = block->second->instructions.begin();
			instruction != block->second->instructions.end(); ++instruction)
		{
			ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(
				**instruction);
		
			if(ptx.opcode        != ir::PTXInstruction::St)    continue;
			if(ptx.addressSpace  != ir::PTXInstruction::Param) continue;
			if(ptx.d.addressMode != ir::PTXOperand::Address)   continue;
			
			if(bitBucketArguments.count(ptx.d.identifier))
			{
				delete *instruction;
				instruction = --block->second->instructions.erase(instruction);
				
				continue;
			}
			
			auto argument = argumentMap.find(ptx.d.identifier);
			
			if(argument == argumentMap.end()) continue;

			ptx.type = argument->second.type;
			ptx.pg   = call.pg;
			ptx.d    = argument->second;
				
			if(argument->second.addressMode == ir::PTXOperand::Register)
			{
				// If the types match, it is a move
				if(argument->second.type == ptx.d.type)
				{
					ptx.opcode = ir::PTXInstruction::Mov;
				}
				else
				{
					// otherwise, we need a cast
					ptx.opcode   = ir::PTXInstruction::Cvt;
					ptx.modifier = ir::PTXInstruction::Modifier_invalid;
				}
			}
			else
			{
				assert(argument->second.addressMode ==
					ir::PTXOperand::Immediate);
		
				ptx.opcode = ir::PTXInstruction::Mov;
			}
		}
	}
	
	// Convert all loads from that parameter to moves from the register
	for(auto block = newBlocks.begin(); block != newBlocks.end(); ++block)
	{
		for(auto instruction = block->second->instructions.begin();
			instruction != block->second->instructions.end(); ++instruction)
		{
			ir::PTXInstruction& ptx = static_cast<ir::PTXInstruction&>(
				**instruction);
	
			if(ptx.opcode        != ir::PTXInstruction::Ld)    continue;
			if(ptx.addressSpace  != ir::PTXInstruction::Param) continue;
			if(ptx.a.addressMode != ir::PTXOperand::Address)   continue;
			
			if(bitBucketArguments.count(ptx.a.identifier))
			{
				delete *instruction;
				instruction = --block->second->instructions.erase(instruction);
				
				continue;
			}
			
			auto argument = argumentMap.find(ptx.a.identifier);
			
			if(argument == argumentMap.end()) continue;
			
			assert(ptx.d.addressMode == ir::PTXOperand::Register);
			
			ptx.type = argument->second.type;			
			ptx.pg   = call.pg;
			ptx.a    = argument->second;
			
			// If the types match, it is a move
			if(ptx.type == ptx.a.type)
			{
				ptx.opcode = ir::PTXInstruction::Mov;
			}
			else
			{
				// otherwise, we need a cast
				ptx.opcode        = ir::PTXInstruction::Cvt;
				ptx.modifier      = ir::PTXInstruction::Modifier_invalid;
			}
		}
	}
}
	void ATIExecutableKernel::initializeSharedMemory()
	{
		report("Allocating shared memory");

		typedef std::unordered_map<std::string, size_t> AllocationMap;
		typedef std::unordered_set<std::string> StringSet;
		typedef std::deque<ir::PTXOperand*> OperandVector;
		typedef std::unordered_map<std::string,
				ir::Module::GlobalMap::const_iterator> GlobalMap;

		AllocationMap map;
		GlobalMap sharedGlobals;
		StringSet external;
		OperandVector externalOperands;

		unsigned int externalAlignment = 1;
		size_t sharedSize = 0;

		assert(module != 0);

		// global shared variables
		ir::Module::GlobalMap globals = module->globals();
		ir::Module::GlobalMap::const_iterator global;
		for (global = globals.begin() ; global != globals.end() ; global++)
		{
			ir::PTXStatement statement = global->second.statement;
			if (statement.directive == ir::PTXStatement::Shared)
			{
				if (statement.attribute == ir::PTXStatement::Extern)
				{
					report("Found global external shared variable \""
							<< statement.name << "\"");

					assertM(external.count(statement.name) == 0,
							"External global \"" << statement.name
							<< "\" declared more than once.");

					external.insert(statement.name);
					externalAlignment = std::max(externalAlignment,
							(unsigned int)statement.alignment);
					externalAlignment = std::max(externalAlignment,
							ir::PTXOperand::bytes(statement.type));
				} else {
					report("Found global shared variable \"" 
							<< statement.name << "\"");
					sharedGlobals.insert(
							std::make_pair(statement.name, global));
				}
			}
		}

		// local shared variables	
		LocalMap::const_iterator local;
		for (local = locals.begin() ; local != locals.end() ; local++)
		{
			if (local->second.space == ir::PTXInstruction::Shared)
			{
				if (local->second.attribute == ir::PTXStatement::Extern)
				{
					report("Found local external shared variable \"" 
							<< local->second.name << "\"");

					assertM(external.count(local->second.name) == 0,
							"External local \"" << local->second.name
							<< "\" declared more than once.");

					external.insert(local->second.name);
					externalAlignment = std::max(externalAlignment,
							(unsigned int)local->second.alignment);
					externalAlignment = std::max(externalAlignment,
							ir::PTXOperand::bytes(local->second.type));
				} else
				{
					report("Allocating local shared variable \""
							<< local->second.name << "\" of size "
							<< local->second.getSize());

					_pad(sharedSize, local->second.alignment);
					map.insert(std::make_pair(local->second.name, sharedSize));
					sharedSize += local->second.getSize();
				}
			}
		}

		ir::ControlFlowGraph::iterator block;
		for (block = cfg()->begin() ; block != cfg()->end() ; block++)
		{
			ir::ControlFlowGraph::InstructionList insts = block->instructions;
			ir::ControlFlowGraph::InstructionList::iterator inst;
			for (inst = insts.begin() ; inst != insts.end() ; inst++)
			{
				ir::PTXInstruction& ptx = 
					static_cast<ir::PTXInstruction&>(**inst);

				if (ptx.opcode == ir::PTXInstruction::Mov ||
						ptx.opcode == ir::PTXInstruction::Ld ||
						ptx.opcode == ir::PTXInstruction::St)
				{
					ir::PTXOperand* operands[] = {&ptx.d, &ptx.a, &ptx.b, 
						&ptx.c};

					for (unsigned int i = 0 ; i != 4 ; i++)
					{
						ir::PTXOperand* operand = operands[i];

						if (operand->addressMode == ir::PTXOperand::Address)
						{
							StringSet::iterator si = 
								external.find(operand->identifier);
							if (si != external.end())
							{
								report("For instruction \""
										<< ptx.toString()
										<< "\", mapping shared label \"" << *si
										<< "\" to external shared memory.");
								externalOperands.push_back(operand);
								continue;
							}

							GlobalMap::iterator gi = 
								sharedGlobals.find(operand->identifier);
							if (gi != sharedGlobals.end())
							{
								ir::Module::GlobalMap::const_iterator it = 
									gi->second;
								sharedGlobals.erase(gi);

								report("Allocating global shared variable \""
										<< it->second.statement.name << "\"");

								map.insert(std::make_pair(
											it->second.statement.name, 
											sharedSize));
								sharedSize += it->second.statement.bytes();
							}

							AllocationMap::iterator mapping = 
								map.find(operand->identifier);
							if (mapping != map.end())
							{
								report("For instruction " << ptx.toString()
										<< ", mapping shared label "
										<< mapping->first << " to " << 
										mapping->second);

								operand->addressMode = 
									ir::PTXOperand::Immediate;
								operand->imm_uint = mapping->second;
							}
						}
					}
				}
			}
		}

		_pad(sharedSize, externalAlignment);

		report("Mapping external shared variables.");
		OperandVector::iterator operand;
		for (operand = externalOperands.begin() ; 
				operand != externalOperands.end() ; operand++)
		{
			report("Mapping external shared label \""
					<< (*operand)->identifier << "\" to " << sharedSize);
			(*operand)->addressMode = ir::PTXOperand::Immediate;
			(*operand)->imm_uint = sharedSize;
		}

		// allocate shared memory object
		_sharedMemorySize = sharedSize;

		report("Total shared memory size is " << _sharedMemorySize);
	}