diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index 4704e638..4dd302d9 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -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, diff --git a/IDE/mintest/minlib/src/System/Type.bf b/IDE/mintest/minlib/src/System/Type.bf index 503ab2ff..b4dd702e 100644 --- a/IDE/mintest/minlib/src/System/Type.bf +++ b/IDE/mintest/minlib/src/System/Type.bf @@ -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, diff --git a/IDEHelper/Backend/BeContext.cpp b/IDEHelper/Backend/BeContext.cpp index cbe013c7..872a5b02 100644 --- a/IDEHelper/Backend/BeContext.cpp +++ b/IDEHelper/Backend/BeContext.cpp @@ -71,6 +71,22 @@ BeStructType* BeContext::CreateStruct(const StringImpl& name) return structType; } +BeStructType* BeContext::CreateStruct(const SizedArrayImpl& types) +{ + BeStructType** valuePtr = NULL; + if (mAnonymousStructMap.TryGetValueWith(types, &valuePtr)) + return *valuePtr; + + Array 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) diff --git a/IDEHelper/Backend/BeContext.h b/IDEHelper/Backend/BeContext.h index 8b62fba1..cba7f1cc 100644 --- a/IDEHelper/Backend/BeContext.h +++ b/IDEHelper/Backend/BeContext.h @@ -226,14 +226,16 @@ public: //BumpAllocator mAlloc; BeType* mPrimitiveTypes[BeTypeCode_COUNT]; OwnedVector mTypes; + Dictionary, BeStructType*> mAnonymousStructMap; public: void NotImpl(); public: BeContext(); - BeType* GetPrimitiveType(BeTypeCode typeCode); + BeType* GetPrimitiveType(BeTypeCode typeCode); BeStructType* CreateStruct(const StringImpl& name); + BeStructType* CreateStruct(const SizedArrayImpl& types); BePointerType* GetPointerTo(BeType* beType); void SetStructBody(BeStructType* structType, const SizedArrayImpl& types, bool packed); BeSizedArrayType* CreateSizedArrayType(BeType* type, int length); diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index f069c327..06d0a6ec 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -963,6 +963,13 @@ void BeIRCodeGen::HandleNextCmd() SetResult(curId, mBeContext->CreateStruct(typeName)); } break; + case BfIRCmd_CreateAnonymousStruct: + { + CMD_PARAM(CmdParamVec, 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(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(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"); } diff --git a/IDEHelper/Backend/BeModule.cpp b/IDEHelper/Backend/BeModule.cpp index 635d04c4..7c17ae19 100644 --- a/IDEHelper/Backend/BeModule.cpp +++ b/IDEHelper/Backend/BeModule.cpp @@ -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); diff --git a/IDEHelper/Backend/BeModule.h b/IDEHelper/Backend/BeModule.h index 0ca7d7f5..0816b11b 100644 --- a/IDEHelper/Backend/BeModule.h +++ b/IDEHelper/Backend/BeModule.h @@ -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); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 34af594f..f157f4c4 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -3470,6 +3470,8 @@ void BfCompiler::VisitSourceExteriorNodes() if (parser->mAwaitingDelete) return; + if (parser->mParserData == NULL) + return; if (parser->mParserData->mExteriorNodesCheckIdx == mSystem->mTypeMapVersion) return; diff --git a/IDEHelper/Compiler/BfDemangler.cpp b/IDEHelper/Compiler/BfDemangler.cpp index b28b1ab2..9df61596 100644 --- a/IDEHelper/Compiler/BfDemangler.cpp +++ b/IDEHelper/Compiler/BfDemangler.cpp @@ -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; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index f45d88cf..c22ce4de 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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'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 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,8 +4836,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV if ((addDeref <= 0) && (!elementType->IsValuelessType())) mModule->AssertErrorState(); } + if ((paramType->IsComposite()) && (!paramType->IsTypedPrimitive())) - { + { if (mModule->mCompiler->mOptions.mAllowStructByVal) { //byval @@ -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& 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; } @@ -5436,9 +5502,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu } else { - wantsSplat = methodInstance->GetParamIsSplat(paramIdx); + 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) @@ -9909,8 +9969,10 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) if (hasCaptures) { hasThis = true; - methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes); - int thisIdx = methodInstance->HasStructRet() ? 1 : 0; + methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes); + 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()) - { - mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_NoAlias); - mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_StructRet); + if (methodInstance->GetStructRetIdx() != -1) + { + 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,10 +10009,18 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) fieldIdx = 0; SizedArray irArgs; - int argIdx = 0; - if (methodInstance->HasStructRet()) - irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++)); + if (methodInstance->mIdHash == 775) + { + NOP; + } + int argIdx = 0; + if (bindMethodInstance->GetStructRetIdx() == 0) + { + irArgs.push_back(mModule->mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx())); + argIdx++; + } + for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++) { auto fieldInst = &useTypeInstance->mFieldInstances[fieldIdx]; @@ -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); @@ -9974,6 +10047,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++) { @@ -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(); } @@ -10783,14 +10862,17 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam origReturnType = mModule->mBfIRBuilder->MapType(mModule->GetPrimitiveType(BfTypeCode_None)); } - SizedArray newTypes; - if ((invokeMethodInstance != NULL) && (invokeMethodInstance->HasStructRet())) + SizedArray newTypes; + + 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; diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index f2359a49..485592a2 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -3305,6 +3305,13 @@ BfIRType BfIRBuilder::CreateStructType(const StringImpl& name) return retType; } +BfIRType BfIRBuilder::CreateStructType(const BfSizedArray& memberTypes) +{ + BfIRType retType = WriteCmd(BfIRCmd_CreateAnonymousStruct, memberTypes); + NEW_CMD_INSERTED_IRTYPE; + return retType; +} + void BfIRBuilder::StructSetBody(BfIRType type, const BfSizedArray& 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; diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index 9a7c2d7c..5c6ff727 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -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_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& memberTypes); void StructSetBody(BfIRType type, const BfSizedArray& memberTypes, bool isPacked); BfIRType MapType(BfType* type, BfIRPopulateType populateType = BfIRPopulateType_Declaration); BfIRType MapTypeInst(BfTypeInstance* typeInst, BfIRPopulateType populateType = BfIRPopulateType_Declaration); diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index aba9592d..56030b22 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -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,12 +1141,19 @@ void BfIRCodeGen::HandleNextCmd() SetResult(curId, GetLLVMType(typeCode, isSigned)); } break; + case BfIRCmd_CreateAnonymousStruct: + { + CMD_PARAM(CmdParamVec, members); + llvm::StructType* structType = llvm::StructType::get(*mLLVMContext, members); + SetResult(curId, structType); + } + break; case BfIRCmd_CreateStruct: { CMD_PARAM(String, typeName); SetResult(curId, llvm::StructType::create(*mLLVMContext, typeName.c_str())); } - break; + break; case BfIRCmd_StructSetBody: { CMD_PARAM(llvm::Type*, type); @@ -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: diff --git a/IDEHelper/Compiler/BfIRCodeGen.h b/IDEHelper/Compiler/BfIRCodeGen.h index f06ed529..a2374578 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.h +++ b/IDEHelper/Compiler/BfIRCodeGen.h @@ -82,7 +82,7 @@ public: Dictionary mResults; Dictionary mTypes; Dictionary mIntrinsicMap; - Dictionary mIntrinsicReverseMap; + Dictionary mIntrinsicReverseMap; Array mConfigConsts32; Array mConfigConsts64; diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index 9b78c802..90ca75c2 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -1566,7 +1566,7 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* } } else if (type->IsTypeInstance()) - { + { auto typeInstance = (BfTypeInstance*)type; auto typeDef = typeInstance->mTypeDef; @@ -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); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 55c9ceb0..c7659705 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1088,7 +1088,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) } } else if (!mIsReified) - { + { mBfIRBuilder->mIgnoreWrites = true; } else @@ -1097,10 +1097,9 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) // code as we walk the AST //mBfIRBuilder->mDbgVerifyCodeGen = true; if ( - (mModuleName == "-") - //|| (mModuleName == "Blurg") - //|| (mModuleName == "System_Int32") - //|| (mModuleName == "Hey_Dude_Bro_TestClass") + (mModuleName == "-") + //|| (mModuleName == "Tests_FuncRefs_Class") + //|| (mModuleName == "Tests_FuncRefs") ) mBfIRBuilder->mDbgVerifyCodeGen = true; @@ -3993,7 +3992,7 @@ void BfModule::CreateFakeCallerMethod(const String& funcName) SizedArray 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)); } @@ -13394,16 +13397,20 @@ 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()) - { - thisIdx = 1; - staticFuncArgs.push_back(mBfIRBuilder->GetArgument(0)); - memberFuncArgs.push_back(mBfIRBuilder->GetArgument(0)); + if (mCurMethodInstance->GetStructRetIdx() != -1) + { + 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); @@ -14364,22 +14378,25 @@ 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); - - //argIdx++; + if (resolvedTypeRef2 != NULL) + _SetupParam(paramName, resolvedTypeRef2); + 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,19 +15509,28 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp argIdx++; } } + + if (loweredTypeCode2 != BfTypeCode_None) + argIdx++; } + if (argIdx == methodInstance->GetStructRetIdx()) + argIdx++; + bool hadParams = false; bool hasDefault = false; int compositeVariableIdx = -1; int paramIdx = 0; for (paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++) - { + { // We already issues a type error for this param if we had one in declaration processing SetAndRestoreValue 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++; } } @@ -16754,10 +16803,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { int localIdx = 0; int argIdx = 0; - - if (methodInstance->HasStructRet()) - argIdx++; - + Array 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); @@ -19913,9 +20000,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool } int argIdx = 0; - PopulateType(methodInstance->mReturnType, BfPopulateType_Data); - if (methodInstance->HasStructRet()) - argIdx++; + PopulateType(methodInstance->mReturnType, BfPopulateType_Data); 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()) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 6985f0ce..195115b8 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -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); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index b1399d8e..6bc13cda 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -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 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()); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index a9ffc3db..8a2a8f61 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -7370,7 +7370,8 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all SetAndRestoreValue 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; } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index f72bcd46..888f5026 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -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(paramDef->mParamDeclaration->mNameNode); -// else if ((mClosureInstanceInfo != NULL) && (paramIdx < (int)mClosureInstanceInfo->mCaptureNodes.size())) -// return mClosureInstanceInfo->mCaptureNodes[paramIdx]; return NULL; } @@ -894,37 +912,39 @@ int BfMethodInstance::DbgGetVirtualMethodNum() } void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl& paramTypes, bool forceStatic) -{ +{ 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())) @@ -1032,8 +1059,15 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, }, checkType); } else - _AddType(checkType); - + _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() -{ - if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (mIsSplattable)) - return BfTypeCode_None; +bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode, BfTypeCode* outTypeCode2) +{ + 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) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index d9de045f..8c9890fc 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -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 diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 7e4000c3..98cc4105 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -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); diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index ac21315e..f4f45f25 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -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 _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) diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index 801defb3..6b24188d 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -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); diff --git a/IDEHelper/Tests/CLib/CLib.sln b/IDEHelper/Tests/CLib/CLib.sln new file mode 100644 index 00000000..1513df72 --- /dev/null +++ b/IDEHelper/Tests/CLib/CLib.sln @@ -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 diff --git a/IDEHelper/Tests/CLib/CLib.vcxproj b/IDEHelper/Tests/CLib/CLib.vcxproj new file mode 100644 index 00000000..cf8a0ba9 --- /dev/null +++ b/IDEHelper/Tests/CLib/CLib.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {D72A956A-5D9C-42F4-B35B-05F0B05B632C} + Win32Proj + CLib + 10.0.18362.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + false + MultiThreadedDebug + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/IDEHelper/Tests/CLib/CLib.vcxproj.filters b/IDEHelper/Tests/CLib/CLib.vcxproj.filters new file mode 100644 index 00000000..baced89e --- /dev/null +++ b/IDEHelper/Tests/CLib/CLib.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/IDEHelper/Tests/CLib/main.cpp b/IDEHelper/Tests/CLib/main.cpp new file mode 100644 index 00000000..63f35928 --- /dev/null +++ b/IDEHelper/Tests/CLib/main.cpp @@ -0,0 +1,371 @@ +#include + +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); +} \ No newline at end of file diff --git a/IDEHelper/Tests/src/Interop.bf b/IDEHelper/Tests/src/Interop.bf new file mode 100644 index 00000000..dbbf4cd1 --- /dev/null +++ b/IDEHelper/Tests/src/Interop.bf @@ -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); + } + } +} diff --git a/bin/test_build.bat b/bin/test_build.bat index 178ef7a3..eb373421 100644 --- a/bin/test_build.bat +++ b/bin/test_build.bat @@ -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 diff --git a/extern/llvm_build.sh b/extern/llvm_build.sh index 45db5a11..5d0be715 100755 --- a/extern/llvm_build.sh +++ b/extern/llvm_build.sh @@ -3,13 +3,14 @@ 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 .. -fi + 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 mkdir llvm_linux_8_0_0