mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Start of SIMD support
This commit is contained in:
parent
73e260c1d5
commit
64b62c09be
30 changed files with 5846 additions and 5096 deletions
|
@ -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
|
||||
{
|
||||
|
|
14
BeefLibs/corlib/src/Numerics/Bool4.bf
Normal file
14
BeefLibs/corlib/src/Numerics/Bool4.bf
Normal 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);
|
||||
}
|
||||
}
|
89
BeefLibs/corlib/src/Numerics/Float4.bf
Normal file
89
BeefLibs/corlib/src/Numerics/Float4.bf
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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>";
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -385,6 +385,7 @@ public:
|
|||
BfTypeDef* mCLinkAttributeTypeDef;
|
||||
BfTypeDef* mImportAttributeTypeDef;
|
||||
BfTypeDef* mCReprAttributeTypeDef;
|
||||
BfTypeDef* mUnderlyingArrayAttributeTypeDef;
|
||||
BfTypeDef* mAlignAttributeTypeDef;
|
||||
BfTypeDef* mAllowDuplicatesAttributeTypeDef;
|
||||
BfTypeDef* mNoDiscardAttributeTypeDef;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
///
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
26
IDEHelper/Tests/src/Numerics.bf
Normal file
26
IDEHelper/Tests/src/Numerics.bf
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue