예제 #1
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Operand* ConstantFolder::LoadFromGlobal(Operand* op, const Type* loadType, 
                                        __int64 offset) {
	// If the operand is not a reference to a global variable then we can't do anything,
	// even if the variable may be a constant.
	auto variableRef = op->As<VariableReference>();
	
    if(variableRef == nullptr) {
        return nullptr;
    }

	auto globalVar = variableRef->GetGlobal();

	if(globalVar == nullptr) {
        return nullptr;
    }

	// It's a global variable, now make sure that it's a constant
	// with an initializer that is not a tentative definition.
	if((globalVar->HasInitializer() == false) ||
	   (globalVar->IsConstant() == false)     ||
	    globalVar->IsTentative()) {
        return nullptr;
    }

	// If the offset is negative or larger than the size of the type we give up 
	// (some bytes may be available, but it's not worth the effort trying to extract them).
	if(IsValidOffset(globalVar, loadType, offset) == false) {
		return nullptr;
	}

	// If this is a simple value load it now; this is the common case.
	// Note that we can't load the value if it originates from something like
	// 'int a = (int)&a;', because it's not a compile-time constant.
	// An exception is when we the converted operand is 0 or a null pointer.
    if(globalVar->HasZeroInitializer()) {
		// The variable is initialized only with zeros, so the offset
		// doesn't matter as long as it's valid (and we checked that above).
		__int64 data = 0;
		return GetOperandHavingData((unsigned char*)&data, 8, loadType);
	}

	Initializer* initializer = globalVar->GetInitializer();
    DebugValidator::IsNotNull(initializer);

	if(initializer->IsInitializerList() == false) {
		return LoadFromInitializer(initializer, loadType, offset);
	}

	// We have an initializer list, try to compute the index 
	// of the initializer from which we should load.
	return LoadFromOffset(initializer, globalVar->GetType(), 
                          loadType, offset);
}