1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Interop fixes and tests, fixing xplat struct passing issues

This commit is contained in:
Brian Fiete 2020-06-10 07:12:07 -07:00
parent 4cf6af53bd
commit 5da74382d4
31 changed files with 1569 additions and 239 deletions

View file

@ -509,13 +509,23 @@ namespace System
Let,
Boolean,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
UInt8,
Int16,
UInt16,
Int24,
UInt24,
Int32,
UInt32,
Int40,
UInt40,
Int48,
UInt48,
Int56,
UInt56,
Int64,
UInt64,
Int128,
UInt128,
Int,
UInt,
IntUnknown,

View file

@ -476,13 +476,23 @@ namespace System
Let,
Boolean,
Int8,
UInt8,
Int16,
UInt16,
Int32,
UInt32,
Int64,
UInt64,
UInt8,
Int16,
UInt16,
Int24,
UInt24,
Int32,
UInt32,
Int40,
UInt40,
Int48,
UInt48,
Int56,
UInt56,
Int64,
UInt64,
Int128,
UInt128,
Int,
UInt,
IntUnknown,

View file

@ -71,6 +71,22 @@ BeStructType* BeContext::CreateStruct(const StringImpl& name)
return structType;
}
BeStructType* BeContext::CreateStruct(const SizedArrayImpl<BeType*>& types)
{
BeStructType** valuePtr = NULL;
if (mAnonymousStructMap.TryGetValueWith(types, &valuePtr))
return *valuePtr;
Array<BeType*> key;
for (auto type : types)
key.Add(type);
BeStructType* structType = CreateStruct("");
SetStructBody(structType, types, false);
mAnonymousStructMap.TryAdd(key, structType);
return structType;
}
BePointerType* BeContext::GetPointerTo(BeType* beType)
{
if (beType->mPointerType == NULL)

View file

@ -226,6 +226,7 @@ public:
//BumpAllocator mAlloc;
BeType* mPrimitiveTypes[BeTypeCode_COUNT];
OwnedVector<BeType> mTypes;
Dictionary<Array<BeType*>, BeStructType*> mAnonymousStructMap;
public:
void NotImpl();
@ -234,6 +235,7 @@ public:
BeContext();
BeType* GetPrimitiveType(BeTypeCode typeCode);
BeStructType* CreateStruct(const StringImpl& name);
BeStructType* CreateStruct(const SizedArrayImpl<BeType*>& types);
BePointerType* GetPointerTo(BeType* beType);
void SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed);
BeSizedArrayType* CreateSizedArrayType(BeType* type, int length);

View file

@ -963,6 +963,13 @@ void BeIRCodeGen::HandleNextCmd()
SetResult(curId, mBeContext->CreateStruct(typeName));
}
break;
case BfIRCmd_CreateAnonymousStruct:
{
CMD_PARAM(CmdParamVec<BeType*>, members);
BeStructType* structType = mBeContext->CreateStruct(members);
SetResult(curId, structType);
}
break;
case BfIRCmd_StructSetBody:
{
CMD_PARAM(BeType*, type);
@ -2143,7 +2150,8 @@ void BeIRCodeGen::HandleNextCmd()
{
if (attribute == BfIRAttribute_StructRet)
{
BF_ASSERT(argIdx == 1);
auto valType = callInst->mArgs[argIdx - 1].mValue->GetType();
BF_ASSERT(valType->IsPointer());
callInst->mArgs[argIdx - 1].mStructRet = true;
}
else if (attribute == BfIRAttribute_ZExt)
@ -2152,6 +2160,9 @@ void BeIRCodeGen::HandleNextCmd()
callInst->mArgs[argIdx - 1].mNoAlias = true;
else if (attribute == BfIRAttribute_NoCapture)
callInst->mArgs[argIdx - 1].mNoCapture = true;
else if (attribute == BfIRAttribute_ByVal)
{
}
else
BF_FATAL("Unhandled");
}
@ -2177,7 +2188,21 @@ void BeIRCodeGen::HandleNextCmd()
if (argIdx > 0)
{
if (attribute == BfIRAttribute_Dereferencable)
{
callInst->mArgs[argIdx - 1].mDereferenceableSize = arg;
if (auto func = BeValueDynCast<BeFunction>(callInst->mFunc))
{
BF_ASSERT(func->mParams[argIdx - 1].mDereferenceableSize == arg);
}
}
else if (attribute == BfIRAttribute_ByVal)
{
callInst->mArgs[argIdx - 1].mByRefSize = arg;
if (auto func = BeValueDynCast<BeFunction>(callInst->mFunc))
{
BF_ASSERT(func->mParams[argIdx - 1].mByValSize == arg);
}
}
else
BF_FATAL("Unhandled");
}
@ -2242,6 +2267,8 @@ void BeIRCodeGen::HandleNextCmd()
{
if (attribute == BfIRAttribute_Dereferencable)
func->mParams[argIdx - 1].mDereferenceableSize = arg;
else if (attribute == BfIRAttribute_ByVal)
func->mParams[argIdx - 1].mByValSize = arg;
else
BF_FATAL("Unhandled");
}

View file

@ -532,6 +532,7 @@ void BeFunction::HashContent(BeHashContext& hashCtx)
hashCtx.Mixin(param.mStructRet);
hashCtx.Mixin(param.mZExt);
hashCtx.Mixin(param.mDereferenceableSize);
hashCtx.Mixin(param.mByValSize);
}
if (mDbgFunction != NULL)
mDbgFunction->HashReference(hashCtx);

View file

@ -410,6 +410,7 @@ public:
bool mNoCapture;
bool mZExt;
int mDereferenceableSize;
int mByValSize;
BeFunctionParam()
{
@ -418,6 +419,7 @@ public:
mNoCapture = false;
mZExt = false;
mDereferenceableSize = -1;
mByValSize = -1;
}
};
@ -1207,6 +1209,7 @@ public:
{
BeValue* mValue;
int mDereferenceableSize;
int mByRefSize;
bool mStructRet;
bool mZExt;
bool mNoAlias;
@ -1219,6 +1222,7 @@ public:
mNoAlias = false;
mNoCapture = false;
mDereferenceableSize = -1;
mByRefSize = -1;
}
};
@ -1254,6 +1258,8 @@ public:
arg.mValue->HashReference(hashCtx);
hashCtx.Mixin(arg.mStructRet);
hashCtx.Mixin(arg.mZExt);
hashCtx.Mixin(arg.mDereferenceableSize);
hashCtx.Mixin(arg.mByRefSize);
}
hashCtx.Mixin(mCallingConv);
hashCtx.Mixin(mNoReturn);

View file

@ -3470,6 +3470,8 @@ void BfCompiler::VisitSourceExteriorNodes()
if (parser->mAwaitingDelete)
return;
if (parser->mParserData == NULL)
return;
if (parser->mParserData->mExteriorNodesCheckIdx == mSystem->mTypeMapVersion)
return;

View file

@ -2496,6 +2496,8 @@ void MsDemangleScanner::Process(const StringImpl& mangledName)
String BfDemangler::Demangle(const StringImpl& mangledName, DbgLanguage language, Flags flags)
{
if (mangledName.IsEmpty())
return "";
if (mangledName[0] == '?')
{
MsDemangler demangler;

View file

@ -4484,7 +4484,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
}
else
{
auto val = mModule->GetDefaultTypedValue(returnType, true, methodInstance->HasStructRet() ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
auto val = mModule->GetDefaultTypedValue(returnType, true, (methodInstance->GetStructRetIdx() != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
if (val.mKind == BfTypedValueKind_Addr)
val.mKind = BfTypedValueKind_TempAddr;
return val;
@ -4492,7 +4492,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
};
mModule->PopulateType(origReturnType, BfPopulateType_Data);
if (methodInstance->HasStructRet())
if (methodInstance->GetStructRetIdx() != -1)
{
// We need to ensure that mReceivingValue has the correct type, otherwise it's possible that a conversion operator needs to be applied
// This happens for returning Result<T>'s with a 'T' value
@ -4756,13 +4756,23 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
mModule->mBfIRBuilder->PopulateType(returnType);
BfIRValue callInst;
int callIRArgCount = (int)irArgs.size();
if (sret != NULL)
{
SizedArray<BfIRValue, 8> sretIRArgs;
sretIRArgs.push_back(sret->mValue);
if (!irArgs.IsEmpty())
sretIRArgs.Insert(sretIRArgs.size(), &irArgs[0], irArgs.size());
int sretIdx = methodInstance->GetStructRetIdx();
int inIdx = 0;
for (int outIdx = 0; outIdx < irArgs.size() + 1; outIdx++)
{
if (outIdx == sretIdx)
{
sretIRArgs.Add(sret->mValue);
continue;
}
sretIRArgs.Add(irArgs[inIdx++]);
}
callInst = mModule->mBfIRBuilder->CreateCall(funcCallInst, sretIRArgs);
callIRArgCount++;
}
else
{
@ -4780,18 +4790,23 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
int paramIdx = 0;
bool doingThis = !methodDef->mIsStatic;
int argIdx = 0;
if (sret != NULL)
if (methodInstance->mIdHash == 1140)
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_StructRet);
argIdx++;
NOP;
}
int paramCount = methodInstance->GetParamCount();
for ( ; argIdx < (int)irArgs.size(); /*argIdx++*/)
for ( ; argIdx < callIRArgCount ; )
{
if (argIdx >= paramCount)
break;
if (argIdx == methodInstance->GetStructRetIdx())
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_StructRet);
argIdx++;
continue;
}
auto _HandleParamType = [&] (BfType* paramType)
{
@ -4799,10 +4814,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
{
if ((!doingThis) || (!methodDef->mIsMutating && methodInstance->AllowsSplatting()))
{
auto loweredTypeCode = paramType->GetLoweredType();
if (loweredTypeCode != BfTypeCode_None)
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (paramType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
argIdx++;
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
return; // Lowering never requires attributes
}
}
@ -4818,6 +4836,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
if ((addDeref <= 0) && (!elementType->IsValuelessType()))
mModule->AssertErrorState();
}
if ((paramType->IsComposite()) && (!paramType->IsTypedPrimitive()))
{
if (mModule->mCompiler->mOptions.mAllowStructByVal)
@ -4835,8 +4854,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
}
else
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_NoCapture);
addDeref = paramType->mSize;
if (doingThis)
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_NoCapture);
addDeref = paramType->mSize;
}
else
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_ByVal, mModule->mSystem->mPtrSize);
}
}
}
}
@ -4876,13 +4902,28 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
}
else
{
if (paramIdx >= methodInstance->GetParamCount())
break;
paramType = methodInstance->GetParamType(paramIdx);
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (paramType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
argIdx++;
paramIdx++;
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
continue;
}
if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef()))
{
paramIdx++;
continue;
}
//if (resolvedTypeRef->IsSplattable())
if (methodInstance->GetParamIsSplat(paramIdx))
{
BfTypeUtils::SplatIterate(_HandleParamType, paramType);
@ -4893,8 +4934,6 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
_HandleParamType(methodInstance->GetParamType(paramIdx));
}
if (doingThis)
doingThis = false;
else
@ -4936,13 +4975,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
result = *sret;
else if (hasResult)
{
if (methodInstance->mReturnType->GetLoweredType() != BfTypeCode_None)
BfTypeCode loweredRetType = BfTypeCode_None;
BfTypeCode loweredRetType2 = BfTypeCode_None;
if (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2))
{
auto loweredType = mModule->GetPrimitiveType(methodInstance->mReturnType->GetLoweredType());
auto loweredPtrType = mModule->CreatePointerType(loweredType);
auto retVal = mModule->CreateAlloca(methodInstance->mReturnType);
auto castedRetVal = mModule->mBfIRBuilder->CreateBitCast(retVal, mModule->mBfIRBuilder->MapType(loweredPtrType));
BfIRType loweredIRType = mModule->GetIRLoweredType(loweredRetType, loweredRetType2);
loweredIRType = mModule->mBfIRBuilder->GetPointerTo(loweredIRType);
auto castedRetVal = mModule->mBfIRBuilder->CreateBitCast(retVal, loweredIRType);
mModule->mBfIRBuilder->CreateStore(callInst, castedRetVal);
result = BfTypedValue(retVal, methodInstance->mReturnType, BfTypedValueKind_TempAddr);
}
@ -5116,14 +5156,40 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
if (!disableLowering)
{
auto loweredTypeCode = argVal.mType->GetLoweredType();
if (loweredTypeCode != BfTypeCode_None)
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (argVal.mType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
auto primType = mModule->GetPrimitiveType(loweredTypeCode);
auto ptrType = mModule->CreatePointerType(primType);
BfIRValue primPtrVal = mModule->mBfIRBuilder->CreateBitCast(argVal.mValue, mModule->mBfIRBuilder->MapType(ptrType));
// auto primType = mModule->GetPrimitiveType(loweredTypeCode);
// auto ptrType = mModule->CreatePointerType(primType);
// BfIRValue primPtrVal = mModule->mBfIRBuilder->CreateBitCast(argVal.mValue, mModule->mBfIRBuilder->MapType(ptrType));
// auto primVal = mModule->mBfIRBuilder->CreateLoad(primPtrVal);
// irArgs.push_back(primVal);
//
// if (loweredTypeCode2 != BfTypeCode_None)
// {
// auto primType2 = mModule->GetPrimitiveType(loweredTypeCode2);
// auto ptrType2 = mModule->CreatePointerType(primType2);
// BfIRValue primPtrVal2 = mModule->mBfIRBuilder->CreateBitCast(mModule->mBfIRBuilder->CreateInBoundsGEP(primPtrVal, 1), mModule->mBfIRBuilder->MapType(ptrType2));
// auto primVal2 = mModule->mBfIRBuilder->CreateLoad(primPtrVal2);
// irArgs.push_back(primVal2);
// }
auto primType = mModule->mBfIRBuilder->GetPrimitiveType(loweredTypeCode);
auto ptrType = mModule->mBfIRBuilder->GetPointerTo(primType);
BfIRValue primPtrVal = mModule->mBfIRBuilder->CreateBitCast(argVal.mValue, ptrType);
auto primVal = mModule->mBfIRBuilder->CreateLoad(primPtrVal);
irArgs.push_back(primVal);
if (loweredTypeCode2 != BfTypeCode_None)
{
auto primType2 = mModule->mBfIRBuilder->GetPrimitiveType(loweredTypeCode2);
auto ptrType2 = mModule->mBfIRBuilder->GetPointerTo(primType2);
BfIRValue primPtrVal2 = mModule->mBfIRBuilder->CreateBitCast(mModule->mBfIRBuilder->CreateInBoundsGEP(primPtrVal, 1), ptrType2);
auto primVal2 = mModule->mBfIRBuilder->CreateLoad(primPtrVal2);
irArgs.push_back(primVal2);
}
return;
}
}
@ -5244,7 +5310,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!mModule->mCompiler->mIsResolveOnly)
sCallIdx++;
int callIdx = sCallIdx;
if (callIdx == 4348)
if (callIdx == 1177)
{
NOP;
}
@ -5439,6 +5505,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
wantsSplat = methodInstance->GetParamIsSplat(paramIdx);
if (methodInstance->IsImplicitCapture(paramIdx))
{
auto paramType = methodInstance->GetParamType(paramIdx);
if (mModule->mCurMethodInstance->IsMixin())
{
// Don't bother, also- can fail on captures
@ -5461,10 +5528,12 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{
SplatArgs(lookupVal, irArgs);
}
else
else if (paramType->IsRef())
{
irArgs.push_back(lookupVal.mValue);
}
else
PushArg(lookupVal, irArgs, true);
}
}
paramIdx++;
@ -5549,7 +5618,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
bool hadMissingArg = false;
int argExprIdx = argIdx;
if ((methodDef->mMethodType == BfMethodType_Extension))
if (methodDef->mMethodType == BfMethodType_Extension)
{
argExprIdx--;
if (argExprIdx == -1)
@ -5718,12 +5787,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{
if (methodRefType->WantsDataPassedAsSplat(dataIdx))
SplatArgs(lookupVal, irArgs);
else if (lookupVal.mType->IsComposite())
{
irArgs.push_back(lookupVal.mValue);
}
else
irArgs.push_back(lookupVal.mValue);
irArgs.push_back(lookupVal.mValue);
}
}
@ -6814,11 +6879,6 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
methodMatcher.CheckType(lookupTypeInst, target, true);
}
if ((methodMatcher.mBestMethodDef != NULL) && (methodMatcher.mBestMethodDef->mName == "Zorf"))
{
NOP;
}
BfTypedValue staticResult;
methodMatcher.TryDevirtualizeCall(target, &origTarget, &staticResult);
if (staticResult)
@ -9910,7 +9970,9 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
{
hasThis = true;
methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes);
int thisIdx = methodInstance->HasStructRet() ? 1 : 0;
int thisIdx = 0;
if (methodInstance->GetStructRetIdx() == 0)
thisIdx = 1;
irParamTypes[thisIdx] = mModule->mBfIRBuilder->MapType(useTypeInstance);
}
else
@ -9927,10 +9989,10 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
auto funcType = mModule->mBfIRBuilder->CreateFunctionType(irReturnType, irParamTypes);
funcValue = mModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName);
if (methodInstance->HasStructRet())
if (methodInstance->GetStructRetIdx() != -1)
{
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_NoAlias);
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_StructRet);
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, methodInstance->GetStructRetIdx() + 1, BfIRAttribute_NoAlias);
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, methodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
}
auto srcCallingConv = mModule->GetIRCallingConvention(methodInstance);
@ -9947,9 +10009,17 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
fieldIdx = 0;
SizedArray<BfIRValue, 8> irArgs;
if (methodInstance->mIdHash == 775)
{
NOP;
}
int argIdx = 0;
if (methodInstance->HasStructRet())
irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++));
if (bindMethodInstance->GetStructRetIdx() == 0)
{
irArgs.push_back(mModule->mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()));
argIdx++;
}
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
{
@ -9965,7 +10035,10 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
disableSplat = true;
}
}
int thisIdx = methodInstance->HasStructRet() ? 1 : 0;
int thisIdx = 0;
if (methodInstance->GetStructRetIdx() == 0)
thisIdx = 1;
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mModule->mBfIRBuilder->GetArgument(thisIdx), 0, gepIdx);
BfTypedValue typedVal(fieldPtr, fieldType, true);
PushArg(typedVal, irArgs, disableSplat);
@ -9975,6 +10048,12 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (hasThis)
argIdx++;
if (bindMethodInstance->GetStructRetIdx() == 1)
{
irArgs.push_back(mModule->mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()));
argIdx++;
}
for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
{
auto paramType = methodInstance->GetParamType(paramIdx);
@ -9992,12 +10071,12 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
if (mModule->mCompiler->mOptions.mAllowHotSwapping)
bindFuncVal = mModule->mBfIRBuilder->RemapBindFunction(bindFuncVal);
auto callInst = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
if (methodInstance->HasStructRet())
mModule->mBfIRBuilder->Call_AddAttribute(callInst, 1, BfIRAttribute_StructRet);
if (bindMethodInstance->GetStructRetIdx() != -1)
mModule->mBfIRBuilder->Call_AddAttribute(callInst, bindMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
auto destCallingConv = mModule->GetIRCallingConvention(bindMethodInstance);
if (destCallingConv != BfIRCallingConv_CDecl)
mModule->mBfIRBuilder->SetCallCallingConv(callInst, destCallingConv);
if ((methodInstance->mReturnType->IsValuelessType()) || (methodInstance->HasStructRet()))
if ((methodInstance->mReturnType->IsValuelessType()) || (methodInstance->GetStructRetIdx() != -1))
{
mModule->mBfIRBuilder->CreateRetVoid();
}
@ -10784,13 +10863,16 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
}
SizedArray<BfIRType, 3> newTypes;
if ((invokeMethodInstance != NULL) && (invokeMethodInstance->HasStructRet()))
if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx() == 0))
newTypes.push_back(origParamTypes[0]);
if (!methodDef->mIsStatic)
newTypes.push_back(mModule->mBfIRBuilder->MapType(useTypeInstance));
if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx() == 1))
newTypes.push_back(origParamTypes[1]);
int paramStartIdx = 0;
if ((invokeMethodInstance != NULL) && (invokeMethodInstance->HasStructRet()))
if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx() != -1))
paramStartIdx++;
if (!methodDef->mIsStatic)
paramStartIdx++;
@ -14585,6 +14667,11 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
return mResult;
}
if (matchedMethod->mName == "get__CultureName")
{
NOP;
}
auto methodInstance = GetPropertyMethodInstance(matchedMethod);
if (methodInstance.mMethodInstance == NULL)
return mResult;
@ -14662,7 +14749,7 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
}
else
{
auto val = mModule->GetDefaultTypedValue(returnType, true, methodInstance.mMethodInstance->HasStructRet() ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
auto val = mModule->GetDefaultTypedValue(returnType, true, (methodInstance.mMethodInstance->GetStructRetIdx() != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
if (val.mKind == BfTypedValueKind_Addr)
val.mKind = BfTypedValueKind_TempAddr;
return val;

View file

@ -3305,6 +3305,13 @@ BfIRType BfIRBuilder::CreateStructType(const StringImpl& name)
return retType;
}
BfIRType BfIRBuilder::CreateStructType(const BfSizedArray<BfIRType>& memberTypes)
{
BfIRType retType = WriteCmd(BfIRCmd_CreateAnonymousStruct, memberTypes);
NEW_CMD_INSERTED_IRTYPE;
return retType;
}
void BfIRBuilder::StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, bool isPacked)
{
WriteCmd(BfIRCmd_StructSetBody, type, memberTypes, isPacked);
@ -4421,6 +4428,11 @@ BfIRFunction BfIRBuilder::CreateFunction(BfIRFunctionType funcType, BfIRLinkageT
NEW_CMD_INSERTED_IRVALUE;
mFunctionMap[name] = retVal;
if (name == "?TestStructRetCapture$Rt@Lambdas@Tests@bf@@QEAA?AUStructA@123@XZ")
{
NOP;
}
//BfLogSys(mModule->mSystem, "BfIRBuilder::CreateFunction: %d %s Module:%p\n", retVal.mId, name.c_str(), mModule);
return retVal;

View file

@ -94,10 +94,20 @@ enum BfTypeCode : uint8
BfTypeCode_UInt8,
BfTypeCode_Int16,
BfTypeCode_UInt16,
BfTypeCode_Int24,
BfTypeCode_UInt24,
BfTypeCode_Int32,
BfTypeCode_UInt32,
BfTypeCode_Int40,
BfTypeCode_UInt40,
BfTypeCode_Int48,
BfTypeCode_UInt48,
BfTypeCode_Int56,
BfTypeCode_UInt56,
BfTypeCode_Int64,
BfTypeCode_UInt64,
BfTypeCode_Int128,
BfTypeCode_UInt128,
BfTypeCode_IntPtr,
BfTypeCode_UIntPtr,
BfTypeCode_IntUnknown,
@ -152,6 +162,7 @@ enum BfIRCmd : uint8
BfIRCmd_SetType,
BfIRCmd_SetInstType,
BfIRCmd_PrimitiveType,
BfIRCmd_CreateAnonymousStruct,
BfIRCmd_CreateStruct,
BfIRCmd_StructSetBody,
BfIRCmd_Type,
@ -1050,6 +1061,7 @@ public:
BfIRType GetPrimitiveType(BfTypeCode typeCode);
BfIRType CreateStructType(const StringImpl& name);
BfIRType CreateStructType(const BfSizedArray<BfIRType>& memberTypes);
void StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, bool isPacked);
BfIRType MapType(BfType* type, BfIRPopulateType populateType = BfIRPopulateType_Declaration);
BfIRType MapTypeInst(BfTypeInstance* typeInst, BfIRPopulateType populateType = BfIRPopulateType_Declaration);

View file

@ -434,17 +434,42 @@ llvm::Type* BfIRCodeGen::GetLLVMType(BfTypeCode typeCode, bool& isSigned)
case BfTypeCode_UInt16:
case BfTypeCode_Char16:
return llvm::Type::getInt16Ty(*mLLVMContext);
case BfTypeCode_Int24:
isSigned = true;
return llvm::Type::getIntNTy(*mLLVMContext, 24);
case BfTypeCode_UInt24:
return llvm::Type::getIntNTy(*mLLVMContext, 24);
case BfTypeCode_Int32:
isSigned = true;
return llvm::Type::getInt32Ty(*mLLVMContext);
case BfTypeCode_UInt32:
case BfTypeCode_Char32:
return llvm::Type::getInt32Ty(*mLLVMContext);
case BfTypeCode_Int40:
isSigned = true;
return llvm::Type::getIntNTy(*mLLVMContext, 40);
case BfTypeCode_UInt40:
return llvm::Type::getIntNTy(*mLLVMContext, 40);
case BfTypeCode_Int48:
isSigned = true;
return llvm::Type::getIntNTy(*mLLVMContext, 48);
case BfTypeCode_UInt48:
return llvm::Type::getIntNTy(*mLLVMContext, 48);
case BfTypeCode_Int56:
isSigned = true;
return llvm::Type::getIntNTy(*mLLVMContext, 56);
case BfTypeCode_UInt56:
return llvm::Type::getIntNTy(*mLLVMContext, 56);
case BfTypeCode_Int64:
isSigned = true;
return llvm::Type::getInt64Ty(*mLLVMContext);
case BfTypeCode_UInt64:
return llvm::Type::getInt64Ty(*mLLVMContext);
case BfTypeCode_Int128:
isSigned = true;
return llvm::Type::getInt128Ty(*mLLVMContext);
case BfTypeCode_UInt128:
return llvm::Type::getInt128Ty(*mLLVMContext);
case BfTypeCode_IntPtr:
BF_FATAL("Illegal");
/*isSigned = true;
@ -1116,6 +1141,13 @@ void BfIRCodeGen::HandleNextCmd()
SetResult(curId, GetLLVMType(typeCode, isSigned));
}
break;
case BfIRCmd_CreateAnonymousStruct:
{
CMD_PARAM(CmdParamVec<llvm::Type*>, members);
llvm::StructType* structType = llvm::StructType::get(*mLLVMContext, members);
SetResult(curId, structType);
}
break;
case BfIRCmd_CreateStruct:
{
CMD_PARAM(String, typeName);
@ -2621,6 +2653,15 @@ void BfIRCodeGen::HandleNextCmd()
{
((llvm::CallInst*)callInst)->addDereferenceableAttr(argIdx, arg);
}
else if (attribute == BfIRAttribute_ByVal)
{
llvm::AttrBuilder B;
B.addAttribute(llvm::Attribute::ByVal);
B.addAlignmentAttr(arg);
auto attrList = ((llvm::CallInst*)callInst)->getAttributes();
attrList = attrList.addAttributes(*mLLVMContext, argIdx, B);
((llvm::CallInst*)callInst)->setAttributes(attrList);
}
}
}
break;
@ -2655,6 +2696,15 @@ void BfIRCodeGen::HandleNextCmd()
{
((llvm::Function*)func)->addDereferenceableAttr(argIdx, arg);
}
else if (attribute == BfIRAttribute_ByVal)
{
llvm::AttrBuilder B;
B.addAttribute(llvm::Attribute::ByVal);
B.addAlignmentAttr(arg);
auto attrList = ((llvm::Function*)func)->getAttributes();
attrList = attrList.addAttributes(*mLLVMContext, argIdx, B);
((llvm::Function*)func)->setAttributes(attrList);
}
}
break;
case BfIRCmd_Func_SetParamName:

View file

@ -1577,7 +1577,7 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType*
name += "E";
name += "A";
}
else if (((type->IsGenericTypeInstance()) || (type->IsTuple()) || (type->IsEnum())) && (mangleContext.mInRet))
else if (((type->IsGenericTypeInstance()) || (type->IsComposite()) || (type->IsEnum())) && (mangleContext.mInRet))
name += "?A";
Mangle(mangleContext, name, typeInstance, false);

View file

@ -1098,9 +1098,8 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen)
//mBfIRBuilder->mDbgVerifyCodeGen = true;
if (
(mModuleName == "-")
//|| (mModuleName == "Blurg")
//|| (mModuleName == "System_Int32")
//|| (mModuleName == "Hey_Dude_Bro_TestClass")
//|| (mModuleName == "Tests_FuncRefs_Class")
//|| (mModuleName == "Tests_FuncRefs")
)
mBfIRBuilder->mDbgVerifyCodeGen = true;
@ -3993,7 +3992,7 @@ void BfModule::CreateFakeCallerMethod(const String& funcName)
SizedArray<BfIRValue, 8> args;
BfExprEvaluator exprEvaluator(this);
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
auto retPtrType = CreatePointerType(mCurMethodInstance->mReturnType);
exprEvaluator.PushArg(GetDefaultTypedValue(retPtrType, true, BfDefaultValueKind_Const), args);
@ -4001,7 +4000,7 @@ void BfModule::CreateFakeCallerMethod(const String& funcName)
if (mCurMethodInstance->HasThis())
{
auto thisValue = GetDefaultTypedValue(mCurMethodInstance->GetOwner(), true);
auto thisValue = GetDefaultTypedValue(mCurMethodInstance->GetOwner(), true, mCurTypeInstance->IsComposite() ? BfDefaultValueKind_Addr : BfDefaultValueKind_Const);
exprEvaluator.PushThis(NULL, thisValue, mCurMethodInstance, args);
}
@ -12705,7 +12704,7 @@ void BfModule::CreateDIRetVal()
{
BfType* dbgType = mCurMethodInstance->mReturnType;
BfIRValue dbgValue = mCurMethodState->mRetVal.mValue;
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
BF_ASSERT(mCurMethodState->mRetValAddr);
dbgType = CreatePointerType(dbgType);
@ -13207,11 +13206,11 @@ void BfModule::MarkScopeLeft(BfScopeData* scopeData)
void BfModule::CreateReturn(BfIRValue val)
{
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
// Store to sret
BF_ASSERT(val);
mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(0));
mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
mBfIRBuilder->CreateRetVoid();
}
else
@ -13222,14 +13221,18 @@ void BfModule::CreateReturn(BfIRValue val)
}
else if (mCurMethodInstance->mReturnType->IsStruct())
{
auto loweredType = GetPrimitiveType(mCurMethodInstance->mReturnType->GetLoweredType());
auto ptrReturnType = CreatePointerType(mCurMethodInstance->mReturnType);
auto ptrLoweredValue = CreateAlloca(loweredType);
auto ptrReturnValue = mBfIRBuilder->CreateBitCast(ptrLoweredValue, mBfIRBuilder->MapType(ptrReturnType));
mBfIRBuilder->CreateStore(val, ptrReturnValue);
BfTypeCode loweredReturnType = BfTypeCode_None;
BfTypeCode loweredReturnType2 = BfTypeCode_None;
mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
auto loadedLoweredValue = mBfIRBuilder->CreateLoad(ptrLoweredValue);
mBfIRBuilder->CreateRet(loadedLoweredValue);
auto retVal = CreateAlloca(mCurMethodInstance->mReturnType);
mBfIRBuilder->CreateStore(val, retVal);
auto irRetType = GetIRLoweredType(loweredReturnType, loweredReturnType2);
irRetType = mBfIRBuilder->GetPointerTo(irRetType);
auto ptrReturnValue = mBfIRBuilder->CreateBitCast(retVal, irRetType);
auto loadedReturnValue = mBfIRBuilder->CreateLoad(ptrReturnValue);
mBfIRBuilder->CreateRet(loadedReturnValue);
}
else
{
@ -13286,7 +13289,7 @@ void BfModule::EmitDefaultReturn()
{
if (mCurMethodInstance->mReturnType->IsVoid())
mBfIRBuilder->CreateRetVoid();
else if (!mCurMethodInstance->HasStructRet())
else if (mCurMethodInstance->GetStructRetIdx() == -1)
mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType));
}
@ -13395,15 +13398,19 @@ void BfModule::CreateDelegateInvokeMethod()
if (mCurMethodInstance->mReturnType->IsValueType())
mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType, BfIRPopulateType_Full);
if (mCurMethodInstance->GetStructRetIdx() != 0)
memberFuncArgs.push_back(BfIRValue()); // Push 'target'
int thisIdx = 0;
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
thisIdx = 1;
staticFuncArgs.push_back(mBfIRBuilder->GetArgument(0));
memberFuncArgs.push_back(mBfIRBuilder->GetArgument(0));
thisIdx = mCurMethodInstance->GetStructRetIdx() ^ 1;
staticFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
memberFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
}
memberFuncArgs.push_back(BfIRValue()); // Push 'target'
if (mCurMethodInstance->GetStructRetIdx() == 0)
memberFuncArgs.push_back(BfIRValue()); // Push 'target'
mCurMethodInstance->GetIRFunctionInfo(this, origReturnType, staticParamTypes, true);
@ -13441,8 +13448,8 @@ void BfModule::CreateDelegateInvokeMethod()
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);
nonStaticResult = mBfIRBuilder->CreateCall(funcPtr, memberFuncArgs);
if (mCurMethodInstance->HasStructRet())
mBfIRBuilder->Call_AddAttribute(nonStaticResult, 1, BfIRAttribute_StructRet);
if (mCurMethodInstance->GetStructRetIdx() != -1)
mBfIRBuilder->Call_AddAttribute(nonStaticResult, mCurMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
if (callingConv != BfIRCallingConv_CDecl)
mBfIRBuilder->SetCallCallingConv(nonStaticResult, callingConv);
mCurMethodState->SetHadReturn(false);
@ -13459,8 +13466,11 @@ void BfModule::CreateDelegateInvokeMethod()
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, staticFuncPtrPtr);
auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);
staticResult = mBfIRBuilder->CreateCall(funcPtr, staticFuncArgs);
if (mCurMethodInstance->HasStructRet())
mBfIRBuilder->Call_AddAttribute(staticResult, 1, BfIRAttribute_StructRet);
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
// Note: since this is a forced static invocation, we know the sret will be the first parameter
mBfIRBuilder->Call_AddAttribute(staticResult, 0 + 1, BfIRAttribute_StructRet);
}
if (callingConv == BfIRCallingConv_ThisCall)
callingConv = BfIRCallingConv_CDecl;
if (callingConv != BfIRCallingConv_CDecl)
@ -13473,16 +13483,20 @@ void BfModule::CreateDelegateInvokeMethod()
mBfIRBuilder->AddBlock(doneBB);
mBfIRBuilder->SetInsertPoint(doneBB);
if ((mCurMethodInstance->mReturnType->IsValuelessType()) || (mCurMethodInstance->HasStructRet()))
if ((mCurMethodInstance->mReturnType->IsValuelessType()) || (mCurMethodInstance->GetStructRetIdx() != -1))
{
mBfIRBuilder->CreateRetVoid();
}
else
{
auto loweredReturnType = mCurMethodInstance->mReturnType;
if (loweredReturnType->GetLoweredType() != BfTypeCode_None)
loweredReturnType = GetPrimitiveType(loweredReturnType->GetLoweredType());
auto phi = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(loweredReturnType), 2);
BfIRType loweredIRReturnType;
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2))
loweredIRReturnType = GetIRLoweredType(loweredTypeCode, loweredTypeCode2);
else
loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
auto phi = mBfIRBuilder->CreatePhi(loweredIRReturnType, 2);
mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueBB);
mBfIRBuilder->AddPhiIncoming(phi, staticResult, falseBB);
mBfIRBuilder->CreateRet(phi);
@ -14365,21 +14379,24 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
int argCount = methodInstance->GetIRFunctionParamCount(this);
if (methodInstance->HasStructRet())
{
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoAlias);
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_StructRet);
argIdx++;
}
while (argIdx < argCount)
{
if (argIdx == methodInstance->GetStructRetIdx())
{
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoAlias);
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_StructRet);
argIdx++;
continue;
}
while ((paramIdx != -1) && (methodInstance->IsParamSkipped(paramIdx)))
paramIdx++;
BfType* resolvedTypeRef = NULL;
BfType* resolvedTypeRef2 = NULL;
String paramName;
bool isSplattable = false;
bool tryLowering = true;
bool isThis = paramIdx == -1;
if (isThis)
{
@ -14389,6 +14406,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
else
resolvedTypeRef = methodInstance->GetOwner();
isSplattable = (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsThisSplatting());
tryLowering = methodInstance->AllowsThisSplatting();
}
else
{
@ -14409,11 +14427,24 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
}
}
//
if (tryLowering)
{
auto loweredTypeCode = resolvedTypeRef->GetLoweredType();
if (loweredTypeCode != BfTypeCode_None)
resolvedTypeRef = GetPrimitiveType(loweredTypeCode);
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (resolvedTypeRef->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
mBfIRBuilder->Func_SetParamName(func, argIdx + 1, paramName + "__1");
argIdx++;
if (loweredTypeCode2 != BfTypeCode_None)
{
mBfIRBuilder->Func_SetParamName(func, argIdx + 1, paramName + "__2");
argIdx++;
}
paramIdx++;
continue;
}
}
auto _SetupParam = [&](const StringImpl& paramName, BfType* resolvedTypeRef)
@ -14432,16 +14463,17 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
}
if ((resolvedTypeRef->IsComposite()) && (!resolvedTypeRef->IsTypedPrimitive()))
{
if (mCompiler->mOptions.mAllowStructByVal)
{
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal);
}
else
if (paramIdx == -1)
{
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoCapture);
PopulateType(resolvedTypeRef, BfPopulateType_Data);
addDeref = resolvedTypeRef->mSize;
}
else
{
mBfIRBuilder->PopulateType(resolvedTypeRef);
mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal, mSystem->mPtrSize);
}
}
else if (resolvedTypeRef->IsPrimitiveType())
{
@ -14521,8 +14553,9 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
}
_SetupParam(paramName, resolvedTypeRef);
if (resolvedTypeRef2 != NULL)
_SetupParam(paramName, resolvedTypeRef2);
//argIdx++;
paramIdx++;
}
}
@ -15412,11 +15445,15 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
isThisStruct = thisType->IsStruct() && !thisType->IsTypedPrimitive();
int argIdx = 0;
if (methodInstance->HasStructRet())
if (argIdx == methodInstance->GetStructRetIdx())
argIdx++;
if (!methodDef->mIsStatic)
{
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
BfLocalVariable* paramVar = new BfLocalVariable();
paramVar->mResolvedType = thisType;
paramVar->mName = "this";
@ -15431,7 +15468,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
paramVar->mIsSplat = true;
}
else if ((!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified))
paramVar->mIsLowered = thisType->GetLoweredType() != BfTypeCode_None;
paramVar->mIsLowered = thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
auto thisTypeInst = thisType->ToTypeInstance();
paramVar->mIsStruct = isThisStruct;
@ -15472,8 +15509,14 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
argIdx++;
}
}
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
}
if (argIdx == methodInstance->GetStructRetIdx())
argIdx++;
bool hadParams = false;
bool hasDefault = false;
@ -15485,6 +15528,9 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
BfLocalVariable* paramVar = new BfLocalVariable();
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
bool isParamSkipped = methodInstance->IsParamSkipped(paramIdx);
BfType* unresolvedType = methodInstance->GetParamType(paramIdx, false);
@ -15529,7 +15575,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
paramVar->mIsSplat = true; // Treat skipped (valueless) as a splat
paramVar->mValue = mBfIRBuilder->GetFakeVal();
}
paramVar->mIsLowered = resolvedType->GetLoweredType() != BfTypeCode_None;
paramVar->mIsLowered = resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
paramVar->mIsStruct = resolvedType->IsComposite() && !resolvedType->IsTypedPrimitive();
paramVar->mParamIdx = paramIdx;
paramVar->mIsImplicitParam = methodInstance->IsImplicitCapture(paramIdx);
@ -15639,6 +15685,9 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
{
argIdx++;
}
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
}
}
@ -16755,9 +16804,6 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
int localIdx = 0;
int argIdx = 0;
if (methodInstance->HasStructRet())
argIdx++;
Array<BfIRValue> splatAddrValues;
for ( ; argIdx < irParamCount; localIdx++)
@ -16766,6 +16812,13 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
if ((isThis) && (thisType->IsValuelessType()))
isThis = false;
if (methodInstance->GetStructRetIdx() == argIdx)
{
argIdx++;
if (argIdx == irParamCount)
break;
}
BfLocalVariable* paramVar = NULL;
while (true)
{
@ -16782,7 +16835,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
paramVar->mIsReadOnly = true;
}
bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) || (paramVar->mResolvedType->GetLoweredType() != BfTypeCode_None);
bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) || (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter));
if (paramVar->mResolvedType->IsMethodRef())
wantsAddr = false;
@ -16895,6 +16948,15 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
}
else if (paramVar->mIsLowered)
{
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
argIdx++;
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
}
else
{
argIdx++;
@ -16909,12 +16971,13 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
int declArgIdx = 0;
localIdx = 0;
argIdx = 0;
if (methodInstance->HasStructRet())
argIdx++;
int splatAddrIdx = 0;
while (localIdx < (int)methodState.mLocals.size())
{
if (argIdx == methodInstance->GetStructRetIdx())
argIdx++;
int curLocalIdx = localIdx++;
BfLocalVariable* paramVar = methodState.mLocals[curLocalIdx];
if (!paramVar->IsParam())
@ -17010,19 +17073,34 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
bool handled = false;
if (paramVar->mIsLowered)
{
auto loweredTypeCode = paramVar->mResolvedType->GetLoweredType();
BF_ASSERT(loweredTypeCode != BfTypeCode_None);
if (loweredTypeCode != BfTypeCode_None)
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
// We have a lowered type coming in, so we have to cast the .addr before storing
auto primType = GetPrimitiveType(loweredTypeCode);
auto primPtrType = CreatePointerType(primType);
auto primPtrVal = mBfIRBuilder->CreateBitCast(paramVar->mAddr, mBfIRBuilder->MapType(primPtrType));
mBfIRBuilder->CreateAlignedStore(paramVar->mValue, primPtrVal, paramVar->mResolvedType->mSize);
auto primType = mBfIRBuilder->GetPrimitiveType(loweredTypeCode);
auto primPtrType = mBfIRBuilder->GetPointerTo(primType);
auto primPtrVal = mBfIRBuilder->CreateBitCast(paramVar->mAddr, primPtrType);
mBfIRBuilder->CreateStore(paramVar->mValue, primPtrVal);
if (loweredTypeCode2 != BfTypeCode_None)
{
declArgIdx++;
auto primType2 = mBfIRBuilder->GetPrimitiveType(loweredTypeCode2);
auto primPtrType2 = mBfIRBuilder->GetPointerTo(primType2);
auto primPtrVal2 = mBfIRBuilder->CreateBitCast(mBfIRBuilder->CreateInBoundsGEP(primPtrVal, 1), primPtrType2);
mBfIRBuilder->CreateStore(mBfIRBuilder->GetArgument(argIdx + 1), primPtrVal2);
}
// We don't want to allow directly using value
paramVar->mValue = BfIRValue();
handled = true;
}
else
{
BF_ASSERT("Expected lowered");
}
}
if (!handled)
@ -17190,6 +17268,15 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
}
else if (paramVar->mIsLowered)
{
argIdx++;
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
if (loweredTypeCode != BfTypeCode_None)
argIdx++;
}
else if (!paramVar->mResolvedType->IsValuelessType())
{
argIdx++;
@ -17322,10 +17409,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
BF_ASSERT(innerType->IsUnspecializedType());
}
else if (methodInstance->HasStructRet())
else if (methodInstance->GetStructRetIdx() != -1)
{
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(0), methodInstance->mReturnType, true);
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
exprEvaluator.mReceivingValue = &returnType;
auto retVal = exprEvaluator.CreateCall(innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
@ -17692,11 +17779,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
{
mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType);
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
{
auto ptrType = CreatePointerType(mCurMethodInstance->mReturnType);
auto allocaInst = AllocLocalVariable(ptrType, "__return.addr", false);
auto storeInst = mBfIRBuilder->CreateStore(mBfIRBuilder->GetArgument(0), allocaInst);
auto storeInst = mBfIRBuilder->CreateStore(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()), allocaInst);
mBfIRBuilder->ClearDebugLocation(storeInst);
mCurMethodState->mRetValAddr = allocaInst;
}
@ -17886,7 +17973,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
if (mCurMethodState->mIRExitBlock)
{
if ((mCurMethodState->mRetVal) && (!mCurMethodInstance->HasStructRet()))
if ((mCurMethodState->mRetVal) && (mCurMethodInstance->GetStructRetIdx() == -1))
{
auto loadedVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetVal.mValue);
@ -19914,8 +20001,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
int argIdx = 0;
PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
if (methodInstance->HasStructRet())
argIdx++;
if (!methodDef->mIsStatic)
{
if (methodInstance->GetParamIsSplat(-1))
@ -19923,6 +20008,10 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
else if (!methodInstance->GetOwner()->IsValuelessType())
argIdx++;
}
if (methodInstance->GetStructRetIdx() != -1)
argIdx++;
for (auto& methodParam : mCurMethodInstance->mParams)
{
if (methodParam.mResolvedType->IsMethodRef())

View file

@ -1631,6 +1631,7 @@ public:
BfTypeInstance* GetWrappedStructType(BfType* type, bool allowSpecialized = true);
BfTypeInstance* GetPrimitiveStructType(BfTypeCode typeCode);
BfPrimitiveType* GetPrimitiveType(BfTypeCode typeCode);
BfIRType GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2);
BfMethodRefType* CreateMethodRefType(BfMethodInstance* methodInstance, bool mustAlreadyExist = false);
BfType* FixIntUnknown(BfType* type);
void FixIntUnknown(BfTypedValue& typedVal, BfType* matchType = NULL);

View file

@ -3136,37 +3136,6 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (isCRepr)
{
typeInstance->mIsSplattable = false;
if ((mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) && (mCompiler->mSystem->mPtrSize == 4))
{
// Win32 splat rules
if ((typeInstance->mBaseType->mInstSize == 0) && (typeInstance->mInstSize <= 16))
{
typeInstance->mIsSplattable = true;
for (int fieldIdx = 0; fieldIdx < (int)typeInstance->mFieldInstances.size(); fieldIdx++)
{
auto fieldInstance = (BfFieldInstance*)&typeInstance->mFieldInstances[fieldIdx];
if (fieldInstance->mDataIdx >= 0)
{
if (!fieldInstance->mResolvedType->IsPrimitiveType())
typeInstance->mIsSplattable = false;
else
{
auto primType = (BfPrimitiveType*)fieldInstance->mResolvedType;
if ((primType->mTypeDef->mTypeCode != BfTypeCode_Int32) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_UInt32) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_IntPtr) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_UIntPtr) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_Pointer) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_Single) &&
(primType->mTypeDef->mTypeCode != BfTypeCode_Double))
typeInstance->mIsSplattable = false;
}
}
}
}
}
}
else
typeInstance->mIsSplattable = (dataCount <= 3) && (!hadNonSplattable);
@ -4736,6 +4705,18 @@ BfPrimitiveType* BfModule::GetPrimitiveType(BfTypeCode typeCode)
return primType;
}
BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2)
{
BF_ASSERT(loweredTypeCode != BfTypeCode_None);
if (loweredTypeCode2 == BfTypeCode_None)
return mBfIRBuilder->GetPrimitiveType(loweredTypeCode);
SizedArray<BfIRType, 2> types;
types.push_back(mBfIRBuilder->GetPrimitiveType(loweredTypeCode));
types.push_back(mBfIRBuilder->GetPrimitiveType(loweredTypeCode2));
return mBfIRBuilder->CreateStructType(types);
}
BfMethodRefType* BfModule::CreateMethodRefType(BfMethodInstance* methodInstance, bool mustAlreadyExist)
{
auto methodRefType = new BfMethodRefType();
@ -7803,6 +7784,10 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
genericTypeInst = new BfTypeInstance();
genericTypeInst->mGenericTypeInfo = new BfGenericTypeInfo();
genericTypeInst->mTypeDef = typeDef;
if (parentGenericTypeInstance->mGenericTypeInfo->mGenericParams.IsEmpty())
PopulateType(parentGenericTypeInstance, BfPopulateType_Declaration);
for (int i = 0; i < numParentGenericParams; i++)
{
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(parentGenericTypeInstance->mGenericTypeInfo->mGenericParams[i]->AddRef());

View file

@ -7370,7 +7370,8 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all
SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
ReadArguments(objectCreateExpr, objectCreateExpr, &arguments, &commas, BfToken_None, true);
}
MEMBER_SET(objectCreateExpr, mCloseToken, block->mCloseBrace);
if (block->mCloseBrace != NULL)
MEMBER_SET(objectCreateExpr, mCloseToken, block->mCloseBrace);
return objectCreateExpr;
}

View file

@ -611,9 +611,24 @@ bool BfMethodInstance::HasParamsArray()
return GetParamKind((int)mParams.size() - 1) == BfParamKind_Params;
}
bool BfMethodInstance::HasStructRet()
int BfMethodInstance::GetStructRetIdx()
{
return (mReturnType->IsComposite()) && (!mReturnType->IsValuelessType()) && (mReturnType->GetLoweredType() == BfTypeCode_None);
if ((mReturnType->IsComposite()) && (!mReturnType->IsValuelessType()) && (!GetLoweredReturnType()))
{
auto owner = mMethodInstanceGroup->mOwner;
if (owner->mModule->mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)
return 0;
if (!HasThis())
return 0;
if (!owner->IsValueType())
return 1;
if ((mMethodDef->mIsMutating) || ((!AllowsSplatting()) && (!owner->GetLoweredType(BfTypeUsage_Parameter))))
return 1;
return 0;
}
return -1;
}
bool BfMethodInstance::HasSelf()
@ -626,6 +641,11 @@ bool BfMethodInstance::HasSelf()
return false;
}
bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2)
{
return mReturnType->GetLoweredType(mMethodDef->mIsStatic ? BfTypeUsage_Return_Static : BfTypeUsage_Return_NonStatic, loweredTypeCode, loweredTypeCode2);
}
bool BfMethodInstance::IsSkipCall(bool bypassVirtual)
{
if ((mMethodDef->mIsSkipCall) &&
@ -743,7 +763,7 @@ BfType* BfMethodInstance::GetParamType(int paramIdx, bool useResolvedType)
return mMethodInfoEx->mClosureInstanceInfo->mThisOverride;
BF_ASSERT(!mMethodDef->mIsStatic);
auto owner = mMethodInstanceGroup->mOwner;
if ((owner->IsValueType()) && ((mMethodDef->mIsMutating) || (!AllowsSplatting())) && (owner->GetLoweredType() == BfTypeCode_None))
if ((owner->IsValueType()) && ((mMethodDef->mIsMutating) || (!AllowsSplatting())) && (!owner->GetLoweredType(BfTypeUsage_Parameter)))
return owner->mModule->CreatePointerType(owner);
return owner;
}
@ -849,8 +869,6 @@ BfIdentifierNode* BfMethodInstance::GetParamNameNode(int paramIdx)
BfParameterDef* paramDef = mMethodDef->mParams[methodParam->mParamDefIdx];
if (paramDef->mParamDeclaration != NULL)
return BfNodeDynCast<BfIdentifierNode>(paramDef->mParamDeclaration->mNameNode);
// else if ((mClosureInstanceInfo != NULL) && (paramIdx < (int)mClosureInstanceInfo->mCaptureNodes.size()))
// return mClosureInstanceInfo->mCaptureNodes[paramIdx];
return NULL;
}
@ -897,34 +915,36 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
{
module->PopulateType(mReturnType);
BfType* loweredReturnType = mReturnType;
auto loweredReturnTypeCode = mReturnType->GetLoweredType();
if (loweredReturnTypeCode != BfTypeCode_None)
loweredReturnType = module->GetPrimitiveType(loweredReturnTypeCode);
if (loweredReturnType->IsValuelessType())
BfTypeCode loweredReturnTypeCode = BfTypeCode_None;
BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;
if (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2))
{
auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2);
returnType = irReturnType;
}
else if (mReturnType->IsValuelessType())
{
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
}
else if (loweredReturnType->IsComposite())
else if (mReturnType->IsComposite())
{
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
auto typeInst = loweredReturnType->ToTypeInstance();
auto typeInst = mReturnType->ToTypeInstance();
if (typeInst != NULL)
{
paramTypes.push_back(module->mBfIRBuilder->MapTypeInstPtr(typeInst));
}
else
{
auto ptrType = module->CreatePointerType(loweredReturnType);
auto ptrType = module->CreatePointerType(mReturnType);
paramTypes.push_back(module->mBfIRBuilder->MapType(ptrType));
}
}
else
{
returnType = module->mBfIRBuilder->MapType(loweredReturnType);
returnType = module->mBfIRBuilder->MapType(mReturnType);
}
for (int paramIdx = -1; paramIdx < GetParamCount(); paramIdx++)
@ -972,11 +992,18 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
checkLowered = true;
}
BfType* checkType2 = NULL;
if (checkLowered)
{
auto loweredTypeCode = checkType->GetLoweredType();
if (loweredTypeCode != BfTypeCode_None)
checkType = module->GetPrimitiveType(loweredTypeCode);
BfTypeCode loweredTypeCode = BfTypeCode_None;
BfTypeCode loweredTypeCode2 = BfTypeCode_None;
if (checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
{
paramTypes.push_back(module->mBfIRBuilder->GetPrimitiveType(loweredTypeCode));
if (loweredTypeCode2 != BfTypeCode_None)
paramTypes.push_back(module->mBfIRBuilder->GetPrimitiveType(loweredTypeCode2));
continue;
}
}
if ((paramIdx == 0) && (GetParamName(0) == "this") && (checkType->IsPointer()))
@ -1034,6 +1061,13 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
else
_AddType(checkType);
if (checkType2 != NULL)
_AddType(checkType2);
}
if ((GetStructRetIdx() == 1) && (!forceStatic))
{
BF_SWAP(paramTypes[0], paramTypes[1]);
}
}
@ -1414,19 +1448,100 @@ BfPrimitiveType* BfTypeInstance::GetDiscriminatorType(int* outDataIdx)
return (BfPrimitiveType*)fieldInstance.mResolvedType;
}
BfTypeCode BfTypeInstance::GetLoweredType()
bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode, BfTypeCode* outTypeCode2)
{
if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (mIsSplattable))
return BfTypeCode_None;
if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (IsBoxed()) || (mIsSplattable))
return false;
if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows)
{
// Odd Windows rule: composite returns for non-static methods are always sret
if (typeUsage == BfTypeUsage_Return_NonStatic)
return false;
}
else
{
// Non-Windows systems allow lowered splitting of composites over two int params
if (mModule->mSystem->mPtrSize == 8)
{
if (mInstSize == 12)
{
if (outTypeCode != NULL)
*outTypeCode = BfTypeCode_Int64;
if (outTypeCode2 != NULL)
*outTypeCode2 = BfTypeCode_Int32;
return true;
}
if (mInstSize == 16)
{
if (outTypeCode != NULL)
*outTypeCode = BfTypeCode_Int64;
if (outTypeCode2 != NULL)
*outTypeCode2 = BfTypeCode_Int64;
return true;
}
}
}
BfTypeCode typeCode = BfTypeCode_None;
BfTypeCode pow2TypeCode = BfTypeCode_None;
switch (mInstSize)
{
case 1: return BfTypeCode_Int8;
case 2: return BfTypeCode_Int16;
case 4: return BfTypeCode_Int32;
case 8: if (mModule->mSystem->mPtrSize == 8) return BfTypeCode_Int64;
case 1:
pow2TypeCode = BfTypeCode_Int8;
break;
case 2:
pow2TypeCode = BfTypeCode_Int16;
break;
case 3:
typeCode = BfTypeCode_Int24;
break;
case 4:
pow2TypeCode = BfTypeCode_Int32;
break;
case 5:
typeCode = BfTypeCode_Int40;
break;
case 6:
typeCode = BfTypeCode_Int48;
break;
case 7:
typeCode = BfTypeCode_Int56;
break;
case 8:
if (mModule->mSystem->mPtrSize == 8)
{
pow2TypeCode = BfTypeCode_Int64;
break;
}
if (typeUsage == BfTypeUsage_Return_Static)
{
pow2TypeCode = BfTypeCode_Int64;
break;
}
break;
}
return BfTypeCode_None;
if (pow2TypeCode != BfTypeCode_None)
{
if (outTypeCode != NULL)
*outTypeCode = pow2TypeCode;
return true;
}
if (mModule->mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)
{
if (typeCode != BfTypeCode_None)
{
if (outTypeCode != NULL)
*outTypeCode = typeCode;
return true;
}
}
return false;
}
bool BfTypeInstance::HasEquivalentLayout(BfTypeInstance* compareTo)

View file

@ -428,6 +428,14 @@ public:
}
};
enum BfTypeUsage
{
BfTypeUsage_Unspecified,
BfTypeUsage_Return_Static,
BfTypeUsage_Return_NonStatic,
BfTypeUsage_Parameter,
};
class BfType
{
public:
@ -539,7 +547,7 @@ public:
virtual bool IsConstExprValue() { return false; }
virtual bool IsDependentOnUnderlyingType() { return false; }
virtual bool WantsGCMarking() { return false; }
virtual BfTypeCode GetLoweredType() { return BfTypeCode_None; }
virtual bool GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode = NULL, BfTypeCode* outTypeCode2 = NULL) { return false; }
virtual BfType* GetUnderlyingType() { return NULL; }
virtual bool HasWrappedRepresentation() { return IsWrappableType(); }
virtual bool IsTypeMemberIncluded(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef = NULL, BfModule* module = NULL) { return true; } // May be 'false' only for generic extensions with constraints
@ -852,8 +860,9 @@ public:
bool IsSpecializedByAutoCompleteMethod();
bool HasThis();
bool HasParamsArray();
bool HasStructRet();
int GetStructRetIdx();
bool HasSelf();
bool GetLoweredReturnType(BfTypeCode* loweredTypeCode = NULL, BfTypeCode* loweredTypeCode2 = NULL);
bool IsAutocompleteMethod() { /*return mIdHash == -1;*/ return mIsAutocompleteMethod; }
bool IsSkipCall(bool bypassVirtual = false);
bool IsVarArgs();
@ -1827,11 +1836,11 @@ public:
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) override;
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) override;
virtual bool WantsGCMarking() override;
virtual BfTypeCode GetLoweredType() override;
virtual bool GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode = NULL, BfTypeCode* outTypeCode2 = NULL) override;
BfGenericTypeInfo* GetGenericTypeInfo() { return mGenericTypeInfo; }
virtual BfTypeInstance* ToGenericTypeInstance() { return (mGenericTypeInfo != NULL) ? this : NULL; }
virtual BfTypeInstance* ToGenericTypeInstance() override { return (mGenericTypeInfo != NULL) ? this : NULL; }
virtual bool IsGenericTypeInstance() override { return mGenericTypeInfo != NULL; }
virtual bool IsSpecializedType() override { return (mGenericTypeInfo != NULL) && (!mGenericTypeInfo->mIsUnspecialized); }
virtual bool IsSpecializedByAutoCompleteMethod() override;
@ -2020,7 +2029,7 @@ public:
virtual bool IsUnspecializedType() override { return mIsUnspecializedType; }
virtual bool IsUnspecializedTypeVariation() override { return mIsUnspecializedTypeVariation; }
virtual BfDelegateInfo* GetDelegateInfo() { return &mDelegateInfo; }
virtual BfDelegateInfo* GetDelegateInfo() override { return &mDelegateInfo; }
};
class BfTupleType : public BfTypeInstance

View file

@ -4885,12 +4885,12 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
BfType* origType;
BfExprEvaluator exprEvaluator(this);
bool alreadyWritten = false;
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
exprEvaluator.mReceivingValue = &mCurMethodState->mRetVal;
if (mCurMethodInstance->mMethodDef->mIsReadOnly)
exprEvaluator.mAllowReadOnlyReference = true;
auto retValue = CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, expectingReturnType, BfEvalExprFlags_AllowRefExpr, &origType);
if (mCurMethodInstance->HasStructRet())
if (mCurMethodInstance->GetStructRetIdx() != -1)
alreadyWritten = exprEvaluator.mReceivingValue == NULL;
MarkScopeLeft(&mCurMethodState->mHeadScope);

View file

@ -6734,7 +6734,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(BfAstNode* targetSrc, DbgTypedValue t
if ((param != NULL) && (param->mType != NULL) && (param->mType->IsCompositeType()))
{
if (splatParams.Contains(param->mName))
if ((param->mName != NULL) && (splatParams.Contains(param->mName)))
{
std::function<void(const DbgTypedValue& typedVal)> _SplatArgs = [&](const DbgTypedValue& typedVal)
{
@ -7267,7 +7267,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
}
else if (methodName == "__demangleMethod")
{
if (argValues.size() == 1)
if (argValues.size() == 2)
{
auto checkType = argValues[0].mType;
if (checkType->IsPointer())
@ -7293,6 +7293,27 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
}
}
}
else if (methodName == "__demangle")
{
if (argValues.size() == 1)
{
auto rawTextType = mDbgModule->GetPrimitiveType(DbgType_RawText, GetLanguage());
String mangledName = argValues[0].mCharPtr;
static String demangledName;
demangledName = BfDemangler::Demangle(mangledName, DbgLanguage_Unknown);
if (demangledName.StartsWith("bf."))
demangledName.Remove(0, 3);
DbgTypedValue result;
result.mType = rawTextType;
result.mCharPtr = demangledName.c_str();
result.mIsLiteral = true;
return result;
}
}
else if (methodName == "__demangleFakeMember")
{
if (argValues.size() == 1)

View file

@ -158,6 +158,18 @@ public:
return mPtr;
}
String GetString() const
{
if (!mType->IsPointer())
return "";
if ((mType->mTypeParam->mTypeCode != DbgType_SChar) && (mType->mTypeParam->mTypeCode != DbgType_UChar))
return "";
if (mIsLiteral)
return mCharPtr;
//return (const char*)mPtr;
return "";
}
operator bool() const
{
return (mType != NULL) && (!mHasNoValue);

View file

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.645
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLib", "CLib.vcxproj", "{D72A956A-5D9C-42F4-B35B-05F0B05B632C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Debug|x64.ActiveCfg = Debug|x64
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Debug|x64.Build.0 = Debug|x64
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Debug|x86.ActiveCfg = Debug|Win32
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Debug|x86.Build.0 = Debug|Win32
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Release|x64.ActiveCfg = Release|x64
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Release|x64.Build.0 = Release|x64
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Release|x86.ActiveCfg = Release|Win32
{D72A956A-5D9C-42F4-B35B-05F0B05B632C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B4D3315D-D9A9-4A82-BEC4-B05271FC794E}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{D72A956A-5D9C-42F4-B35B-05F0B05B632C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>CLib</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,371 @@
#include <inttypes.h>
namespace Tests
{
struct Interop
{
struct StructA
{
int mA;
int MethodA0(int arg0)
{
return arg0 + mA * 100;
}
StructA MethodA1(StructA other, int arg0)
{
StructA ret;
ret.mA = mA + other.mA + arg0;
return ret;
}
};
struct StructB
{
int mA;
char mB;
int MethodB0(int arg0)
{
return arg0 + mA * 100 + mB * 10000;
}
StructB MethodB1(StructB other, int arg0)
{
StructB ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructC
{
char mA;
int mB;
int MethodC0(int arg0)
{
return arg0 + mA * 100 + mB * 10000;
}
StructC MethodC1(StructC other, int arg0)
{
StructC ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructD
{
int mA;
int mB;
int MethodD0(int arg0)
{
return arg0 + mA * 100 + mB * 10000;
}
StructD MethodD1(StructD other, int arg0)
{
StructD ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructE
{
int mA;
int mB;
int mC;
int MethodE0(int arg0)
{
return arg0 + mA * 100 + mC * 10000;
}
StructE MethodE1(StructE other, int arg0)
{
StructE ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructF
{
char mA;
char mB;
char mC;
int MethodF0(int arg0)
{
return arg0 + mA * 100 + mC * 10000;
}
StructF MethodF1(StructF other, int arg0)
{
StructF ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructG
{
char mA;
char mB;
char mC;
char mD;
int MethodG0(int arg0)
{
return arg0 + mA * 100 + mC * 10000;
}
StructG MethodG1(StructG other, int arg0)
{
StructG ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructH
{
int64_t mA;
int64_t mB;
int64_t mC;
int MethodH0(int arg0)
{
return arg0 + (int)mA * 100 + (int)mC * 10000;
}
StructH MethodH1(StructH other, int arg0)
{
StructH ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
struct StructI
{
char mA;
char mB;
char mC;
char mD;
char mE;
int MethodI0(int arg0)
{
return arg0 + (int)mA * 100 + (int)mC * 10000;
}
StructI MethodI1(StructI other, int arg0)
{
StructI ret;
ret.mA = mA + other.mA + arg0;
ret.mB = mB + other.mB;
return ret;
}
};
};
}
using namespace Tests;
extern "C" int Func0(int a, int b)
{
return a + b * 100;
}
//////////////////////////////////////////////////////////////////////////
extern "C" int Func1A(Interop::StructA arg0, Interop::StructA arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1B(Interop::StructB arg0, Interop::StructB arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1C(Interop::StructC arg0, Interop::StructC arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1D(Interop::StructD arg0, Interop::StructD arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1E(Interop::StructE arg0, Interop::StructE arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1F(Interop::StructF arg0, Interop::StructF arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1G(Interop::StructG arg0, Interop::StructG arg1, int arg2)
{
return arg0.mA + arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1H(Interop::StructH arg0, Interop::StructH arg1, int arg2)
{
return (int)arg0.mA + (int)arg1.mA * 100 + arg2 * 10000;
}
extern "C" int Func1I(Interop::StructI arg0, Interop::StructI arg1, int arg2)
{
return (int)arg0.mA + (int)arg1.mA * 100 + arg2 * 10000;
}
//////////////////////////////////////////////////////////////////////////
extern "C" Interop::StructA Func2A(Interop::StructA arg0, int arg1)
{
Interop::StructA ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructB Func2B(Interop::StructB arg0, int arg1)
{
Interop::StructB ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructC Func2C(Interop::StructC arg0, int arg1)
{
Interop::StructC ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructD Func2D(Interop::StructD arg0, int arg1)
{
Interop::StructD ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructE Func2E(Interop::StructE arg0, int arg1)
{
Interop::StructE ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructF Func2F(Interop::StructF arg0, int arg1)
{
Interop::StructF ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructG Func2G(Interop::StructG arg0, int arg1)
{
Interop::StructG ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructH Func2H(Interop::StructH arg0, int arg1)
{
Interop::StructH ret;
ret.mA = arg0.mA + arg1;
return ret;
}
extern "C" Interop::StructI Func2I(Interop::StructI arg0, int arg1)
{
Interop::StructI ret;
ret.mA = arg0.mA + arg1;
return ret;
}
//////////////////////////////////////////////////////////////////////////
extern "C" int Func3A(Interop::StructA* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3B(Interop::StructB* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3C(Interop::StructC* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3D(Interop::StructD* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3E(Interop::StructE* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3F(Interop::StructF* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
extern "C" int Func3G(Interop::StructG* ptr)
{
return ptr[0].mA + ptr[1].mA * 100;
}
void UseIt()
{
Interop::StructA sa;
sa.MethodA0(0);
sa.MethodA1(sa, 1);
Interop::StructB sb;
sb.MethodB0(0);
sb.MethodB1(sb, 1);
Interop::StructC sc;
sc.MethodC0(0);
sc.MethodC1(sc, 1);
Interop::StructD sd;
sd.MethodD0(0);
sd.MethodD1(sd, 1);
Interop::StructE se;
se.MethodE0(0);
se.MethodE1(se, 1);
Interop::StructF sf;
sf.MethodF0(0);
sf.MethodF1(sf, 1);
Interop::StructG sg;
sg.MethodG0(0);
sg.MethodG1(sg, 1);
Interop::StructH sh;
sh.MethodH0(0);
sh.MethodH1(sh, 1);
Interop::StructI si;
si.MethodI0(0);
si.MethodI1(si, 1);
}

View file

@ -0,0 +1,261 @@
using System;
namespace Tests
{
class Interop
{
[CRepr]
public struct StructA
{
public int32 mA;
[LinkName(.CPP)]
public extern int32 MethodA0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructA MethodA1(StructA sa, int32 arg0) mut;
}
[CRepr]
public struct StructB
{
public int32 mA;
public int8 mB;
[LinkName(.CPP)]
public extern int32 MethodB0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructB MethodB1(StructB sa, int32 arg0) mut;
}
[CRepr]
public struct StructC
{
public int8 mA;
public int32 mB;
[LinkName(.CPP)]
public extern int32 MethodC0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructC MethodC1(StructC sa, int32 arg0) mut;
}
[CRepr]
public struct StructD
{
public int32 mA;
public int32 mB;
[LinkName(.CPP)]
public extern int32 MethodD0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructD MethodD1(StructD sa, int32 arg0) mut;
}
[CRepr]
public struct StructE
{
public int32 mA;
public int32 mB;
public int32 mC;
[LinkName(.CPP)]
public extern int32 MethodE0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructE MethodE1(StructE sa, int32 arg0) mut;
}
[CRepr]
public struct StructF
{
public int8 mA;
public int8 mB;
public int8 mC;
[LinkName(.CPP)]
public extern int32 MethodF0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructF MethodF1(StructF sa, int32 arg0) mut;
}
[CRepr]
public struct StructG
{
public int8 mA;
public int8 mB;
public int8 mC;
public int8 mD;
[LinkName(.CPP)]
public extern int32 MethodG0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructG MethodG1(StructG sa, int32 arg0) mut;
}
[CRepr]
public struct StructH
{
public int64 mA;
public int64 mB;
public int64 mC;
[LinkName(.CPP)]
public extern int32 MethodH0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructH MethodH1(StructH sa, int32 arg0) mut;
}
[CRepr]
public struct StructI
{
public int8 mA;
public int8 mB;
public int8 mC;
public int8 mD;
public int8 mE;
[LinkName(.CPP)]
public extern int32 MethodI0(int32 arg0) mut;
[LinkName(.CPP)]
public extern StructI MethodI1(StructI sa, int32 arg0) mut;
}
[LinkName(.C)]
public static extern int32 Func0(int32 a, int32 b);
[LinkName(.C)]
public static extern int32 Func1A(StructA arg0, StructA arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1B(StructB arg0, StructB arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1C(StructC arg0, StructC arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1D(StructD arg0, StructD arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1E(StructE arg0, StructE arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1F(StructF arg0, StructF arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1G(StructG arg0, StructG arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1H(StructH arg0, StructH arg1, int32 arg2);
[LinkName(.C)]
public static extern int32 Func1I(StructI arg0, StructI arg1, int32 arg2);
[LinkName(.C)]
public static extern StructA Func2A(StructA arg0, int32 arg2);
[LinkName(.C)]
public static extern StructB Func2B(StructB arg0, int32 arg2);
[LinkName(.C)]
public static extern StructC Func2C(StructC arg0, int32 arg2);
[LinkName(.C)]
public static extern StructD Func2D(StructD arg0, int32 arg2);
[LinkName(.C)]
public static extern StructE Func2E(StructE arg0, int32 arg2);
[LinkName(.C)]
public static extern StructF Func2F(StructF arg0, int32 arg2);
[LinkName(.C)]
public static extern StructG Func2G(StructG arg0, int32 arg2);
[LinkName(.C)]
public static extern StructH Func2H(StructH arg0, int32 arg2);
[LinkName(.C)]
public static extern StructI Func2I(StructI arg0, int32 arg2);
[Test]
public static void TestBasics()
{
//return;
StructA sa0 = default;
sa0.mA = 10;
StructA sa1 = default;
sa1.mA = 11;
StructB sb0 = default;
sb0.mA = 20;
StructB sb1 = default;
sb1.mA = 21;
StructC sc0 = default;
sc0.mA = 30;
StructC sc1 = default;
sc1.mA = 31;
StructD sd0 = default;
sd0.mA = 40;
StructD sd1 = default;
sd1.mA = 41;
StructE se0 = default;
se0.mA = 50;
StructE se1 = default;
se1.mA = 51;
StructF sf0 = default;
sf0.mA = 60;
StructF sf1 = default;
sf1.mA = 61;
StructG sg0 = default;
sg0.mA = 70;
StructG sg1 = default;
sg1.mA = 71;
StructH sh0 = default;
sh0.mA = 80;
StructH sh1 = default;
sh1.mA = 81;
StructI si0 = default;
si0.mA = 90;
StructI si1 = default;
si1.mA = 91;
Test.Assert(Func0(12, 34) == 3412);
Test.Assert(Func1A(sa0, sa1, 12) == 121110);
Test.Assert(sa0.MethodA0(12) == 1012);
Test.Assert(sa0.MethodA1(sa1, 12).mA == 33);
Test.Assert(Func2A(sa0, 12).mA == 22);
Test.Assert(Func1B(sb0, sb1, 12) == 122120);
Test.Assert(sb0.MethodB0(12) == 2012);
Test.Assert(sb0.MethodB1(sb1, 12).mA == 53);
Test.Assert(Func2B(sb0, 12).mA == 32);
Test.Assert(Func1C(sc0, sc1, 12) == 123130);
Test.Assert(sc0.MethodC0(12) == 3012);
Test.Assert(sc0.MethodC1(sc1, 12).mA == 73);
Test.Assert(Func2C(sc0, 12).mA == 42);
Test.Assert(Func1D(sd0, sd1, 12) == 124140);
Test.Assert(sd0.MethodD0(12) == 4012);
Test.Assert(sd0.MethodD1(sd1, 12).mA == 93);
Test.Assert(Func2D(sd0, 12).mA == 52);
Test.Assert(Func1E(se0, se1, 12) == 125150);
Test.Assert(se0.MethodE0(12) == 5012);
Test.Assert(se0.MethodE1(se1, 12).mA == 113);
Test.Assert(Func2E(se0, 12).mA == 62);
Test.Assert(Func1F(sf0, sf1, 12) == 126160);
Test.Assert(sf0.MethodF0(12) == 6012);
Test.Assert(sf0.MethodF1(sf1, 12).mA == (int8)133);
Test.Assert(Func2F(sf0, 12).mA == 72);
Test.Assert(Func1G(sg0, sg1, 12) == 127170);
Test.Assert(sg0.MethodG0(12) == 7012);
Test.Assert(sg0.MethodG1(sg1, 12).mA == (int8)153);
Test.Assert(Func2G(sg0, 12).mA == 82);
Test.Assert(Func1H(sh0, sh1, 12) == 128180);
Test.Assert(sh0.MethodH0(12) == 8012);
Test.Assert(sh0.MethodH1(sh1, 12).mA == 173);
Test.Assert(Func2H(sh0, 12).mA == 92);
Test.Assert(Func1I(si0, si1, 12) == 129190);
Test.Assert(si0.MethodI0(12) == 9012);
Test.Assert(si0.MethodI1(si1, 12).mA == (int8)193);
Test.Assert(Func2I(si0, 12).mA == 102);
}
}
}

View file

@ -9,11 +9,15 @@ md stats
@REM GOTO RANDO
@ECHO Testing IDEHelper\Tests
CALL bin/msbuild.bat IDEHelper\Tests\CLib\CLib.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:SolutionDir=%cd%\ /v:m
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR
IDE\dist\BeefBuild_d -proddir=IDEHelper\Tests -test
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR
@ECHO Testing IDEHelper\Tests (Win32)
CALL bin/msbuild.bat IDEHelper\Tests\CLib\CLib.vcxproj /p:Configuration=Debug /p:Platform=x86 /p:SolutionDir=%cd%\ /v:m
IDE\dist\BeefBuild_d -proddir=IDEHelper\Tests -test -platform=Win32
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR

11
extern/llvm_build.sh vendored
View file

@ -3,12 +3,13 @@ set -e
if [ ! -d llvm-project_8_0_0 ]; then
git clone https://github.com/llvm/llvm-project.git llvm-project_8_0_0
fi
if [ -d llvm-project_8_0_0 ]; then
cd llvm-project_8_0_0
git checkout llvmorg-8.0.0
cd ..
if [ -d llvm-project_8_0_0 ]; then
cd llvm-project_8_0_0
git checkout llvmorg-8.0.0
cd ..
fi
fi
if [ ! -d llvm_linux_8_0_0 ]; then