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

Start of SIMD support

This commit is contained in:
Brian Fiete 2020-08-23 05:42:42 -07:00
parent 73e260c1d5
commit 64b62c09be
30 changed files with 5846 additions and 5096 deletions

View file

@ -309,6 +309,15 @@ namespace System
}
[AttributeUsage(.Struct)]
public struct UnderlyingArrayAttribute : Attribute
{
public this(Type t, int size, bool isVector)
{
}
}
[AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute
{

View file

@ -0,0 +1,14 @@
namespace System.Numerics
{
[UnderlyingArray(typeof(bool), 4, true)]
struct bool4
{
public bool x;
public bool y;
public bool z;
public bool w;
[Intrinsic("and")]
public static extern bool4 operator&(bool4 lhs, bool4 rhs);
}
}

View file

@ -0,0 +1,89 @@
namespace System.Numerics
{
[UnderlyingArray(typeof(float), 4, true)]
struct float4
{
public float x;
public float y;
public float z;
public float w;
public this()
{
this = default;
}
public this(float x, float y, float z, float w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public extern float4 wzyx { [Intrinsic("shuffle3210")] get; [Intrinsic("shuffle3210")] set; }
[Intrinsic("add")]
public static extern float4 operator+(float4 lhs, float4 rhs);
[Intrinsic("add"), Commutable]
public static extern float4 operator+(float4 lhs, float rhs);
[Intrinsic("add")]
public static extern float4 operator++(float4 lhs);
[Intrinsic("sub")]
public static extern float4 operator-(float4 lhs, float4 rhs);
[Intrinsic("sub"), Commutable]
public static extern float4 operator-(float4 lhs, float rhs);
[Intrinsic("sub")]
public static extern float4 operator--(float4 lhs);
[Intrinsic("mul")]
public static extern float4 operator*(float4 lhs, float4 rhs);
[Intrinsic("mul"), Commutable]
public static extern float4 operator*(float4 lhs, float rhs);
[Intrinsic("div")]
public static extern float4 operator/(float4 lhs, float4 rhs);
[Intrinsic("div")]
public static extern float4 operator/(float4 lhs, float rhs);
[Intrinsic("div")]
public static extern float4 operator/(float lhs, float4 rhs);
[Intrinsic("mod")]
public static extern float4 operator%(float4 lhs, float4 rhs);
[Intrinsic("mod")]
public static extern float4 operator%(float4 lhs, float rhs);
[Intrinsic("mod")]
public static extern float4 operator%(float lhs, float4 rhs);
[Intrinsic("eq")]
public static extern bool4 operator==(float4 lhs, float4 rhs);
[Intrinsic("eq"), Commutable]
public static extern bool4 operator==(float4 lhs, float rhs);
[Intrinsic("neq")]
public static extern bool4 operator!=(float4 lhs, float4 rhs);
[Intrinsic("neq"), Commutable]
public static extern bool4 operator!=(float4 lhs, float rhs);
[Intrinsic("lt")]
public static extern bool4 operator<(float4 lhs, float4 rhs);
[Intrinsic("lt")]
public static extern bool4 operator<(float4 lhs, float rhs);
[Intrinsic("lte")]
public static extern bool4 operator<=(float4 lhs, float4 rhs);
[Intrinsic("lte")]
public static extern bool4 operator<=(float4 lhs, float rhs);
[Intrinsic("gt")]
public static extern bool4 operator>(float4 lhs, float4 rhs);
[Intrinsic("gt")]
public static extern bool4 operator>(float4 lhs, float rhs);
[Intrinsic("gte")]
public static extern bool4 operator>=(float4 lhs, float4 rhs);
[Intrinsic("gte")]
public static extern bool4 operator>=(float4 lhs, float rhs);
}
}

View file

@ -3,7 +3,7 @@ namespace System
[AlwaysInclude]
struct SizedArray<T, CSize> where CSize : const int
{
T[CSize] mVal;
protected T[CSize] mVal;
public int Count
{

View file

@ -309,6 +309,15 @@ namespace System
}
[AttributeUsage(.Struct)]
public struct UnderlyingArrayAttribute : Attribute
{
public this(Type t, int size, bool isVector)
{
}
}
[AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute
{

View file

@ -323,9 +323,8 @@ namespace System
struct Int64 : int64
{
public const int64 MaxValue = 0x7FFFFFFFFFFFFFFFL;
//public const long MinValue = -0x8000000000000000L;
public const int64 MinValue = -0x7FFFFFFFFFFFFFFFL; //TODO: Should be one lower!
public const int64 MinValue = -0x8000000000000000L;
public override void ToString(String strBuffer)
{
// Dumb, make better.

View file

@ -214,7 +214,7 @@ namespace IDE
Add("Match Brace", new => gApp.Cmd_MatchBrace);
Add("Navigate Backwards", new => gApp.[Friend]NavigateBackwards);
Add("Navigate Forwards", new => gApp.[Friend]NavigateForwards);
Add("New Debug Session", new => gApp.[Friend]Cmd_NewDebugSession);
Add("New Debug Session", new => gApp.Cmd_NewDebugSession);
Add("New File", new => gApp.Cmd_NewFile);
Add("New Project", new => gApp.Cmd_NewProject);
Add("New Workspace", new => gApp.Cmd_NewWorkspace);
@ -257,8 +257,8 @@ namespace IDE
Add("Show Class View", new => gApp.ShowClassViewPanel);
Add("Show Current", new => gApp.Cmd_ShowCurrent);
Add("Show Diagnostics", new => gApp.ShowDiagnostics);
Add("Show Disassembly", new => gApp.[Friend]ShowDisassemblyAtStack);
Add("Show Errors", new => gApp.[Friend]ShowErrors);
Add("Show Disassembly", new => gApp.ShowDisassemblyAtStack);
Add("Show Errors", new => gApp.ShowErrors);
Add("Show Error Next", new => gApp.ShowErrorNext);
Add("Show File Externally", new => gApp.Cmd_ShowFileExternally);
Add("Show Find Results", new => gApp.ShowFindResults);
@ -272,7 +272,7 @@ namespace IDE
Add("Show Threads", new => gApp.ShowThreads);
Add("Show Watches", new => gApp.ShowWatches);
Add("Show Workspace Explorer", new => gApp.ShowWorkspacePanel);
Add("Start Debugging", new => gApp.[Friend]RunWithCompiling);
Add("Start Debugging", new => gApp.RunWithCompiling);
Add("Start Without Debugging", new => gApp.[Friend]RunWithoutDebugging);
Add("Start Without Compiling", new => gApp.[Friend]RunWithoutCompiling);
Add("Step Into", new => gApp.[Friend]StepInto);

View file

@ -91,9 +91,9 @@ namespace IDE.ui
label.AppendF(" ({0})", platformNames[0]);
}
let (category, propEntry) = mDialog.[Friend]AddPropertiesItem(root, label, "mFilter");
mDialog.[Friend]SetupDistinctBuildOptions(propEntry);
mDialog.[Friend]AddDistinctBuildOptions(category, -1, true);
let (category, propEntry) = mDialog.AddPropertiesItem(root, label, "mFilter");
mDialog.SetupDistinctBuildOptions(propEntry);
mDialog.AddDistinctBuildOptions(category, -1, true);
delete typeOptionsEntry;
}

View file

@ -56,6 +56,15 @@ BeType* BeContext::GetPrimitiveType(BeTypeCode typeCode)
case BeTypeCode_Double:
primType->mSize = primType->mAlign = 8;
break;
case BeTypeCode_M128:
primType->mSize = primType->mAlign = 16;
break;
case BeTypeCode_M256:
primType->mSize = primType->mAlign = 32;
break;
case BeTypeCode_M512:
primType->mSize = primType->mAlign = 64;
break;
}
mPrimitiveTypes[(int)typeCode] = primType;
return primType;
@ -152,6 +161,18 @@ BeSizedArrayType* BeContext::CreateSizedArrayType(BeType* type, int length)
return arrayType;
}
BeVectorType* BeContext::CreateVectorType(BeType* type, int length)
{
auto arrayType = mTypes.Alloc<BeVectorType>();
arrayType->mContext = this;
arrayType->mTypeCode = BeTypeCode_Vector;
arrayType->mElementType = type;
arrayType->mLength = length;
arrayType->mSize = type->mSize * length;
arrayType->mAlign = type->mAlign;
return arrayType;
}
BeFunctionType* BeContext::CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg)
{
auto funcType = mTypes.Alloc<BeFunctionType>();
@ -196,6 +217,14 @@ bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
if (lhsSizedArray->mLength != rhsSizedArray->mLength)
return false;
return AreTypesEqual(lhsSizedArray->mElementType, rhsSizedArray->mElementType);
}
case BeTypeCode_Vector:
{
auto lhsSizedArray = (BeVectorType*)lhs;
auto rhsSizedArray = (BeVectorType*)rhs;
if (lhsSizedArray->mLength != rhsSizedArray->mLength)
return false;
return AreTypesEqual(lhsSizedArray->mElementType, rhsSizedArray->mElementType);
}
}
return false;

View file

@ -20,10 +20,14 @@ enum BeTypeCode
BeTypeCode_Int64,
BeTypeCode_Float,
BeTypeCode_Double,
BeTypeCode_M128,
BeTypeCode_M256,
BeTypeCode_M512,
BeTypeCode_Struct,
BeTypeCode_Function,
BeTypeCode_Pointer,
BeTypeCode_SizedArray,
BeTypeCode_Vector,
BeTypeCode_CmpResult, // Psuedo
BeTypeCode_COUNT
@ -122,7 +126,22 @@ public:
return (mTypeCode == BeTypeCode_SizedArray);
}
bool IsVector()
{
return (mTypeCode == BeTypeCode_Vector) || (mTypeCode == BeTypeCode_M128) || (mTypeCode == BeTypeCode_M256) || (mTypeCode == BeTypeCode_M512);
}
bool IsExplicitVectorType()
{
return (mTypeCode == BeTypeCode_Vector);
}
bool IsComposite()
{
return (mTypeCode == BeTypeCode_Struct) || (mTypeCode == BeTypeCode_SizedArray) || (mTypeCode == BeTypeCode_Vector) || (mTypeCode == BeTypeCode_M128) || (mTypeCode == BeTypeCode_M256) || (mTypeCode == BeTypeCode_M512);
}
bool IsNonVectorComposite()
{
return (mTypeCode == BeTypeCode_Struct) || (mTypeCode == BeTypeCode_SizedArray);
}
@ -191,6 +210,21 @@ public:
}
};
class BeVectorType : public BeType
{
public:
BeContext* mContext;
BeType* mElementType;
int mLength;
virtual void HashContent(BeHashContext& hashCtx) override
{
hashCtx.Mixin(BeTypeCode_Vector);
hashCtx.Mixin(mLength);
mElementType->HashReference(hashCtx);
}
};
class BeFunctionTypeParam
{
public:
@ -239,6 +273,7 @@ public:
BePointerType* GetPointerTo(BeType* beType);
void SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed);
BeSizedArrayType* CreateSizedArrayType(BeType* type, int length);
BeVectorType* CreateVectorType(BeType* type, int length);
BeFunctionType* CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg);
bool AreTypesEqual(BeType* lhs, BeType* rhs);

View file

@ -1015,7 +1015,10 @@ void BeIRCodeGen::HandleNextCmd()
{
CMD_PARAM(int, typeId);
CMD_PARAM(BeType*, type);
GetTypeEntry(typeId).mBeType = type;
auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mBeType = type;
if (typeEntry.mInstBeType == NULL)
typeEntry.mInstBeType = type;
}
break;
case BfIRCmd_SetInstType:
@ -1100,6 +1103,13 @@ void BeIRCodeGen::HandleNextCmd()
SetResult(curId, mBeContext->CreateSizedArrayType(elementType, length));
}
break;
case BfIRCmd_GetVectorType:
{
CMD_PARAM(BeType*, elementType);
CMD_PARAM(int, length);
SetResult(curId, mBeContext->CreateVectorType(elementType, length));
}
break;
case BfIRCmd_CreateConstStruct:
{
CMD_PARAM(BeType*, type);
@ -2050,49 +2060,14 @@ void BeIRCodeGen::HandleNextCmd()
break;
case BfIRCmd_GetIntrinsic:
{
CMD_PARAM(String, intrinName);
CMD_PARAM(int, intrinId);
CMD_PARAM(BeType*, returnType);
CMD_PARAM(CmdParamVec<BeType*>, paramTypes);
auto intrin = mBeModule->mAlloc.Alloc<BeIntrinsic>();
intrin->mKind = (BfIRIntrinsic)intrinId;
switch (intrin->mKind)
{
case BfIRIntrinsic_Abs:
intrin->mReturnType = paramTypes[0];
break;
case BfIRIntrinsic_AtomicAdd:
case BfIRIntrinsic_AtomicAnd:
case BfIRIntrinsic_AtomicCmpXChg:
case BfIRIntrinsic_AtomicLoad:
case BfIRIntrinsic_AtomicMax:
case BfIRIntrinsic_AtomicMin:
case BfIRIntrinsic_AtomicNAnd:
case BfIRIntrinsic_AtomicOr:
case BfIRIntrinsic_AtomicSub:
case BfIRIntrinsic_AtomicUMax:
case BfIRIntrinsic_AtomicUMin:
case BfIRIntrinsic_AtomicXChg:
case BfIRIntrinsic_AtomicXor:
if (!paramTypes.IsEmpty())
{
BF_ASSERT(paramTypes[0]->IsPointer());
if (paramTypes[0]->IsPointer())
intrin->mReturnType = ((BePointerType*)paramTypes[0])->mElementType;
}
else
intrin->mReturnType = mBeContext->GetPrimitiveType(BeTypeCode_None);
break;
case BfIRIntrinsic_AtomicCmpStore:
case BfIRIntrinsic_AtomicCmpStore_Weak:
intrin->mReturnType = mBeContext->GetPrimitiveType(BeTypeCode_Boolean);
break;
case BfIRIntrinsic_Cast:
intrin->mReturnType = returnType;
break;
}
intrin->mReturnType = returnType;
SetResult(curId, intrin);
}
break;
@ -2585,7 +2560,10 @@ void BeIRCodeGen::HandleNextCmd()
{
CMD_PARAM(int, typeId);
CMD_PARAM(BeMDNode*, type);
GetTypeEntry(typeId).mDIType = (BeDbgType*)type;
auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mDIType = (BeDbgType*)type;
if (typeEntry.mInstDIType == NULL)
typeEntry.mInstDIType = (BeDbgType*)type;
}
break;
case BfIRCmd_DbgSetInstType:

File diff suppressed because it is too large Load diff

View file

@ -192,11 +192,13 @@ enum BeMCOperandKind
BeMCOperandKind_Immediate_i16,
BeMCOperandKind_Immediate_i32,
BeMCOperandKind_Immediate_i64,
BeMCOperandKind_Immediate_HomeSize,
BeMCOperandKind_Immediate_Null,
BeMCOperandKind_Immediate_f32,
BeMCOperandKind_Immediate_f64,
BeMCOperandKind_Immediate_f32_Packed128,
BeMCOperandKind_Immediate_f64_Packed128,
BeMCOperandKind_Immediate_int32x4,
BeMCOperandKind_ConstAgg,
BeMCOperandKind_Block,
BeMCOperandKind_Label,
@ -283,12 +285,12 @@ public:
bool IsImmediateInt() const
{
return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_i64));
return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_HomeSize));
}
bool IsImmediateFloat() const
{
return ((mKind >= BeMCOperandKind_Immediate_f32) && (mKind <= BeMCOperandKind_Immediate_f64_Packed128));
return ((mKind >= BeMCOperandKind_Immediate_f32) && (mKind <= BeMCOperandKind_Immediate_int32x4));
}
bool IsNativeReg() const
@ -925,10 +927,12 @@ enum BeMCInstForm
BeMCInstForm_FRM64_XMM32,
BeMCInstForm_FRM32_XMM64,
BeMCInstForm_FRM64_XMM64,
BeMCInstForm_FRM128_XMM128,
BeMCInstForm_XMM32_RM32,
BeMCInstForm_XMM64_RM32,
BeMCInstForm_XMM32_RM64,
BeMCInstForm_XMM64_RM64,
BeMCInstForm_XMM128_RM128,
BeMCInstForm_R32_F32,
BeMCInstForm_R64_F32,
BeMCInstForm_R32_F64,
@ -1209,6 +1213,9 @@ enum BeMCNativeTypeCode
BeMCNativeTypeCode_Int64,
BeMCNativeTypeCode_Float,
BeMCNativeTypeCode_Double,
BeMCNativeTypeCode_M128,
BeMCNativeTypeCode_M256,
BeMCNativeTypeCode_M512,
BeMCNativeTypeCode_COUNT
};
@ -1347,6 +1354,7 @@ public:
void Print();
BeMCOperand GetOperand(BeValue* value, bool allowMetaResult = false, bool allowFail = false); // Meta results are PHIs or CmpResults
BeMCOperand CreateNot(const BeMCOperand& operand);
BeMCOperand TryToVector(BeValue* value);
BeType* GetType(const BeMCOperand& operand);
bool AreTypesEquivalent(BeType* type0, BeType* type1);
void AddRelRefs(BeMCOperand& operand, int refCount);
@ -1413,10 +1421,12 @@ public:
bool IsVolatileReg(X64CPURegister reg);
bool IsXMMReg(X64CPURegister reg);
X64CPURegister ResizeRegister(X64CPURegister reg, int numBits);
X64CPURegister ResizeRegister(X64CPURegister reg, BeType* type);
X64CPURegister GetFullRegister(X64CPURegister reg);
bool IsAddress(BeMCOperand& operand);
bool IsAddressable(BeMCOperand& operand);
bool IsVRegExpr(BeMCOperand& operand);
void FixOperand(BeMCOperand& operand);
void FixOperand(BeMCOperand& operand, int depth = 0);
BeMCOperand GetFixedOperand(const BeMCOperand& operand);
uint8 GetREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit);
void EmitREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit);

View file

@ -507,6 +507,12 @@ BeType* BeGEPConstant::GetType()
BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray);
return arrayType->mContext->GetPointerTo(arrayType->mElementType);
}
else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector)
{
BeVectorType* arrayType = (BeVectorType*)ptrType->mElementType;
BF_ASSERT(arrayType->mTypeCode == BeTypeCode_Vector);
return arrayType->mContext->GetPointerTo(arrayType->mElementType);
}
/*else if (ptrType->mElementType->IsPointer())
{
return ptrType->mElementType;
@ -528,6 +534,12 @@ BeType* BeExtractValueConstant::GetType()
BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray);
return arrayType->mElementType;
}
else if (type->mTypeCode == BeTypeCode_Vector)
{
BeVectorType* arrayType = (BeVectorType*)type;
BF_ASSERT(arrayType->mTypeCode == BeTypeCode_Vector);
return arrayType->mElementType;
}
/*else if (ptrType->mElementType->IsPointer())
{
return ptrType->mElementType;
@ -655,6 +667,11 @@ BeType* BeExtractValueInst::GetType()
BeSizedArrayType* arrayType = (BeSizedArrayType*)aggType;
return arrayType->mElementType;
}
if (aggType->mTypeCode == BeTypeCode_Vector)
{
BeVectorType* arrayType = (BeVectorType*)aggType;
return arrayType->mElementType;
}
BF_ASSERT(aggType->mTypeCode == BeTypeCode_Struct);
BeStructType* structType = (BeStructType*)aggType;
return structType->mMembers[mIdx].mType;
@ -703,6 +720,11 @@ BeType* BeGEPInst::GetType()
BeSizedArrayType* arrayType = (BeSizedArrayType*)ptrType->mElementType;
return GetContext()->GetPointerTo(arrayType->mElementType);
}
else if (elementType->IsVector())
{
BeVectorType* arrayType = (BeVectorType*)ptrType->mElementType;
return GetContext()->GetPointerTo(arrayType->mElementType);
}
else
{
BF_FATAL("Bad type");
@ -1308,7 +1330,8 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
switch (constant->mType->mTypeCode)
{
case BeTypeCode_Struct:
case BeTypeCode_SizedArray:
case BeTypeCode_SizedArray:
case BeTypeCode_Vector:
for (int valIdx = 0; valIdx < (int)constant->mMemberValues.size(); valIdx++)
{
if (valIdx > 0)
@ -1412,7 +1435,8 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
return;
}
case BeTypeCode_Struct:
case BeTypeCode_SizedArray:
case BeTypeCode_SizedArray:
case BeTypeCode_Vector:
str += "zeroinitializer";
return;
case BeTypeCode_Function:
@ -3033,6 +3057,15 @@ void BeModule::ToString(StringImpl& str, BeType* type)
str += "]";
return;
}
case BeTypeCode_Vector:
{
auto arrayType = (BeSizedArrayType*)type;
ToString(str, arrayType->mElementType);
str += "<";
str += StrFormat("%d", arrayType->mLength);
str += ">";
return;
}
}
str += "<UnknownType>";
}

View file

@ -382,6 +382,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mCLinkAttributeTypeDef = NULL;
mImportAttributeTypeDef = NULL;
mCReprAttributeTypeDef = NULL;
mUnderlyingArrayAttributeTypeDef = NULL;
mAlignAttributeTypeDef = NULL;
mAllowDuplicatesAttributeTypeDef = NULL;
mNoDiscardAttributeTypeDef = NULL;
@ -2691,7 +2692,7 @@ bool BfCompiler::SlowGenerateSlotNums()
if (!failed)
{
bool success = VerifySlotNums();
if (!success)
if ((!success) && (!isHotCompile))
{
BF_DBG_FATAL("Failed!");
}
@ -2736,7 +2737,7 @@ void BfCompiler::GenerateSlotNums()
}
if (VerifySlotNums())
return;
return;
if (!QuickGenerateSlotNums())
SlowGenerateSlotNums();
@ -6256,6 +6257,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mCLinkAttributeTypeDef = _GetRequiredType("System.CLinkAttribute");
mImportAttributeTypeDef = _GetRequiredType("System.ImportAttribute");
mCReprAttributeTypeDef = _GetRequiredType("System.CReprAttribute");
mUnderlyingArrayAttributeTypeDef = _GetRequiredType("System.UnderlyingArrayAttribute");
mAlignAttributeTypeDef = _GetRequiredType("System.AlignAttribute");
mAllowDuplicatesAttributeTypeDef = _GetRequiredType("System.AllowDuplicatesAttribute");
mNoDiscardAttributeTypeDef = _GetRequiredType("System.NoDiscardAttribute");

View file

@ -385,6 +385,7 @@ public:
BfTypeDef* mCLinkAttributeTypeDef;
BfTypeDef* mImportAttributeTypeDef;
BfTypeDef* mCReprAttributeTypeDef;
BfTypeDef* mUnderlyingArrayAttributeTypeDef;
BfTypeDef* mAlignAttributeTypeDef;
BfTypeDef* mAllowDuplicatesAttributeTypeDef;
BfTypeDef* mNoDiscardAttributeTypeDef;

View file

@ -1007,6 +1007,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
typeInst->mTypeFailed = false;
typeInst->mTypeWarned = false;
typeInst->mIsSplattable = false;
typeInst->mHasUnderlyingArray = false;
typeInst->mHasPackingHoles = false;
typeInst->mWantsGCMarking = false;
delete typeInst->mTypeInfoEx;

View file

@ -4864,13 +4864,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
else
{
callInst = mModule->mBfIRBuilder->CreateCall(funcCallInst, irArgs);
if (hasResult)
if ((hasResult) && (!methodDef->mName.IsEmpty()) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->SetName(callInst, methodDef->mName);
}
if (expectCallingConvention != BfIRCallingConv_CDecl)
if ((expectCallingConvention != BfIRCallingConv_CDecl) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->SetCallCallingConv(callInst, expectCallingConvention);
if (methodDef->mNoReturn)
if ((methodDef->mNoReturn) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->Call_AddAttribute(callInst, -1, BfIRAttribute_NoReturn);
bool hadAttrs = false;
@ -4881,7 +4881,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
int paramCount = methodInstance->GetParamCount();
for ( ; argIdx < callIRArgCount ; )
{
{
if (methodInstance->mIsIntrinsic)
break;
if (argIdx == methodInstance->GetStructRetIdx())
{
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_StructRet);
@ -5087,7 +5090,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target)
{
auto moduleMethodInstance = GetSelectedMethod(methodMatcher->mTargetSrc, methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, *methodMatcher);
auto& moduleMethodInstance = methodMatcher->mBestMethodInstance;
if (!moduleMethodInstance)
moduleMethodInstance = GetSelectedMethod(methodMatcher->mTargetSrc, methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, *methodMatcher);
if (moduleMethodInstance.mMethodInstance == NULL)
return BfTypedValue();
if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner()))
@ -5095,7 +5100,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTyped
auto castedTarget = mModule->Cast(methodMatcher->mTargetSrc, target, moduleMethodInstance.mMethodInstance->GetOwner());
BF_ASSERT(castedTarget);
target = castedTarget;
}
}
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, false, methodMatcher->mArguments);
}
@ -17673,16 +17678,32 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
SizedArray<BfExpression*, 2> argSrcs;
argSrcs.push_back(unaryOpExpr);
auto result = CreateCall(&methodMatcher, BfTypedValue());
BfTypedValue postOpVal;
if (isPostOp)
postOpVal = mModule->LoadValue(args[0].mTypedValue);
auto result = CreateCall(&methodMatcher, BfTypedValue());
if ((result.mType != NULL) && (methodMatcher.mSelfType != NULL) && (result.mType->IsSelf()))
{
BF_ASSERT(mModule->IsInGeneric());
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
}
if (isPostOp)
result = args[0].mTypedValue;
if ((methodMatcher.mBestMethodInstance) && (methodMatcher.mBestMethodInstance.mMethodInstance->mIsIntrinsic) &&
((findOp == BfUnaryOp_Increment) || (findOp == BfUnaryOp_Decrement)))
{
if (args[0].mTypedValue.IsAddr())
mModule->mBfIRBuilder->CreateStore(result.mValue, args[0].mTypedValue.mValue);
else
{
mModule->AssertErrorState();
}
}
if (postOpVal)
result = postOpVal;
return result;
}
@ -18954,7 +18975,27 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
}
}
if (methodMatcher.mBestMethodDef != NULL)
bool hadMatch = methodMatcher.mBestMethodDef != NULL;
if ((methodMatcher.mBestMethodDef != NULL) && ((flags & BfBinOpFlag_IgnoreOperatorWithWrongResult) != 0))
{
auto matchedOp = ((BfOperatorDeclaration*)methodMatcher.mBestMethodDef->mMethodDeclaration)->mBinOp;
methodMatcher.mBestMethodInstance = GetSelectedMethod(methodMatcher.mTargetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
if ((methodMatcher.mBestMethodInstance.mMethodInstance->mReturnType != mExpectingType) &&
((matchedOp == binaryOp) || (matchedOp == oppositeBinaryOp)))
{
if (binaryOp == BfBinaryOp_Equality)
binaryOp = BfBinaryOp_StrictEquality;
if (binaryOp == BfBinaryOp_InEquality)
binaryOp = BfBinaryOp_StrictEquality;
hadMatch = false;
break;
}
}
if (hadMatch)
{
methodMatcher.FlushAmbiguityError();

View file

@ -293,7 +293,8 @@ enum BfBinOpFlags
{
BfBinOpFlag_None = 0,
BfBinOpFlag_NoClassify = 1,
BfBinOpFlag_ForceLeftType = 2
BfBinOpFlag_ForceLeftType = 2,
BfBinOpFlag_IgnoreOperatorWithWrongResult = 4,
};
class BfExprEvaluator : public BfStructuralVisitor

View file

@ -2167,7 +2167,14 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
BfIRType irType;
BfIRMDNode diType;
bool trackDIType = false;
BfTypeInstance* typeInstance = type->ToTypeInstance();
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
bool underlyingArrayIsVector = false;
if (typeInstance != NULL)
typeInstance->GetUnderlyingArray(underlyingArrayType, underlyingArraySize, underlyingArrayIsVector);
if (type->IsPointer())
{
BfPointerType* pointerType = (BfPointerType*)type;
@ -2281,6 +2288,19 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
irType = CreateStructType(name);
StructSetBody(irType, members, false);
}
else if (underlyingArraySize != -1)
{
if (underlyingArrayIsVector)
{
if (underlyingArrayType == mModule->GetPrimitiveType(BfTypeCode_Boolean))
underlyingArrayType = mModule->GetPrimitiveType(BfTypeCode_UInt8);
irType = GetVectorType(MapType(underlyingArrayType), underlyingArraySize);
}
else
irType = GetSizedArrayType(MapType(underlyingArrayType), underlyingArraySize);
if (wantDIData)
diType = DbgCreateArrayType((int64)type->mSize * 8, type->mAlign * 8, DbgGetType(underlyingArrayType), underlyingArraySize);
}
else if (type->IsSizedArray())
{
BfSizedArrayType* arrayType = (BfSizedArrayType*)type;
@ -2375,8 +2395,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
}
}
else if (type->IsTypeInstance())
{
BfTypeInstance* typeInstance = type->ToTypeInstance();
{
auto typeDef = typeInstance->mTypeDef;
BfIRMDNode diForwardDecl;
@ -2524,14 +2543,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
#ifdef BFIR_RENTRY_CHECK
ReEntryCheck reEntryCheck(&mDefReentrySet, type);
#endif
String typeName = GetDebugTypeName(typeInstance, false);
bool isGlobalContainer = typeDef->IsGlobalsContainer();
bool isDefiningModule = ((type->GetModule() == mModule) || (type->IsFunction()));
auto diForwardDecl = DbgGetTypeInst(typeInstance);
//BF_ASSERT(WantsDbgDefinition(type));
llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;
@ -2539,6 +2551,9 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
bool isPacked = false;
bool isUnion = false;
bool isCRepr = false;
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
bool underlyingArrayIsVector = false;
if (typeInstance->IsBoxed())
{
@ -2549,8 +2564,18 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
isCRepr = typeInstance->mIsCRepr;
isPacked = typeInstance->mIsPacked;
isUnion = typeInstance->mIsUnion;
typeInstance->GetUnderlyingArray(underlyingArrayType, underlyingArraySize, underlyingArrayIsVector);
if (underlyingArrayType != NULL)
return; // Done
}
String typeName = GetDebugTypeName(typeInstance, false);
bool isGlobalContainer = typeDef->IsGlobalsContainer();
bool isDefiningModule = ((type->GetModule() == mModule) || (type->IsFunction()));
auto diForwardDecl = DbgGetTypeInst(typeInstance);
BfSizedVector<BfFieldInstance*, 8> orderedFields;
if ((type->IsUnion()) && (!type->IsEnum()))
@ -3058,6 +3083,13 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine)
if (typeInstance == NULL)
return;
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
bool underlyingIsVector = false;
typeInstance->GetUnderlyingArray(underlyingArrayType, underlyingArraySize, underlyingIsVector);
if (underlyingArraySize > 0)
return;
auto typeDef = typeInstance->mTypeDef;
#ifdef BFIR_RENTRY_CHECK
@ -3531,6 +3563,13 @@ BfIRType BfIRBuilder::GetSizedArrayType(BfIRType elementType, int length)
}
}
BfIRType BfIRBuilder::GetVectorType(BfIRType elementType, int length)
{
BfIRType retType = WriteCmd(BfIRCmd_GetVectorType, elementType, length);
NEW_CMD_INSERTED_IRTYPE;
return retType;
}
BfIRValue BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values)
{
BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstStruct, type, values);
@ -4516,9 +4555,9 @@ void BfIRBuilder::AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comin
NEW_CMD_INSERTED;
}
BfIRFunction BfIRBuilder::GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes)
BfIRFunction BfIRBuilder::GetIntrinsic(String intrinName, int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes)
{
BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinId, returnType, paramTypes);
BfIRValue retVal = WriteCmd(BfIRCmd_GetIntrinsic, intrinName, intrinId, returnType, paramTypes);
NEW_CMD_INSERTED;
return retVal;
}

View file

@ -175,7 +175,8 @@ enum BfIRCmd : uint8
BfIRCmd_GetType,
BfIRCmd_GetPointerToFuncType,
BfIRCmd_GetPointerToType,
BfIRCmd_GetSizedArrayType,
BfIRCmd_GetSizedArrayType,
BfIRCmd_GetVectorType,
BfIRCmd_CreateConstStruct,
BfIRCmd_CreateConstStructZero,
@ -274,7 +275,7 @@ enum BfIRCmd : uint8
BfIRCmd_CreatePhi,
BfIRCmd_AddPhiIncoming,
BfIRCmd_GetIntrinsic,
BfIRCmd_GetIntrinsic,
BfIRCmd_CreateFunctionType,
BfIRCmd_CreateFunction,
BfIRCmd_EnsureFunctionPatchable,
@ -406,6 +407,8 @@ enum BfIRConfigConst : uint8
enum BfIRIntrinsic : uint8
{
BfIRIntrinsic_Abs,
BfIRIntrinsic_Add,
BfIRIntrinsic_And,
BfIRIntrinsic_AtomicAdd,
BfIRIntrinsic_AtomicAnd,
BfIRIntrinsic_AtomicCmpStore,
@ -425,21 +428,35 @@ enum BfIRIntrinsic : uint8
BfIRIntrinsic_AtomicXor,
BfIRIntrinsic_BSwap,
BfIRIntrinsic_Cast,
BfIRIntrinsic_Cos,
BfIRIntrinsic_Cos,
BfIRIntrinsic_Div,
BfIRIntrinsic_Eq,
BfIRIntrinsic_Floor,
BfIRIntrinsic_Free,
BfIRIntrinsic_Gt,
BfIRIntrinsic_GtE,
BfIRIntrinsic_Log,
BfIRIntrinsic_Log10,
BfIRIntrinsic_Log2,
BfIRIntrinsic_Lt,
BfIRIntrinsic_LtE,
BfIRIntrinsic_Malloc,
BfIRIntrinsic_MemCpy,
BfIRIntrinsic_MemMove,
BfIRIntrinsic_MemSet,
BfIRIntrinsic_Mod,
BfIRIntrinsic_Mul,
BfIRIntrinsic_Not,
BfIRIntrinsic_Neq,
BfIRIntrinsic_Or,
BfIRIntrinsic_Pow,
BfIRIntrinsic_PowI,
BfIRIntrinsic_Round,
BfIRIntrinsic_Shuffle,
BfIRIntrinsic_Sin,
BfIRIntrinsic_Sqrt,
BfIRIntrinsic_Sub,
BfIRIntrinsic_Xor,
BfIRIntrinsic_COUNT,
BfIRIntrinsic_Atomic_FIRST = BfIRIntrinsic_AtomicAdd,
@ -1094,6 +1111,7 @@ public:
BfIRType GetPointerTo(BfIRFunctionType funcType);
BfIRType GetPointerTo(BfIRType type);
BfIRType GetSizedArrayType(BfIRType elementType, int length);
BfIRType GetVectorType(BfIRType elementType, int length);
BfIRValue CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values);
BfIRValue CreateConstString(const StringImpl& string);
@ -1190,7 +1208,7 @@ public:
BfIRValue CreatePhi(BfIRType type, int incomingCount);
void AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comingFrom);
BfIRFunction GetIntrinsic(int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes);
BfIRFunction GetIntrinsic(String intrinName, int intrinId, BfIRType returnType, const BfSizedArray<BfIRType>& paramTypes);
BfIRFunctionType MapMethod(BfMethodInstance* methodInstance);
BfIRFunctionType CreateFunctionType(BfIRType resultType, const BfSizedArray<BfIRType>& paramTypes, bool isVarArg = false);
BfIRFunction CreateFunction(BfIRFunctionType funcType, BfIRLinkageType linkageType, const StringImpl& name);

View file

@ -134,6 +134,8 @@ struct BuiltinEntry
static const BuiltinEntry gIntrinEntries[] =
{
{"abs"},
{"add"},
{"and"},
{"atomic_add"},
{"atomic_and"},
{"atomic_cmpstore"},
@ -153,21 +155,35 @@ static const BuiltinEntry gIntrinEntries[] =
{"atomic_xor"},
{"bswap"},
{"cast"},
{"cos"},
{"cos"},
{"div"},
{"eq"},
{"floor"},
{"free"},
{"gt"},
{"gte"},
{"log"},
{"log10"},
{"log2"},
{"lt"},
{"lte"},
{"malloc"},
{"memcpy"},
{"memmove"},
{"memset"},
{"mod"},
{"mul"},
{"neq"},
{"not"},
{"or"},
{"pow"},
{"powi"},
{"round"},
{"shuffle"},
{"sin"},
{"sqrt"},
{"sub"},
{"xor"},
};
#define CMD_PARAM(ty, name) ty name; Read(name);
@ -1049,6 +1065,33 @@ void BfIRCodeGen::AddNop()
callInst->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoUnwind);
}
llvm::Value* BfIRCodeGen::TryToVector(llvm::Value* value)
{
auto valueType = value->getType();
if (llvm::isa<llvm::VectorType>(valueType))
return value;
if (auto ptrType = llvm::dyn_cast<llvm::PointerType>(valueType))
{
auto ptrElemType = ptrType->getElementType();
if (auto arrType = llvm::dyn_cast<llvm::ArrayType>(ptrElemType))
{
auto vecType = llvm::VectorType::get(arrType->getArrayElementType(), (uint)arrType->getArrayNumElements());
auto vecPtrType = vecType->getPointerTo();
auto ptrVal0 = mIRBuilder->CreateBitCast(value, vecPtrType);
return mIRBuilder->CreateAlignedLoad(ptrVal0, 1);
}
if (auto vecType = llvm::dyn_cast<llvm::VectorType>(ptrElemType))
{
return mIRBuilder->CreateAlignedLoad(value, 1);
}
}
return NULL;
}
bool BfIRCodeGen::TryMemCpy(llvm::Value* ptr, llvm::Value* val)
{
auto valType = val->getType();
@ -1110,6 +1153,31 @@ bool BfIRCodeGen::TryMemCpy(llvm::Value* ptr, llvm::Value* val)
return true;
}
bool BfIRCodeGen::TryVectorCpy(llvm::Value* ptr, llvm::Value* val)
{
if (ptr->getType()->getPointerElementType() == val->getType())
return false;
auto valType = val->getType();
auto vecType = llvm::dyn_cast<llvm::VectorType>(valType);
if (vecType == NULL)
return false;
for (int i = 0; i < (int)vecType->getVectorNumElements(); i++)
{
auto extract = mIRBuilder->CreateExtractElement(val, i);
llvm::Value* gepArgs[] = {
llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mLLVMContext), 0),
llvm::ConstantInt::get(llvm::Type::getInt32Ty(*mLLVMContext), i) };
auto gep = mIRBuilder->CreateInBoundsGEP(ptr, llvm::makeArrayRef(gepArgs));
mIRBuilder->CreateStore(extract, gep);
}
return true;
}
void BfIRCodeGen::CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile)
{
auto sizeConst = llvm::dyn_cast<llvm::ConstantInt>(size);
@ -1273,7 +1341,10 @@ void BfIRCodeGen::HandleNextCmd()
{
CMD_PARAM(int, typeId);
CMD_PARAM(llvm::Type*, type);
GetTypeEntry(typeId).mLLVMType = type;
auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mLLVMType = type;
if (typeEntry.mInstLLVMType == NULL)
typeEntry.mInstLLVMType = type;
}
break;
case BfIRCmd_SetInstType:
@ -1359,6 +1430,13 @@ void BfIRCodeGen::HandleNextCmd()
SetResult(curId, llvm::ArrayType::get(elementType, length));
}
break;
case BfIRCmd_GetVectorType:
{
CMD_PARAM(llvm::Type*, elementType);
CMD_PARAM(int, length);
SetResult(curId, llvm::VectorType::get(elementType, length));
}
break;
case BfIRCmd_CreateConstStruct:
{
CMD_PARAM(llvm::Type*, type);
@ -1854,8 +1932,9 @@ void BfIRCodeGen::HandleNextCmd()
CMD_PARAM(llvm::Value*, val);
CMD_PARAM(llvm::Value*, ptr);
CMD_PARAM(bool, isVolatile);
if (!TryMemCpy(ptr, val))
if ((!TryMemCpy(ptr, val)) &&
(!TryVectorCpy(ptr, val)))
SetResult(curId, mIRBuilder->CreateStore(val, ptr, isVolatile));
}
break;
@ -1865,7 +1944,8 @@ void BfIRCodeGen::HandleNextCmd()
CMD_PARAM(llvm::Value*, ptr);
CMD_PARAM(int, alignment);
CMD_PARAM(bool, isVolatile);
if (!TryMemCpy(ptr, val))
if ((!TryMemCpy(ptr, val)) &&
(!TryVectorCpy(ptr, val)))
SetResult(curId, mIRBuilder->CreateAlignedStore(val, ptr, alignment, isVolatile));
}
break;
@ -2116,29 +2196,11 @@ void BfIRCodeGen::HandleNextCmd()
break;
case BfIRCmd_GetIntrinsic:
{
CMD_PARAM(String, intrinName);
CMD_PARAM(int, intrinId);
CMD_PARAM(llvm::Type*, returnType);
CMD_PARAM(CmdParamVec<llvm::Type*>, paramTypes);
bool isFakeIntrinsic = false;
if (((intrinId >= BfIRIntrinsic_Atomic_FIRST) && (intrinId <= BfIRIntrinsic_Atomic_LAST)) ||
(intrinId == BfIRIntrinsic_Cast))
{
isFakeIntrinsic = true;
}
if (isFakeIntrinsic)
{
auto intrinsicData = mAlloc.Alloc<BfIRIntrinsicData>();
intrinsicData->mIntrinsic = (BfIRIntrinsic)intrinId;
intrinsicData->mReturnType = returnType;
BfIRCodeGenEntry entry;
entry.mKind = BfIRCodeGenEntryKind_IntrinsicData;
entry.mIntrinsicData = intrinsicData;
mResults.TryAdd(curId, entry);
break;
}
llvm::Function* func = NULL;
struct _Intrinsics
@ -2152,43 +2214,74 @@ void BfIRCodeGen::HandleNextCmd()
static _Intrinsics intrinsics[] =
{
{ llvm::Intrinsic::fabs, 0, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicAdd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicAnd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpStore,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpStore_Weak,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpXChg,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicFence,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicLoad,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicMax,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicMin,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicNAnd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicOr,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicStore,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicSub,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicUMax,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicUMin,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXChg,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXor,
{ (llvm::Intrinsic::ID)-2, -1}, // add,
{ (llvm::Intrinsic::ID)-2, -1}, // and,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicAdd,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicAnd,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpStore,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpStore_Weak,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpXChg,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicFence,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicLoad,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicMax,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicMin,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicNAnd,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicOr,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicStore,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicSub,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicUMax,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicUMin,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicXChg,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicXor,
{ llvm::Intrinsic::bswap, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // cast,
{ llvm::Intrinsic::cos, 0, -1},
{ (llvm::Intrinsic::ID)-2, -1}, // cast,
{ llvm::Intrinsic::cos, 0, -1},
{ (llvm::Intrinsic::ID)-2, -1}, // div
{ (llvm::Intrinsic::ID)-2, -1}, // eq
{ llvm::Intrinsic::floor, 0, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // free
{ (llvm::Intrinsic::ID)-2, -1}, // free
{ (llvm::Intrinsic::ID)-2, -1}, // gt
{ (llvm::Intrinsic::ID)-2, -1}, // gte
{ llvm::Intrinsic::log, 0, -1},
{ llvm::Intrinsic::log10, 0, -1},
{ llvm::Intrinsic::log2, 0, -1},
{ (llvm::Intrinsic::ID)-1}, // memset
{ (llvm::Intrinsic::ID)-2, -1}, // lt
{ (llvm::Intrinsic::ID)-2, -1}, // lte
{ (llvm::Intrinsic::ID)-2}, // memset
{ llvm::Intrinsic::memcpy, 0, 1, 2},
{ llvm::Intrinsic::memmove, 0, 2},
{ llvm::Intrinsic::memset, 0, 2},
{ (llvm::Intrinsic::ID)-2, -1}, // mod
{ (llvm::Intrinsic::ID)-2, -1}, // mul
{ (llvm::Intrinsic::ID)-2, -1}, // neq
{ (llvm::Intrinsic::ID)-2, -1}, // not
{ (llvm::Intrinsic::ID)-2, -1}, // or
{ llvm::Intrinsic::pow, 0, -1},
{ llvm::Intrinsic::powi, 0, -1},
{ llvm::Intrinsic::round, 0, -1},
{ llvm::Intrinsic::sin, 0, -1},
{ llvm::Intrinsic::sqrt, 0, -1},
{ (llvm::Intrinsic::ID)-2, -1}, // shuffle
{ llvm::Intrinsic::sin, 0, -1},
{ llvm::Intrinsic::sqrt, 0, -1},
{ (llvm::Intrinsic::ID)-2, -1}, // sub,
{ (llvm::Intrinsic::ID)-2, -1}, // xor
};
BF_STATIC_ASSERT(BF_ARRAY_COUNT(intrinsics) == BfIRIntrinsic_COUNT);
bool isFakeIntrinsic = (int)intrinsics[intrinId].mID == -2;
if (isFakeIntrinsic)
{
auto intrinsicData = mAlloc.Alloc<BfIRIntrinsicData>();
intrinsicData->mName = intrinName;
intrinsicData->mIntrinsic = (BfIRIntrinsic)intrinId;
intrinsicData->mReturnType = returnType;
BfIRCodeGenEntry entry;
entry.mKind = BfIRCodeGenEntryKind_IntrinsicData;
entry.mIntrinsicData = intrinsicData;
mResults.TryAdd(curId, entry);
break;
}
CmdParamVec<llvm::Type*> useParams;
if (intrinsics[intrinId].mArg0 != -1)
{
@ -2319,6 +2412,236 @@ void BfIRCodeGen::HandleNextCmd()
switch (intrinsicData->mIntrinsic)
{
case BfIRIntrinsic_Add:
case BfIRIntrinsic_And:
case BfIRIntrinsic_Div:
case BfIRIntrinsic_Eq:
case BfIRIntrinsic_Gt:
case BfIRIntrinsic_GtE:
case BfIRIntrinsic_Lt:
case BfIRIntrinsic_LtE:
case BfIRIntrinsic_Mod:
case BfIRIntrinsic_Mul:
case BfIRIntrinsic_Neq:
case BfIRIntrinsic_Or:
case BfIRIntrinsic_Sub:
case BfIRIntrinsic_Xor:
{
auto val0 = TryToVector(args[0]);
if (val0 != NULL)
{
auto vecType = val0->getType();
auto elemType = vecType->getVectorElementType();
bool isFP = elemType->isFloatTy();
llvm::Value* val1;
if (args.size() < 2)
{
llvm::Value* val;
if (isFP)
val = llvm::ConstantFP::get(elemType, 1);
else
val = llvm::ConstantInt::get(elemType, 1);
val1 = mIRBuilder->CreateInsertElement(llvm::UndefValue::get(vecType), val, (uint64)0);
val1 = mIRBuilder->CreateInsertElement(val1, val, (uint64)1);
val1 = mIRBuilder->CreateInsertElement(val1, val, (uint64)2);
val1 = mIRBuilder->CreateInsertElement(val1, val, (uint64)3);
}
else if (args[1]->getType()->isPointerTy())
{
auto ptrVal1 = mIRBuilder->CreateBitCast(args[1], vecType->getPointerTo());
val1 = mIRBuilder->CreateAlignedLoad(ptrVal1, 1);
}
else
{
val1 = mIRBuilder->CreateInsertElement(llvm::UndefValue::get(vecType), args[1], (uint64)0);
val1 = mIRBuilder->CreateInsertElement(val1, args[1], (uint64)1);
val1 = mIRBuilder->CreateInsertElement(val1, args[1], (uint64)2);
val1 = mIRBuilder->CreateInsertElement(val1, args[1], (uint64)3);
}
if (isFP)
{
llvm::Value* result = NULL;
switch (intrinsicData->mIntrinsic)
{
case BfIRIntrinsic_Add:
result = mIRBuilder->CreateFAdd(val0, val1);
break;
case BfIRIntrinsic_Div:
result = mIRBuilder->CreateFDiv(val0, val1);
break;
case BfIRIntrinsic_Eq:
result = mIRBuilder->CreateFCmpOEQ(val0, val1);
break;
case BfIRIntrinsic_Gt:
result = mIRBuilder->CreateFCmpOGT(val0, val1);
break;
case BfIRIntrinsic_GtE:
result = mIRBuilder->CreateFCmpOGE(val0, val1);
break;
case BfIRIntrinsic_Lt:
result = mIRBuilder->CreateFCmpOLT(val0, val1);
break;
case BfIRIntrinsic_LtE:
result = mIRBuilder->CreateFCmpOLE(val0, val1);
break;
case BfIRIntrinsic_Mod:
result = mIRBuilder->CreateFRem(val0, val1);
break;
case BfIRIntrinsic_Mul:
result = mIRBuilder->CreateFMul(val0, val1);
break;
case BfIRIntrinsic_Neq:
result = mIRBuilder->CreateFCmpONE(val0, val1);
break;
case BfIRIntrinsic_Sub:
result = mIRBuilder->CreateFSub(val0, val1);
break;
default:
FatalError("Intrinsic argument error");
}
if (result != NULL)
{
if (auto vecType = llvm::dyn_cast<llvm::VectorType>(result->getType()))
{
if (auto intType = llvm::dyn_cast<llvm::IntegerType>(vecType->getVectorElementType()))
{
if (intType->getBitWidth() == 1)
{
auto toType = llvm::VectorType::get(llvm::IntegerType::get(*mLLVMContext, 8), vecType->getVectorNumElements());
result = mIRBuilder->CreateZExt(result, toType);
}
}
}
SetResult(curId, result);
}
}
else
{
llvm::Value* result = NULL;
switch (intrinsicData->mIntrinsic)
{
case BfIRIntrinsic_And:
result = mIRBuilder->CreateAnd(val0, val1);
break;
case BfIRIntrinsic_Add:
result = mIRBuilder->CreateAdd(val0, val1);
break;
case BfIRIntrinsic_Div:
result = mIRBuilder->CreateSDiv(val0, val1);
break;
case BfIRIntrinsic_Eq:
result = mIRBuilder->CreateICmpEQ(val0, val1);
break;
case BfIRIntrinsic_Gt:
result = mIRBuilder->CreateICmpSGT(val0, val1);
break;
case BfIRIntrinsic_GtE:
result = mIRBuilder->CreateICmpSGE(val0, val1);
break;
case BfIRIntrinsic_Lt:
result = mIRBuilder->CreateICmpSLT(val0, val1);
break;
case BfIRIntrinsic_LtE:
result = mIRBuilder->CreateICmpSLE(val0, val1);
break;
case BfIRIntrinsic_Mod:
result = mIRBuilder->CreateSRem(val0, val1);
break;
case BfIRIntrinsic_Mul:
result = mIRBuilder->CreateMul(val0, val1);
break;
case BfIRIntrinsic_Neq:
result = mIRBuilder->CreateICmpNE(val0, val1);
break;
case BfIRIntrinsic_Or:
result = mIRBuilder->CreateOr(val0, val1);
break;
case BfIRIntrinsic_Sub:
result = mIRBuilder->CreateSub(val0, val1);
break;
case BfIRIntrinsic_Xor:
result = mIRBuilder->CreateXor(val0, val1);
break;
default:
FatalError("Intrinsic argument error");
}
if (result != NULL)
{
if (auto vecType = llvm::dyn_cast<llvm::VectorType>(result->getType()))
{
if (auto intType = llvm::dyn_cast<llvm::IntegerType>(vecType->getVectorElementType()))
{
if (intType->getBitWidth() == 1)
{
auto toType = llvm::VectorType::get(llvm::IntegerType::get(*mLLVMContext, 8), vecType->getVectorNumElements());
result = mIRBuilder->CreateZExt(result, toType);
}
}
}
SetResult(curId, result);
}
}
}
else if (auto ptrType = llvm::dyn_cast<llvm::PointerType>(args[1]->getType()))
{
auto ptrElemType = ptrType->getElementType();
if (auto arrType = llvm::dyn_cast<llvm::ArrayType>(ptrElemType))
{
auto vecType = llvm::VectorType::get(arrType->getArrayElementType(), (uint)arrType->getArrayNumElements());
auto vecPtrType = vecType->getPointerTo();
llvm::Value* val0;
val0 = mIRBuilder->CreateInsertElement(llvm::UndefValue::get(vecType), args[0], (uint64)0);
val0 = mIRBuilder->CreateInsertElement(val0, args[0], (uint64)1);
val0 = mIRBuilder->CreateInsertElement(val0, args[0], (uint64)2);
val0 = mIRBuilder->CreateInsertElement(val0, args[0], (uint64)3);
auto ptrVal1 = mIRBuilder->CreateBitCast(args[1], vecPtrType);
auto val1 = mIRBuilder->CreateAlignedLoad(ptrVal1, 1);
switch (intrinsicData->mIntrinsic)
{
case BfIRIntrinsic_Div:
SetResult(curId, mIRBuilder->CreateFDiv(val0, val1));
break;
case BfIRIntrinsic_Mod:
SetResult(curId, mIRBuilder->CreateFRem(val0, val1));
break;
default:
FatalError("Intrinsic argument error");
}
}
}
else
{
FatalError("Intrinsic argument error");
}
}
break;
case BfIRIntrinsic_Shuffle:
{
llvm::SmallVector<uint, 8> intMask;
for (int i = 7; i < (int)intrinsicData->mName.length(); i++)
intMask.push_back((uint)(intrinsicData->mName[i] - '0'));
auto val0 = TryToVector(args[0]);
if (val0 != NULL)
{
SetResult(curId, mIRBuilder->CreateShuffleVector(val0, val0, intMask));
}
else
{
FatalError("Intrinsic argument error");
}
}
break;
case BfIRIntrinsic_AtomicCmpStore:
case BfIRIntrinsic_AtomicCmpStore_Weak:
case BfIRIntrinsic_AtomicCmpXChg:
@ -2326,7 +2649,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[3]);
if (memoryKindConst == NULL)
{
Fail("Non-constant success ordering on Atomic_CmpXChg");
FatalError("Non-constant success ordering on Atomic_CmpXChg");
break;
}
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2365,7 +2688,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[4]);
if (memoryKindConst == NULL)
{
Fail("Non-constant fail ordering on Atomic_CmpXChg");
FatalError("Non-constant fail ordering on Atomic_CmpXChg");
break;
}
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2381,7 +2704,7 @@ void BfIRCodeGen::HandleNextCmd()
failOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
break;
default:
Fail("Invalid fail ordering on Atomic_CmpXChg");
FatalError("Invalid fail ordering on Atomic_CmpXChg");
break;
}
}
@ -2427,7 +2750,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[0]);
if (memoryKindConst == NULL)
{
Fail("Non-constant success ordering on AtomicFence");
FatalError("Non-constant success ordering on AtomicFence");
break;
}
@ -2460,7 +2783,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]);
if (memoryKindConst == NULL)
{
Fail("Non-constant success ordering on AtomicLoad");
FatalError("Non-constant success ordering on AtomicLoad");
break;
}
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2490,7 +2813,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]);
if (memoryKindConst == NULL)
{
Fail("Non-constant success ordering on AtomicLoad");
FatalError("Non-constant success ordering on AtomicLoad");
break;
}
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2569,7 +2892,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[2]);
if (memoryKindConst == NULL)
{
Fail("Non-constant ordering on atomic operation");
FatalError("Non-constant ordering on atomic operation");
break;
}
@ -2676,7 +2999,7 @@ void BfIRCodeGen::HandleNextCmd()
}
break;
default:
Fail("Unhandled intrinsic");
FatalError("Unhandled intrinsic");
}
break;
}
@ -3115,7 +3438,10 @@ void BfIRCodeGen::HandleNextCmd()
{
CMD_PARAM(int, typeId);
CMD_PARAM(llvm::MDNode*, type);
GetTypeEntry(typeId).mDIType = (llvm::DIType*)type;
auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mDIType = (llvm::DIType*)type;
if (typeEntry.mInstDIType == NULL)
typeEntry.mInstDIType = (llvm::DIType*)type;
}
break;
case BfIRCmd_DbgSetInstType:
@ -4537,17 +4863,16 @@ bool BfIRCodeGen::WriteIR(const StringImpl& outFileName, StringImpl& error)
}
int BfIRCodeGen::GetIntrinsicId(const StringImpl& name)
{
// llvm::Intrinsic::ID intrin = llvm::Intrinsic::getIntrinsicForGCCBuiltin("x86", name.c_str());
// if (intrin != llvm::Intrinsic::not_intrinsic)
// return (int)intrin;
{
auto itr = std::lower_bound(std::begin(gIntrinEntries), std::end(gIntrinEntries), name);
if (itr != std::end(gIntrinEntries) && strcmp(itr->mName, name.c_str()) == 0)
{
int id = (int)(itr - gIntrinEntries);
return id;
}
}
if (name.StartsWith("shuffle"))
return BfIRIntrinsic_Shuffle;
return -1;
}

View file

@ -19,6 +19,7 @@ enum BfIRCodeGenEntryKind
class BfIRIntrinsicData
{
public:
String mName;
BfIRIntrinsic mIntrinsic;
llvm::Type* mReturnType;
};
@ -98,7 +99,9 @@ public:
void SetResult(int id, llvm::MDNode* value);
void CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile = false);
void AddNop();
llvm::Value* TryToVector(llvm::Value* value);
bool TryMemCpy(llvm::Value* ptr, llvm::Value* val);
bool TryVectorCpy(llvm::Value* ptr, llvm::Value* val);
public:
BfIRCodeGen();
@ -147,7 +150,7 @@ public:
llvm::BasicBlock* GetLLVMBlock(int streamId);
llvm::MDNode* GetLLVMMetadata(int streamId);
llvm::Type* GetLLVMTypeById(int id);
llvm::Type* GetLLVMTypeById(int id);
///

View file

@ -1229,12 +1229,25 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
}
else
{
auto _HandleMethod = [&](BfMethodInstance* methodInstance)
{
if ((methodInstance != NULL) && (methodInstance->mDeclModule != NULL))
methodInstance->mDeclModule = this;
};
for (auto& methodGroup : typeInst->mMethodInstanceGroups)
{
if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference))
{
oldOnDemandCount++;
}
_HandleMethod(methodGroup.mDefault);
if (methodGroup.mMethodSpecializationMap != NULL)
for (auto& kv : *methodGroup.mMethodSpecializationMap)
_HandleMethod(kv.mValue);
}
}
if (typeInst->IsDeleting())
typeIdx--;
@ -4068,8 +4081,14 @@ void BfModule::EmitEquals(BfTypedValue leftValue, BfTypedValue rightValue, BfIRB
{
BfExprEvaluator exprEvaluator(this);
exprEvaluator.mExpectingType = mCurMethodInstance->mReturnType;
exprEvaluator.PerformBinaryOperation((BfAstNode*)NULL, (BfAstNode*)NULL, strictEquals ? BfBinaryOp_StrictEquality : BfBinaryOp_Equality, NULL, BfBinOpFlag_None, leftValue, rightValue);
auto typeInst = rightValue.mType->ToTypeInstance();
exprEvaluator.PerformBinaryOperation((BfAstNode*)NULL, (BfAstNode*)NULL, strictEquals ? BfBinaryOp_StrictEquality : BfBinaryOp_Equality, NULL, BfBinOpFlag_IgnoreOperatorWithWrongResult, leftValue, rightValue);
BfTypedValue result = exprEvaluator.GetResult();
if (result.mType != GetPrimitiveType(BfTypeCode_Boolean))
{
// Fail?
}
if ((result) && (!result.mType->IsVar()))
{
auto nextBB = mBfIRBuilder->CreateBlock("next");
@ -6520,9 +6539,8 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor
auto methodOwner = methodInstance->GetOwner();
auto methodDef = methodInstance->mMethodDef;
auto methodDeclaration = methodDef->GetMethodDeclaration();
bool hasExternSpecifier = (methodDeclaration != NULL) && (methodDeclaration->mExternSpecifier != NULL);
if (!hasExternSpecifier)
if (!methodDef->mIsExtern)
return BfIRFunction();
if (methodInstance->GetCustomAttributes() == NULL)
@ -6542,33 +6560,44 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor
{
int stringId = constant->mInt32;
auto entry = mContext->mStringObjectIdMap[stringId];
int intrinId = BfIRCodeGen::GetIntrinsicId(entry.mString);
if (intrinId != -1)
String intrinName = entry.mString;
// if (intrinName.StartsWith(":"))
// {
// SizedArray<BfIRType, 2> paramTypes;
// for (auto& param : methodInstance->mParams)
// paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
// return mBfIRBuilder->GetIntrinsic(intrinName.Substring(1), mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
// }
// else
{
if (intrinId == BfIRIntrinsic_Malloc)
int intrinId = BfIRCodeGen::GetIntrinsicId(intrinName);
if (intrinId != -1)
{
return GetBuiltInFunc(BfBuiltInFuncType_Malloc);
}
else if (intrinId == BfIRIntrinsic_Free)
{
return GetBuiltInFunc(BfBuiltInFuncType_Free);
}
if (intrinId == BfIRIntrinsic_Malloc)
{
return GetBuiltInFunc(BfBuiltInFuncType_Malloc);
}
else if (intrinId == BfIRIntrinsic_Free)
{
return GetBuiltInFunc(BfBuiltInFuncType_Free);
}
SizedArray<BfIRType, 2> paramTypes;
for (auto& param : methodInstance->mParams)
paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
return mBfIRBuilder->GetIntrinsic(intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
SizedArray<BfIRType, 2> paramTypes;
for (auto& param : methodInstance->mParams)
paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
return mBfIRBuilder->GetIntrinsic(intrinName, intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
}
else if (reportFailure)
error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str());
}
else if (reportFailure)
error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str());
}
else if (reportFailure)
error = "Intrinsic name must be a constant string";
if (reportFailure)
{
BfAstNode* ref = methodDeclaration->mAttributes;
Fail(error, ref);
{
Fail(error, customAttribute.mRef);
}
}
}
@ -9415,20 +9444,9 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
return func;
}
if (auto methodDeclaration = methodDef->GetMethodDeclaration())
{
if (methodDeclaration->mExternSpecifier != NULL)
{
auto intrinsic = GetIntrinsic(methodInstance);
if (intrinsic)
return intrinsic;
// If we have multiple entries with the same name, they could have different arguments and will generate other errors...
/*auto func = mBfIRBuilder->GetFunction(methodName);
if (func)
return func;*/
}
}
auto intrinsic = GetIntrinsic(methodInstance);
if (intrinsic)
return intrinsic;
if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
{
@ -10550,7 +10568,7 @@ void BfModule::FinishAttributeState(BfAttributeState* attributeState)
Warn(0, "Unused attributes", attributeState->mSrc);
}
void BfModule::ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered)
void BfModule::ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered, BfType*& underlyingArrayType, int& underlyingArraySize)
{
if (mCurTypeInstance->mCustomAttributes != NULL)
{
@ -10593,6 +10611,19 @@ void BfModule::ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bo
}
}
}
else if (typeName == "System.UnderlyingArrayAttribute")
{
if (customAttribute.mCtorArgs.size() >= 2)
{
auto typeConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
auto sizeConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[1]);
if ((typeConstant != NULL) && (sizeConstant != NULL) && (typeConstant->mConstType == BfConstType_TypeOf))
{
underlyingArrayType = (BfType*)(intptr)typeConstant->mInt64;
underlyingArraySize = sizeConstant->mInt32;
}
}
}
}
}
}
@ -13569,19 +13600,23 @@ void BfModule::CreateReturn(BfIRValue val)
BF_ASSERT(val);
mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
mBfIRBuilder->CreateRetVoid();
return;
}
else
if (mCurMethodInstance->mReturnType->IsValuelessType())
{
if (mCurMethodInstance->mReturnType->IsValuelessType())
{
mBfIRBuilder->CreateRetVoid();
}
else if (mCurMethodInstance->mReturnType->IsStruct())
{
BfTypeCode loweredReturnType = BfTypeCode_None;
BfTypeCode loweredReturnType2 = BfTypeCode_None;
mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
mBfIRBuilder->CreateRetVoid();
return;
}
if (mCurMethodInstance->mReturnType->IsStruct())
{
BfTypeCode loweredReturnType = BfTypeCode_None;
BfTypeCode loweredReturnType2 = BfTypeCode_None;
mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
if (loweredReturnType != BfTypeCode_None)
{
auto retVal = CreateAlloca(mCurMethodInstance->mReturnType);
mBfIRBuilder->CreateStore(val, retVal);
@ -13590,13 +13625,12 @@ void BfModule::CreateReturn(BfIRValue val)
auto ptrReturnValue = mBfIRBuilder->CreateBitCast(retVal, irRetType);
auto loadedReturnValue = mBfIRBuilder->CreateLoad(ptrReturnValue);
mBfIRBuilder->CreateRet(loadedReturnValue);
}
else
{
BF_ASSERT(val);
mBfIRBuilder->CreateRet(val);
}
return;
}
}
BF_ASSERT(val);
mBfIRBuilder->CreateRet(val);
}
void BfModule::EmitReturn(BfIRValue val)

View file

@ -1467,7 +1467,7 @@ public:
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
void FinishAttributeState(BfAttributeState* attributeState);
void ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered);
void ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered, BfType*& underlyingArrayType, int& underlyingArraySize);
void ProcessCustomAttributeData();
bool TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue, StringImpl& str);
BfVariant TypedValueToVariant(BfAstNode* refNode, const BfTypedValue& value, bool allowUndef = false);

View file

@ -1908,7 +1908,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
CheckCircularDataError();
bool underlyingTypeDeferred = false;
BfType* underlyingType = NULL;
BfType* underlyingType = NULL;
if (typeInstance->mBaseType != NULL)
{
if (typeInstance->IsTypedPrimitive())
@ -2390,7 +2390,6 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
BF_ASSERT(typeInstance->mBaseType == baseTypeInst);
}
if (auto genericTypeInst = typeInstance->ToGenericTypeInstance())
{
@ -2595,7 +2594,14 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
bool isUnion = false;
bool isCRepr = false;
bool isOrdered = false;
ProcessTypeInstCustomAttributes(isPacked, isUnion, isCRepr, isOrdered);
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
ProcessTypeInstCustomAttributes(isPacked, isUnion, isCRepr, isOrdered, underlyingArrayType, underlyingArraySize);
if (underlyingArraySize > 0)
{
typeInstance->mHasUnderlyingArray = true;
curFieldDataIdx = 0;
}
if (isPacked) // Packed infers ordered
isOrdered = true;
typeInstance->mIsUnion = isUnion;
@ -3150,7 +3156,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
if (isUnion)
{
fieldInstance->mDataIdx = curFieldDataIdx;
fieldInstance->mDataIdx = curFieldDataIdx;
}
}
}
@ -3408,7 +3414,11 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
///
// 'Splattable' means that we can be passed via 3 or fewer primitive/pointer values
if (typeInstance->IsStruct())
if (typeInstance->mHasUnderlyingArray)
{
// Never splat
}
else if (typeInstance->IsStruct())
{
bool hadNonSplattable = false;
@ -3426,7 +3436,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (checkType->IsMethodRef())
{
// For simplicitly, any methodRef inside a struct makes the struct non-splattable. This reduces cases of needing to
// For simplicity, any methodRef inside a struct makes the struct non-splattable. This reduces cases of needing to
// handle embedded methodRefs
hadNonSplattable = true;
}

View file

@ -658,9 +658,13 @@ bool BfMethodInstance::HasParamsArray()
}
int BfMethodInstance::GetStructRetIdx()
{
if ((mReturnType->IsComposite()) && (!mReturnType->IsValuelessType()) && (!GetLoweredReturnType()))
{
if ((mReturnType->IsComposite()) && (!mReturnType->IsValuelessType()) && (!GetLoweredReturnType()) && (!mIsIntrinsic))
{
auto returnTypeInst = mReturnType->ToTypeInstance();
if ((returnTypeInst != NULL) && (returnTypeInst->mHasUnderlyingArray))
return -1;
auto owner = mMethodInstanceGroup->mOwner;
if (owner->mModule->mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)
return 0;
@ -688,7 +692,7 @@ bool BfMethodInstance::HasSelf()
}
bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2)
{
{
return mReturnType->GetLoweredType(mMethodDef->mIsStatic ? BfTypeUsage_Return_Static : BfTypeUsage_Return_NonStatic, loweredTypeCode, loweredTypeCode2);
}
@ -1005,7 +1009,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
}
else if (mReturnType->IsComposite())
else if (GetStructRetIdx() != -1)
{
auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType);
@ -1558,10 +1562,35 @@ BfPrimitiveType* BfTypeInstance::GetDiscriminatorType(int* outDataIdx)
return (BfPrimitiveType*)fieldInstance.mResolvedType;
}
void BfTypeInstance::GetUnderlyingArray(BfType*& type, int& size, bool& isVector)
{
if (mCustomAttributes == NULL)
return;
auto attributes = mCustomAttributes->Get(mModule->mCompiler->mUnderlyingArrayAttributeTypeDef);
if (attributes == NULL)
return;
if (attributes->mCtorArgs.size() != 3)
return;
auto typeConstant = mConstHolder->GetConstant(attributes->mCtorArgs[0]);
auto sizeConstant = mConstHolder->GetConstant(attributes->mCtorArgs[1]);
auto isVectorConstant = mConstHolder->GetConstant(attributes->mCtorArgs[2]);
if ((typeConstant == NULL) || (sizeConstant == NULL) || (isVectorConstant == NULL))
return;
if (typeConstant->mConstType != BfConstType_TypeOf)
return;
type = (BfType*)(intptr)typeConstant->mInt64;
size = sizeConstant->mInt32;
isVector = isVectorConstant->mBool;
}
bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode, BfTypeCode* outTypeCode2)
{
{
if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (IsBoxed()) || (mIsSplattable))
return false;
if (mHasUnderlyingArray)
return false;
if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows)
{

View file

@ -1744,6 +1744,7 @@ public:
bool mIsUnion;
bool mIsPacked;
bool mIsSplattable;
bool mHasUnderlyingArray;
bool mTypeIncomplete;
bool mTypeFailed;
bool mTypeWarned;
@ -1770,6 +1771,7 @@ public:
mRevision = -1;
mIsReified = true;
mIsSplattable = false;
mHasUnderlyingArray = false;
mIsPacked = false;
mBaseType = NULL;
mCustomAttributes = NULL;
@ -1879,6 +1881,7 @@ public:
int GetIFaceVMethodSize();
BfType* GetUnionInnerType(bool* wantSplat = NULL);
BfPrimitiveType* GetDiscriminatorType(int* outDataIdx = NULL);
void GetUnderlyingArray(BfType*& type, int& size, bool& isVector);
bool HasEquivalentLayout(BfTypeInstance* compareTo);
BfIRConstHolder* GetOrCreateConstHolder();
BfIRValue CreateConst(BfConstant* fromConst, BfIRConstHolder* fromHolder);

View file

@ -0,0 +1,26 @@
using System;
using System.Numerics;
namespace Tests
{
class Numerics
{
[Test, UseLLVM]
public static void TestBasics()
{
float4 v0 = .(1, 2, 3, 4);
float4 v1 = .(10, 100, 1000, 10000);
float4 v2 = v0 * v1;
Test.Assert(v2 === .(10, 200, 3000, 40000));
Test.Assert(v2 !== .(10, 200, 3000, 9));
Test.Assert(v2.x == 10);
Test.Assert(v2.y == 200);
Test.Assert(v2.z == 3000);
Test.Assert(v2.w == 40000);
float4 v3 = v0.wzyx;
Test.Assert(v3 === .(4, 3, 2, 1));
}
}
}

View file

@ -6847,6 +6847,34 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
}
headerStr = StrFormat("(%f, %f)", xmmRegVals[0], xmmRegVals[1]);
}
else if (mmDwMmDisplayType == DwMmDisplayType_Byte)
{
int xmmRegVals[4];
xmmCount = 4;
CPURegisters* regs = optEvaluator->GetRegisters();
for (int xmmMinor = 0; xmmMinor < xmmCount; ++xmmMinor)
{
DbgTypedValue xmmReg = GetRegister(StrFormat("xmm%d_%d", xmmMajor, xmmMinor), language, regs, &wdStackFrame->mRegForms);
BF_ASSERT(xmmReg.mType->mTypeCode == DbgType_i32);
BF_ASSERT(xmmReg.mRegNum == CPUReg_XMMREG_FIRST + (xmmMajor * 4) + xmmMinor);
xmmRegVals[xmmMinor] = xmmReg.mInt8;
}
headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
}
else if (mmDwMmDisplayType == DwMmDisplayType_Short)
{
int xmmRegVals[4];
xmmCount = 4;
CPURegisters* regs = optEvaluator->GetRegisters();
for (int xmmMinor = 0; xmmMinor < xmmCount; ++xmmMinor)
{
DbgTypedValue xmmReg = GetRegister(StrFormat("xmm%d_%d", xmmMajor, xmmMinor), language, regs, &wdStackFrame->mRegForms);
BF_ASSERT(xmmReg.mType->mTypeCode == DbgType_i32);
BF_ASSERT(xmmReg.mRegNum == CPUReg_XMMREG_FIRST + (xmmMajor * 4) + xmmMinor);
xmmRegVals[xmmMinor] = xmmReg.mInt16;
}
headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
}
else if (mmDwMmDisplayType == DwMmDisplayType_Int)
{
int xmmRegVals[4];
@ -6860,7 +6888,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
xmmRegVals[xmmMinor] = xmmReg.mInt32;
}
headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
}
}
else // Float
{
float xmmRegVals[4];
@ -8904,7 +8932,7 @@ DbgTypedValue WinDebugger::GetRegister(const StringImpl& regName, DbgLanguage la
return typedVal;
}
if (mmDisplayType == DwMmDisplayType_Int)
if ((mmDisplayType == DwMmDisplayType_Byte) || (mmDisplayType == DwMmDisplayType_Short) || (mmDisplayType == DwMmDisplayType_Int))
{
DbgTypedValue typedVal;
typedVal.mType = dbgModule->GetPrimitiveType(DbgType_i32, language);