Jelajahi Sumber

Fixed issues with global var addresses in const arrays

Brian Fiete 5 tahun lalu
induk
melakukan
b30a72719c

+ 15 - 1
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -680,7 +680,8 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 				globalVariable->mIsTLS = isTLS;
 				globalVariable->mAlign = varType->mAlign;
 				globalVariable->mUnnamedAddr = false;				
-				BF_ASSERT(varType->mAlign > 0);
+				if (initializer != NULL)
+					BF_ASSERT(varType->mAlign > 0);
 
 				SetResult(streamId, globalVariable);
 				beValue = globalVariable;
@@ -721,6 +722,19 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 			BE_MEM_END("ParamType_Const_GEP32_2");
 			return;
 		}
+		else if (constType == BfConstType_ExtractValue)
+		{
+			CMD_PARAM(BeConstant*, target);
+			CMD_PARAM(int, idx0);			
+			
+			auto gepConstant = mBeModule->mAlloc.Alloc<BeExtractValueConstant>();
+			gepConstant->mTarget = target;
+			gepConstant->mIdx0 = idx0;			
+
+			beValue = gepConstant;
+			BE_MEM_END("ParamType_Const_ExtractValue");
+			return;
+		}
 		else if (constType == BfConstType_PtrToInt)
 		{
 			CMD_PARAM(BeConstant*, target);

+ 53 - 7
IDEHelper/Backend/BeMCContext.cpp

@@ -2258,9 +2258,9 @@ BeMCOperand BeMCContext::GetOperand(BeValue* value, bool allowMetaResult, bool a
 		}
 	case BeGEPConstant::TypeId:
 		{
-			auto gepConstant = (BeGEPConstant*)value;
+		auto gepConstant = (BeGEPConstant*)value;
 
-			auto mcVal = GetOperand(gepConstant->mTarget);			
+		auto mcVal = GetOperand(gepConstant->mTarget);
 
 			BePointerType* ptrType = (BePointerType*)GetType(mcVal);
 			BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
@@ -2297,6 +2297,21 @@ BeMCOperand BeMCContext::GetOperand(BeValue* value, bool allowMetaResult, bool a
 			return result;
 		}
 		break;
+	case BeExtractValueConstant::TypeId:		
+		{
+			// Note: this only handles zero-aggregates
+			auto extractConstant = (BeExtractValueConstant*)value;
+			auto elementType = extractConstant->GetType();
+
+			auto mcVal = GetOperand(extractConstant->mTarget);
+			auto valType = GetType(mcVal);
+
+			BeConstant beConstant;
+			beConstant.mType = elementType;
+			beConstant.mUInt64 = 0;
+			return GetOperand(&beConstant);	
+		}
+		break;
 	case BeFunction::TypeId:
 		{
 			auto sym = mCOFFObject->GetSymbol(value);
@@ -9887,7 +9902,7 @@ bool BeMCContext::DoLegalization()
 					}
 					
 					if (arg0Type->IsComposite())
-					{
+					{						
 						if (arg1.mKind == BeMCOperandKind_Immediate_i64)
 						{
 							// This is just a "zero initializer" marker
@@ -12185,8 +12200,10 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
 	BF_ASSERT(src.mKind == BeMCOperandKind_ConstAgg);
 	auto aggConstant = src.mConstant;
 
-	Array<uint8> dataVec;
-	aggConstant->GetData(dataVec);
+	BeConstData constData;
+	aggConstant->GetData(constData);
+
+	Array<uint8>& dataVec = constData.mData;
 	
 	int memSize = dataVec.size();
 	int curOfs = 0;
@@ -12254,7 +12271,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
 		}
 		else
 		{
-			// movabs r11, val32
+			// movabs r11, val64
 			Emit(0x49); Emit(0xBB);
 			mOut.Write((int64)val);
 		}
@@ -12362,6 +12379,30 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
 		Emit(0x89 - 1);
 		EmitModRMRel(EncodeRegNum(X64Reg_R11B), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
 	}
+
+	for (auto constVal : constData.mConsts)
+	{
+		BeMCRelocation reloc;
+
+		// movabs r11, val64
+		Emit(0x49); Emit(0xBB);
+		
+		reloc.mKind = BeMCRelocationKind_ADDR64;
+		reloc.mOffset = mOut.GetPos();
+
+		auto operand = GetOperand(constVal.mConstant);
+
+		reloc.mSymTableIdx = operand.mSymbolIdx;
+		mCOFFObject->mTextSect.mRelocs.push_back(reloc);
+		mTextRelocs.push_back((int)mCOFFObject->mTextSect.mRelocs.size() - 1);
+
+		mOut.Write((int64)0);
+
+		// mov <dest+curOfs>, R11
+		EmitREX(BeMCOperand::FromReg(X64Reg_R11), dest, true);
+		Emit(0x89);
+		EmitModRMRel(EncodeRegNum(X64Reg_R11), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + constVal.mIdx);
+	}
 }
 
 void BeMCContext::DoCodeEmission()
@@ -13166,6 +13207,11 @@ void BeMCContext::DoCodeEmission()
 				{					
 					if (inst->mArg1.mKind == BeMCOperandKind_ConstAgg)
 					{
+						if (mDebugging)
+						{
+							NOP;
+						}
+
 						EmitAggMov(inst->mArg0, inst->mArg1);
 						break;
 					}
@@ -15487,7 +15533,7 @@ void BeMCContext::Generate(BeFunction* function)
 	mDbgPreferredRegs[32] = X64Reg_R8;*/
 
 	//mDbgPreferredRegs[8] = X64Reg_RAX;
-	//mDebugging = (function->mName == "?Main@Program@bf@@SAXPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z");
+	mDebugging = (function->mName == "?Hey@Blurg@bf@@SAXXZ");
 // 		|| (function->mName == "?__BfStaticCtor@roboto_font@Drawing@ClassicUO_assistant@bf@@SAXXZ")
 // 		|| (function->mName == "?Hey@Blurg@bf@@SAXXZ")
 // 		;

+ 45 - 7
IDEHelper/Backend/BeModule.cpp

@@ -445,25 +445,25 @@ BeType* BeConstant::GetType()
 	return mType;
 }
 
-void BeConstant::GetData(Array<uint8>& data)
+void BeConstant::GetData(BeConstData& data)
 {
 	auto type = GetType();
-	while ((((int)data.size()) % type->mAlign) != 0)
-		data.push_back(0);
+	while ((((int)data.mData.size()) % type->mAlign) != 0)
+		data.mData.push_back(0);
 
 	if (type->IsComposite())
 	{
 		for (int i = 0; i < type->mSize; i++)
-			data.push_back(0); // Aggregate
+			data.mData.push_back(0); // Aggregate
 	}
 	else if (type->mTypeCode == BeTypeCode_Float)
 	{
 		float f = mDouble;
-		data.Insert(data.mSize, (uint8*)&f, sizeof(float));
+		data.mData.Insert(data.mData.mSize, (uint8*)&f, sizeof(float));
 	}
 	else
 	{		
-		data.Insert(data.mSize, &mUInt8, type->mSize);
+		data.mData.Insert(data.mData.mSize, &mUInt8, type->mSize);
 	}
 }
 
@@ -491,7 +491,7 @@ void BeConstant::HashContent(BeHashContext& hashCtx)
 		BF_FATAL("NotImpl");
 }
 
-void BeStructConstant::GetData(Array<uint8>& data)
+void BeStructConstant::GetData(BeConstData& data)
 {
 	for (auto val : mMemberValues)
 		val->GetData(data);
@@ -519,6 +519,27 @@ BeType* BeGEPConstant::GetType()
 	}
 }
 
+BeType* BeExtractValueConstant::GetType()
+{
+	BeType* type = mTarget->GetType();	
+	if (type->mTypeCode == BeTypeCode_SizedArray)
+	{
+		BeSizedArrayType* arrayType = (BeSizedArrayType*)type;
+		BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray);
+		return arrayType->mContext->GetPointerTo(arrayType->mElementType);
+	}
+	/*else if (ptrType->mElementType->IsPointer())
+	{
+		return ptrType->mElementType;
+	}*/
+	else
+	{
+		BeStructType* structType = (BeStructType*)type;
+		BF_ASSERT(structType->mTypeCode == BeTypeCode_Struct);
+		return structType->mContext->GetPointerTo(structType->mMembers[mIdx0].mType);
+	}
+}
+
 BeType* BeGlobalVariable::GetType()
 {
 	//if (mIsConstant)
@@ -1240,6 +1261,14 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
 		return;
 	}
 
+	if (auto constantExtract = BeValueDynCast<BeExtractValueConstant>(value))
+	{
+		str += "ConstExtract ";
+		ToString(str, constantExtract->mTarget);
+		str += StrFormat(" %d", constantExtract->mIdx0);
+		return;
+	}
+
 	if (auto arg = BeValueDynCast<BeArgument>(value))
 	{
 		auto activeFunction = arg->mModule->mActiveFunction;
@@ -1313,6 +1342,15 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
 		return;
 	}
 
+	if (auto constant = BeValueDynCast<BeExtractValueConstant>(value))
+	{
+		ToString(str, constant->GetType());
+		str += " extract (";
+		ToString(str, constant->mTarget);
+		str += StrFormat(", %d)", constant->mIdx0);
+		return;
+	}
+
 	if (auto constant = BeValueDynCast<BeStructConstant>(value))
 	{		
 		ToString(str, constant->GetType());

+ 44 - 3
IDEHelper/Backend/BeModule.h

@@ -271,6 +271,20 @@ class BeDbgLoc;
 class BeMDNode;
 class BeGlobalVariable;
 
+class BeConstant;
+
+struct BeConstData
+{
+	struct ConstantEntry
+	{
+		int mIdx;
+		BeConstant* mConstant;
+	};
+
+	Array<uint8> mData;
+	Array<ConstantEntry> mConsts;
+};
+
 class BeConstant : public BeValue
 {
 public:
@@ -304,7 +318,7 @@ public:
 	}
 
 	virtual BeType* GetType();	
-	virtual void GetData(Array<uint8>& data);
+	virtual void GetData(BeConstData& data);
 	virtual void HashContent(BeHashContext& hashCtx) override;
 };
 
@@ -319,6 +333,11 @@ public:
 		mType->HashReference(hashCtx);
 		mTarget->HashReference(hashCtx);
 	}
+
+	virtual void GetData(BeConstData& data) override
+	{
+		mTarget->GetData(data);
+	}
 };
 
 class BeGEPConstant : public BeConstant
@@ -339,6 +358,22 @@ public:
 	}
 };
 
+class BeExtractValueConstant : public BeConstant
+{
+public:
+	BE_VALUE_TYPE(BeExtractValueConstant, BeConstant);
+	int mIdx0;	
+
+	virtual BeType* GetType();
+
+	virtual void HashContent(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		mTarget->HashReference(hashCtx);
+		hashCtx.Mixin(mIdx0);		
+	}
+};
+
 class BeStructConstant : public BeConstant
 {
 public:
@@ -346,7 +381,7 @@ public:
 
 	SizedArray<BeConstant*, 4> mMemberValues;
 
-	virtual void GetData(Array<uint8>& data) override;
+	virtual void GetData(BeConstData& data) override;
 
 	virtual void HashContent(BeHashContext& hashCtx) override
 	{
@@ -399,6 +434,12 @@ public:
 		hashCtx.Mixin(mAlign);
 		hashCtx.Mixin(mUnnamedAddr);
 	}	
+
+	virtual void GetData(BeConstData& data) override
+	{
+		data.mConsts.Add({ (int)data.mData.size(), this });
+		data.mData.Insert(data.mData.size(), (uint8)0, 8);				
+	}
 };
 
 class BeFunctionParam
@@ -679,7 +720,7 @@ public:
 		hashCtx.Mixin(TypeId);
 		mValue->HashReference(hashCtx);
 		mToType->HashReference(hashCtx);
-	}
+	}	
 };
 
 class BeNegInst : public BeInst

+ 1 - 1
IDEHelper/Compiler/BfCompiler.cpp

@@ -5911,7 +5911,7 @@ void BfCompiler::CompileReified()
 
 		auto typeOptions = scratchModule->GetTypeOptions(typeDef);
 		if (typeOptions != NULL)
-			typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);		
+			isAlwaysInclude = typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
 
 		if (typeDef->mProject->IsTestProject())
 		{

+ 22 - 1
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -17660,9 +17660,30 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
 				return;
 			}
 
+			if (mResult.mValue.IsConst())
+			{
+				auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
+				bool isNull = constant->mTypeCode == BfTypeCode_NullPtr;
+
+				if (constant->mConstType == BfConstType_ExtractValue)
+				{
+					auto constExtract = (BfConstantExtractValue*)constant;
+					auto targetConst = mModule->mBfIRBuilder->GetConstantById(constExtract->mTarget);
+					if (targetConst->mConstType == BfConstType_AggZero)
+						isNull = true;
+				}
+
+				if (isNull)
+				{
+					mModule->Warn(0, "Cannot dereference a null pointer", unaryOpExpr);
+					mResult = mModule->GetDefaultTypedValue(mResult.mType, false, BfDefaultValueKind_Addr);
+					mResult = mModule->LoadValue(mResult);
+				}
+			}
+
 			auto derefTarget = mModule->LoadValue(mResult);
 
-			BfPointerType* pointerType = (BfPointerType*)derefTarget.mType;				
+			BfPointerType* pointerType = (BfPointerType*)derefTarget.mType;
 			auto resolvedType = mModule->ResolveType(pointerType->mElementType);
 			if (resolvedType == NULL)
 			{

+ 64 - 3
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -578,6 +578,8 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 {	
 	BfConstant* copiedConst = NULL;
 	
+	int chunkId = -1;
+
 	if ((fromConst->mConstType == BfConstType_BitCast) || (fromConst->mConstType == BfConstType_BitCastNull))
 	{	
 		//HMM- This should never happen?  Is that true?  We always just store string refs as ints
@@ -595,6 +597,21 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 		ptrToInt->mToType = fromConstBitCast->mToType;
 		copiedConst = (BfConstant*)ptrToInt;
 	}
+	else if (fromConst->mConstType == BfConstType_GlobalVar)
+	{
+		auto fromGlobalVar = (BfGlobalVar*)fromConst;
+		auto constGV = mTempAlloc.Alloc<BfGlobalVar>();
+		chunkId = mTempAlloc.GetChunkedId(constGV);
+		constGV->mStreamId = -1;
+		constGV->mConstType = BfConstType_GlobalVar;
+		constGV->mType = fromGlobalVar->mType;
+		constGV->mIsConst = fromGlobalVar->mIsConst;
+		constGV->mLinkageType = fromGlobalVar->mLinkageType;
+		constGV->mInitializer = fromGlobalVar->mInitializer;
+		constGV->mName = AllocStr(fromGlobalVar->mName);
+		constGV->mIsTLS = fromGlobalVar->mIsTLS;
+		copiedConst = (BfConstant*)constGV;
+	}
 	else if (fromConst->mConstType == BfConstType_GEP32_2)
 	{
 		auto fromConstGEP = (BfConstantGEP32_2*)fromConst;
@@ -603,8 +620,21 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 		auto constGEP = mTempAlloc.Alloc<BfConstantGEP32_2>();
 		constGEP->mConstType = BfConstType_GEP32_2;
 		constGEP->mTarget = copiedTarget.mId;
+		constGEP->mIdx0 = fromConstGEP->mIdx0;
+		constGEP->mIdx1 = fromConstGEP->mIdx1;
 		copiedConst = (BfConstant*)constGEP;		
 	}
+	else if (fromConst->mConstType == BfConstType_ExtractValue)
+	{
+		auto fromConstGEP = (BfConstantExtractValue*)fromConst;
+		auto fromTarget = fromHolder->GetConstantById(fromConstGEP->mTarget);
+		auto copiedTarget = CreateConst(fromTarget, fromHolder);
+		auto constGEP = mTempAlloc.Alloc<BfConstantExtractValue>();
+		constGEP->mConstType = BfConstType_ExtractValue;
+		constGEP->mTarget = copiedTarget.mId;
+		constGEP->mIdx0 = fromConstGEP->mIdx0;
+		copiedConst = (BfConstant*)constGEP;
+	}
 	else if (fromConst->mConstType == BfConstType_TypeOf)
 	{
 		auto typeOf = (BfTypeOf_Const*)fromConst;
@@ -647,7 +677,10 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 	
 	BfIRValue retVal;
 	retVal.mFlags = BfIRValueFlags_Const;
-	retVal.mId = mTempAlloc.GetChunkedId(copiedConst);	
+	if (chunkId == -1)
+		chunkId = mTempAlloc.GetChunkedId(copiedConst);
+	retVal.mId = chunkId;	
+	BF_ASSERT(retVal.mId >= 0);
 #ifdef CHECK_CONSTHOLDER
 	retVal.mHolder = this;
 #endif
@@ -1243,6 +1276,12 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 			BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
 			return ToString(targetConst) + StrFormat(" Gep32 %d,%d", gepConst->mIdx0, gepConst->mIdx1);			
 		}
+		else if (constant->mConstType == BfConstType_ExtractValue)
+		{
+			auto gepConst = (BfConstantExtractValue*)constant;
+			BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
+			return ToString(targetConst) + StrFormat(" ExtractValue %d", gepConst->mIdx0);
+		}
 		else if (constant->mConstType == BfConstType_PtrToInt)
 		{
 			auto ptrToIntConst = (BfConstantPtrToInt*)constant;
@@ -1838,6 +1877,14 @@ void BfIRBuilder::Write(const BfIRValue& irValue)
 				Write(gepConst->mIdx1);
 			}
 			break;
+		case (int)BfConstType_ExtractValue:
+			{
+				auto gepConst = (BfConstantExtractValue*)constant;
+				BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
+				Write(targetConst);
+				Write(gepConst->mIdx0);				
+			}
+			break;
 		case (int)BfConstType_PtrToInt:
 			{
 				auto ptrToIntConst = (BfConstantPtrToInt*)constant;
@@ -3964,7 +4011,7 @@ BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0)
 BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0, int idx1)
 {
 	if (val.IsConst())
-	{	
+	{
 		auto constGEP = mTempAlloc.Alloc<BfConstantGEP32_2>();
 		constGEP->mConstType = BfConstType_GEP32_2;
 		constGEP->mTarget = val.mId;
@@ -4024,6 +4071,20 @@ BfIRValue BfIRBuilder::CreateExtractValue(BfIRValue val, int idx)
 			auto arrayConstant = (BfConstantArray*)aggConstant;
 			return arrayConstant->mValues[idx];
 		}
+		
+		auto constGEP = mTempAlloc.Alloc<BfConstantExtractValue>();
+		constGEP->mConstType = BfConstType_ExtractValue;
+		constGEP->mTarget = val.mId;
+		constGEP->mIdx0 = idx;
+
+		BfIRValue retVal;
+		retVal.mFlags = BfIRValueFlags_Const;
+		retVal.mId = mTempAlloc.GetChunkedId(constGEP);
+
+#ifdef CHECK_CONSTHOLDER
+		retVal.mHolder = this;
+#endif
+		return retVal;		
 	}
 
 	BfIRValue retVal = WriteCmd(BfIRCmd_ExtractValue, val, idx);
@@ -4213,7 +4274,7 @@ BfIRValue BfIRBuilder::CreateGlobalVariable(BfIRType varType, bool isConstant, B
 	auto constGV = mTempAlloc.Alloc<BfGlobalVar>();
 	int chunkId = mTempAlloc.GetChunkedId(constGV);
 	constGV->mStreamId = -1;
-	constGV->mConstType = BfConstType_GlobalVar;
+ 	constGV->mConstType = BfConstType_GlobalVar;
 	constGV->mType = varType;	
 	constGV->mIsConst = isConstant;
 	constGV->mLinkageType = linkageType;

+ 8 - 0
IDEHelper/Compiler/BfIRBuilder.h

@@ -134,6 +134,7 @@ enum BfConstType
 	BfConstType_BitCast,
 	BfConstType_BitCastNull,
 	BfConstType_GEP32_2,
+	BfConstType_ExtractValue,
 	BfConstType_PtrToInt,
 	BfConstType_TypeOf,
 	BfConstType_AggZero,
@@ -825,6 +826,13 @@ struct BfConstantGEP32_2
 	int mIdx1;
 };
 
+struct BfConstantExtractValue
+{
+	BfConstType mConstType;
+	int mTarget;
+	int mIdx0;	
+};
+
 struct BfConstantArray
 {
 	BfConstType mConstType;

+ 21 - 8
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -709,7 +709,7 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 			CMD_PARAM(int, streamId);
 			if (streamId == -1)
 			{
-				int streamId = mCmdCount++;
+				int streamId = mCmdCount++;				
 
 				CMD_PARAM(llvm::Type*, varType);
 				CMD_PARAM(bool, isConstant);
@@ -718,13 +718,17 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 				CMD_PARAM(String, name);
 				CMD_PARAM(bool, isTLS);
 
-				auto globalVariable = new llvm::GlobalVariable(
-					*mLLVMModule,
-					varType,
-					isConstant,
-					LLVMMapLinkageType(linkageType),
-					initializer,
-					name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal);
+				llvm::GlobalVariable* globalVariable = mLLVMModule->getGlobalVariable(name.c_str(), true);
+				if (globalVariable == NULL)
+				{
+					globalVariable = new llvm::GlobalVariable(
+						*mLLVMModule,
+						varType,
+						isConstant,
+						LLVMMapLinkageType(linkageType),
+						initializer,
+						name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal);
+				}
 				llvmValue = globalVariable;
 
 				SetResult(streamId, globalVariable);
@@ -791,6 +795,15 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 			llvmValue = llvm::ConstantExpr::getInBoundsGetElementPtr(NULL, target, gepArgs);
 			return;
 		}
+		else if (constType == BfConstType_ExtractValue)
+		{
+			CMD_PARAM(llvm::Constant*, target);
+			CMD_PARAM(int, idx0);			
+			unsigned int gepArgs[] = {
+				(unsigned int)idx0 };
+			llvmValue = llvm::ConstantExpr::getExtractValue(target, gepArgs);
+			return;
+		}
 		else if (constType == BfConstType_PtrToInt)
 		{
 			CMD_PARAM(llvm::Constant*, target);

+ 30 - 2
IDEHelper/Compiler/BfModule.cpp

@@ -5388,6 +5388,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		baseTypeId = typeInstance->mBaseType->mTypeId;
 	}	
 	
+	BfTypeOptions* typeOptions = NULL;
+	if (typeInstance->mTypeOptionsIdx >= 0)
+		typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
+
 	SizedArray<BfIRValue, 16> customAttrs;
 
 	BfTypeInstance* attributeType = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
@@ -5716,7 +5720,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			if ((!fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_NonStaticFields) != 0))
 				includeField = true;
 			if ((fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_StaticFields) != 0))
-				includeField = true;			
+				includeField = true;
+						
+			if ((!fieldDef->mIsStatic) && (typeOptions != NULL))
+				includeField = typeOptions->Apply(includeField, BfOptionFlags_ReflectNonStaticFields);
+			if ((fieldDef->mIsStatic) && (typeOptions != NULL))
+				includeField = typeOptions->Apply(includeField, BfOptionFlags_ReflectStaticFields);
+
 			includeField |= forceReflectFields;
 
 			if (!includeField)
@@ -6031,7 +6041,20 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			includeMethod = true;
 		if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0))
 			includeMethod = true;
-				
+		
+		if (methodDef->mMethodType == BfMethodType_Ctor)
+		{
+			if (typeOptions != NULL)
+				includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectConstructors);
+		}
+		else
+		{
+			if ((!methodDef->mIsStatic) && (typeOptions != NULL))
+				includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectNonStaticMethods);
+			if ((methodDef->mIsStatic) && (typeOptions != NULL))
+				includeMethod = typeOptions->Apply(includeMethod, BfOptionFlags_ReflectStaticMethods);
+		}
+
 		if (!includeMethod)
 			continue;
 
@@ -9820,6 +9843,11 @@ void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
 		return;
 	}
 
+	if (constant->mConstType == BfConstType_GlobalVar)
+	{
+		NOP;
+	}
+
 	auto origConst = irVal;		
 	if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
 	{

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -1604,6 +1604,7 @@ public:
 	void CheckAddFailType();
 	bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
 	BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef);
+	bool CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions* typeOptions);
 	int GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName);
 	void SetTypeOptions(BfTypeInstance* typeInstance);
 	BfModuleOptions GetModuleOptions();

+ 22 - 3
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -1473,6 +1473,11 @@ BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef)
 	return mSystem->GetTypeOptions( matchedIdx);
 }
 
+bool BfModule::CheckTypeOptionMethodFilters(BfMethodDef* methodDef, BfTypeOptions * typeOptions)
+{
+	return true;
+}
+
 int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName)
 {
 	if (mContext->mSystem->mTypeOptions.size() == 0)
@@ -2512,9 +2517,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 	}
 
 	if (typeInstance->mTypeOptionsIdx == -2)
-	{
-		SetTypeOptions(typeInstance);
-	}
+		SetTypeOptions(typeInstance);	
 
 	ProcessCustomAttributeData();
 	bool isPacked = false;
@@ -2530,6 +2533,16 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 	typeInstance->mIsPacked = isPacked;
 	typeInstance->mIsCRepr = isCRepr;
 
+	if (typeInstance->mTypeOptionsIdx >= 0)
+	{
+		auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
+		if (typeOptions != NULL)
+		{
+			typeInstance->mIncludeAllMethods = typeOptions->Apply(typeInstance->mIncludeAllMethods, BfOptionFlags_ReflectAlwaysIncludeAll);
+			typeInstance->mHasBeenInstantiated = typeOptions->Apply(typeInstance->mHasBeenInstantiated, BfOptionFlags_ReflectAssumeInstantiated);
+		}
+	}
+
 	BfType* unionInnerType = NULL;
 	bool hadDeferredVars = false;
 	int dataPos;
@@ -3681,6 +3694,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 
 	auto typeDef = typeInstance->mTypeDef;
 
+	BfTypeOptions* typeOptions = NULL;
+	if (typeInstance->mTypeOptionsIdx >= 0)
+		typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
+
 	// Generate all methods. Pass 0
 	for (auto methodDef : typeDef->mMethods)
 	{
@@ -3980,6 +3997,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 			}
 			if (typeInstance->mIncludeAllMethods)
 				implRequired = true;
+// 			if ((typeOptions != NULL) && (CheckTypeOptionMethodFilters(typeOptions, methodDef)))
+// 				implRequired = true;
 
 			if (typeInstance->IsInterface())
 				declRequired = true;

+ 50 - 0
IDEHelper/Tests/src/Globals.bf

@@ -0,0 +1,50 @@
+using System;
+
+namespace Tests
+{
+	class Globals
+	{
+		static int sVal0 = 123;
+		static int sVal1 = 234;
+		static int sVal2 = 345;
+
+		public const String[3][2] cValStrs = .(("A", "B"), ("C", "D"), );
+		public const String[3][2] cValStrs2 = .(.("A", "B"), .("C", "D"), );
+		public static String[3][2] sValStrs = .(("A", "B"), ("C", "D"), );
+		public static String[3][2] sValStrs2 = .(.("A", "B"), .("C", "D"), );
+
+		public const int*[3][2] cValsInt = .((&sVal0, &sVal1), (&sVal2, ), );
+		public static int*[3][2] sValsInt = .((&sVal0, &sVal1), (&sVal2, ), );
+
+		[Test]
+		public static void TestBasics()
+		{
+			const bool cEq0 = cValStrs[0][0] == "A";
+			const bool cEq1 = cValStrs[0][1] == "A";
+			Test.Assert(cEq0);
+			Test.Assert(!cEq1);
+
+			Test.Assert(cValStrs[0][0] === "A");
+			Test.Assert(cValStrs[0][1] === "B");
+			Test.Assert(cValStrs[1][0] === "C");
+			Test.Assert(cValStrs[1][1] === "D");
+
+			Test.Assert(cValStrs2[0][0] === "A");
+			Test.Assert(cValStrs2[0][1] === "B");
+			Test.Assert(cValStrs2[1][0] === "C");
+			Test.Assert(cValStrs2[1][1] === "D");
+
+			Test.Assert(sValStrs[0][0] === "A");
+			Test.Assert(sValStrs[0][1] === "B");
+			Test.Assert(sValStrs[1][0] === "C");
+			Test.Assert(sValStrs[1][1] === "D");
+
+			Test.Assert(*(cValsInt[0][0]) == 123);
+			Test.Assert(*(cValsInt[0][1]) == 234);
+			Test.Assert(*(cValsInt[1][0]) == 345);
+
+			const int* iPtr = cValsInt[2][0];
+			Test.Assert(iPtr == null);
+		}
+	}
+}