1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +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*/)] [AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute 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] [AlwaysInclude]
struct SizedArray<T, CSize> where CSize : const int struct SizedArray<T, CSize> where CSize : const int
{ {
T[CSize] mVal; protected T[CSize] mVal;
public int Count 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*/)] [AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute public struct NoShowAttribute : Attribute
{ {

View file

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

View file

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

View file

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

View file

@ -56,6 +56,15 @@ BeType* BeContext::GetPrimitiveType(BeTypeCode typeCode)
case BeTypeCode_Double: case BeTypeCode_Double:
primType->mSize = primType->mAlign = 8; primType->mSize = primType->mAlign = 8;
break; 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; mPrimitiveTypes[(int)typeCode] = primType;
return primType; return primType;
@ -152,6 +161,18 @@ BeSizedArrayType* BeContext::CreateSizedArrayType(BeType* type, int length)
return arrayType; 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) BeFunctionType* BeContext::CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg)
{ {
auto funcType = mTypes.Alloc<BeFunctionType>(); auto funcType = mTypes.Alloc<BeFunctionType>();
@ -196,6 +217,14 @@ bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
if (lhsSizedArray->mLength != rhsSizedArray->mLength) if (lhsSizedArray->mLength != rhsSizedArray->mLength)
return false; return false;
return AreTypesEqual(lhsSizedArray->mElementType, rhsSizedArray->mElementType); 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; return false;

View file

@ -20,10 +20,14 @@ enum BeTypeCode
BeTypeCode_Int64, BeTypeCode_Int64,
BeTypeCode_Float, BeTypeCode_Float,
BeTypeCode_Double, BeTypeCode_Double,
BeTypeCode_M128,
BeTypeCode_M256,
BeTypeCode_M512,
BeTypeCode_Struct, BeTypeCode_Struct,
BeTypeCode_Function, BeTypeCode_Function,
BeTypeCode_Pointer, BeTypeCode_Pointer,
BeTypeCode_SizedArray, BeTypeCode_SizedArray,
BeTypeCode_Vector,
BeTypeCode_CmpResult, // Psuedo BeTypeCode_CmpResult, // Psuedo
BeTypeCode_COUNT BeTypeCode_COUNT
@ -122,7 +126,22 @@ public:
return (mTypeCode == BeTypeCode_SizedArray); 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() 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); 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 class BeFunctionTypeParam
{ {
public: public:
@ -239,6 +273,7 @@ public:
BePointerType* GetPointerTo(BeType* beType); BePointerType* GetPointerTo(BeType* beType);
void SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed); void SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed);
BeSizedArrayType* CreateSizedArrayType(BeType* type, int length); BeSizedArrayType* CreateSizedArrayType(BeType* type, int length);
BeVectorType* CreateVectorType(BeType* type, int length);
BeFunctionType* CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg); BeFunctionType* CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg);
bool AreTypesEqual(BeType* lhs, BeType* rhs); bool AreTypesEqual(BeType* lhs, BeType* rhs);

View file

@ -1015,7 +1015,10 @@ void BeIRCodeGen::HandleNextCmd()
{ {
CMD_PARAM(int, typeId); CMD_PARAM(int, typeId);
CMD_PARAM(BeType*, type); CMD_PARAM(BeType*, type);
GetTypeEntry(typeId).mBeType = type; auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mBeType = type;
if (typeEntry.mInstBeType == NULL)
typeEntry.mInstBeType = type;
} }
break; break;
case BfIRCmd_SetInstType: case BfIRCmd_SetInstType:
@ -1100,6 +1103,13 @@ void BeIRCodeGen::HandleNextCmd()
SetResult(curId, mBeContext->CreateSizedArrayType(elementType, length)); SetResult(curId, mBeContext->CreateSizedArrayType(elementType, length));
} }
break; break;
case BfIRCmd_GetVectorType:
{
CMD_PARAM(BeType*, elementType);
CMD_PARAM(int, length);
SetResult(curId, mBeContext->CreateVectorType(elementType, length));
}
break;
case BfIRCmd_CreateConstStruct: case BfIRCmd_CreateConstStruct:
{ {
CMD_PARAM(BeType*, type); CMD_PARAM(BeType*, type);
@ -2050,49 +2060,14 @@ void BeIRCodeGen::HandleNextCmd()
break; break;
case BfIRCmd_GetIntrinsic: case BfIRCmd_GetIntrinsic:
{ {
CMD_PARAM(String, intrinName);
CMD_PARAM(int, intrinId); CMD_PARAM(int, intrinId);
CMD_PARAM(BeType*, returnType); CMD_PARAM(BeType*, returnType);
CMD_PARAM(CmdParamVec<BeType*>, paramTypes); CMD_PARAM(CmdParamVec<BeType*>, paramTypes);
auto intrin = mBeModule->mAlloc.Alloc<BeIntrinsic>(); auto intrin = mBeModule->mAlloc.Alloc<BeIntrinsic>();
intrin->mKind = (BfIRIntrinsic)intrinId; intrin->mKind = (BfIRIntrinsic)intrinId;
intrin->mReturnType = returnType;
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;
}
SetResult(curId, intrin); SetResult(curId, intrin);
} }
break; break;
@ -2585,7 +2560,10 @@ void BeIRCodeGen::HandleNextCmd()
{ {
CMD_PARAM(int, typeId); CMD_PARAM(int, typeId);
CMD_PARAM(BeMDNode*, type); 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; break;
case BfIRCmd_DbgSetInstType: 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_i16,
BeMCOperandKind_Immediate_i32, BeMCOperandKind_Immediate_i32,
BeMCOperandKind_Immediate_i64, BeMCOperandKind_Immediate_i64,
BeMCOperandKind_Immediate_HomeSize,
BeMCOperandKind_Immediate_Null, BeMCOperandKind_Immediate_Null,
BeMCOperandKind_Immediate_f32, BeMCOperandKind_Immediate_f32,
BeMCOperandKind_Immediate_f64, BeMCOperandKind_Immediate_f64,
BeMCOperandKind_Immediate_f32_Packed128, BeMCOperandKind_Immediate_f32_Packed128,
BeMCOperandKind_Immediate_f64_Packed128, BeMCOperandKind_Immediate_f64_Packed128,
BeMCOperandKind_Immediate_int32x4,
BeMCOperandKind_ConstAgg, BeMCOperandKind_ConstAgg,
BeMCOperandKind_Block, BeMCOperandKind_Block,
BeMCOperandKind_Label, BeMCOperandKind_Label,
@ -283,12 +285,12 @@ public:
bool IsImmediateInt() const bool IsImmediateInt() const
{ {
return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_i64)); return ((mKind >= BeMCOperandKind_Immediate_i8) && (mKind <= BeMCOperandKind_Immediate_HomeSize));
} }
bool IsImmediateFloat() const 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 bool IsNativeReg() const
@ -925,10 +927,12 @@ enum BeMCInstForm
BeMCInstForm_FRM64_XMM32, BeMCInstForm_FRM64_XMM32,
BeMCInstForm_FRM32_XMM64, BeMCInstForm_FRM32_XMM64,
BeMCInstForm_FRM64_XMM64, BeMCInstForm_FRM64_XMM64,
BeMCInstForm_FRM128_XMM128,
BeMCInstForm_XMM32_RM32, BeMCInstForm_XMM32_RM32,
BeMCInstForm_XMM64_RM32, BeMCInstForm_XMM64_RM32,
BeMCInstForm_XMM32_RM64, BeMCInstForm_XMM32_RM64,
BeMCInstForm_XMM64_RM64, BeMCInstForm_XMM64_RM64,
BeMCInstForm_XMM128_RM128,
BeMCInstForm_R32_F32, BeMCInstForm_R32_F32,
BeMCInstForm_R64_F32, BeMCInstForm_R64_F32,
BeMCInstForm_R32_F64, BeMCInstForm_R32_F64,
@ -1209,6 +1213,9 @@ enum BeMCNativeTypeCode
BeMCNativeTypeCode_Int64, BeMCNativeTypeCode_Int64,
BeMCNativeTypeCode_Float, BeMCNativeTypeCode_Float,
BeMCNativeTypeCode_Double, BeMCNativeTypeCode_Double,
BeMCNativeTypeCode_M128,
BeMCNativeTypeCode_M256,
BeMCNativeTypeCode_M512,
BeMCNativeTypeCode_COUNT BeMCNativeTypeCode_COUNT
}; };
@ -1347,6 +1354,7 @@ public:
void Print(); void Print();
BeMCOperand GetOperand(BeValue* value, bool allowMetaResult = false, bool allowFail = false); // Meta results are PHIs or CmpResults BeMCOperand GetOperand(BeValue* value, bool allowMetaResult = false, bool allowFail = false); // Meta results are PHIs or CmpResults
BeMCOperand CreateNot(const BeMCOperand& operand); BeMCOperand CreateNot(const BeMCOperand& operand);
BeMCOperand TryToVector(BeValue* value);
BeType* GetType(const BeMCOperand& operand); BeType* GetType(const BeMCOperand& operand);
bool AreTypesEquivalent(BeType* type0, BeType* type1); bool AreTypesEquivalent(BeType* type0, BeType* type1);
void AddRelRefs(BeMCOperand& operand, int refCount); void AddRelRefs(BeMCOperand& operand, int refCount);
@ -1413,10 +1421,12 @@ public:
bool IsVolatileReg(X64CPURegister reg); bool IsVolatileReg(X64CPURegister reg);
bool IsXMMReg(X64CPURegister reg); bool IsXMMReg(X64CPURegister reg);
X64CPURegister ResizeRegister(X64CPURegister reg, int numBits); X64CPURegister ResizeRegister(X64CPURegister reg, int numBits);
X64CPURegister ResizeRegister(X64CPURegister reg, BeType* type);
X64CPURegister GetFullRegister(X64CPURegister reg);
bool IsAddress(BeMCOperand& operand); bool IsAddress(BeMCOperand& operand);
bool IsAddressable(BeMCOperand& operand); bool IsAddressable(BeMCOperand& operand);
bool IsVRegExpr(BeMCOperand& operand); bool IsVRegExpr(BeMCOperand& operand);
void FixOperand(BeMCOperand& operand); void FixOperand(BeMCOperand& operand, int depth = 0);
BeMCOperand GetFixedOperand(const BeMCOperand& operand); BeMCOperand GetFixedOperand(const BeMCOperand& operand);
uint8 GetREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit); uint8 GetREX(const BeMCOperand& op0, const BeMCOperand& op1, bool is64Bit);
void EmitREX(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); BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray);
return arrayType->mContext->GetPointerTo(arrayType->mElementType); 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()) /*else if (ptrType->mElementType->IsPointer())
{ {
return ptrType->mElementType; return ptrType->mElementType;
@ -528,6 +534,12 @@ BeType* BeExtractValueConstant::GetType()
BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray); BF_ASSERT(arrayType->mTypeCode == BeTypeCode_SizedArray);
return arrayType->mElementType; 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()) /*else if (ptrType->mElementType->IsPointer())
{ {
return ptrType->mElementType; return ptrType->mElementType;
@ -655,6 +667,11 @@ BeType* BeExtractValueInst::GetType()
BeSizedArrayType* arrayType = (BeSizedArrayType*)aggType; BeSizedArrayType* arrayType = (BeSizedArrayType*)aggType;
return arrayType->mElementType; return arrayType->mElementType;
} }
if (aggType->mTypeCode == BeTypeCode_Vector)
{
BeVectorType* arrayType = (BeVectorType*)aggType;
return arrayType->mElementType;
}
BF_ASSERT(aggType->mTypeCode == BeTypeCode_Struct); BF_ASSERT(aggType->mTypeCode == BeTypeCode_Struct);
BeStructType* structType = (BeStructType*)aggType; BeStructType* structType = (BeStructType*)aggType;
return structType->mMembers[mIdx].mType; return structType->mMembers[mIdx].mType;
@ -703,6 +720,11 @@ BeType* BeGEPInst::GetType()
BeSizedArrayType* arrayType = (BeSizedArrayType*)ptrType->mElementType; BeSizedArrayType* arrayType = (BeSizedArrayType*)ptrType->mElementType;
return GetContext()->GetPointerTo(arrayType->mElementType); return GetContext()->GetPointerTo(arrayType->mElementType);
} }
else if (elementType->IsVector())
{
BeVectorType* arrayType = (BeVectorType*)ptrType->mElementType;
return GetContext()->GetPointerTo(arrayType->mElementType);
}
else else
{ {
BF_FATAL("Bad type"); BF_FATAL("Bad type");
@ -1308,7 +1330,8 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
switch (constant->mType->mTypeCode) switch (constant->mType->mTypeCode)
{ {
case BeTypeCode_Struct: case BeTypeCode_Struct:
case BeTypeCode_SizedArray: case BeTypeCode_SizedArray:
case BeTypeCode_Vector:
for (int valIdx = 0; valIdx < (int)constant->mMemberValues.size(); valIdx++) for (int valIdx = 0; valIdx < (int)constant->mMemberValues.size(); valIdx++)
{ {
if (valIdx > 0) if (valIdx > 0)
@ -1412,7 +1435,8 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
return; return;
} }
case BeTypeCode_Struct: case BeTypeCode_Struct:
case BeTypeCode_SizedArray: case BeTypeCode_SizedArray:
case BeTypeCode_Vector:
str += "zeroinitializer"; str += "zeroinitializer";
return; return;
case BeTypeCode_Function: case BeTypeCode_Function:
@ -3033,6 +3057,15 @@ void BeModule::ToString(StringImpl& str, BeType* type)
str += "]"; str += "]";
return; return;
} }
case BeTypeCode_Vector:
{
auto arrayType = (BeSizedArrayType*)type;
ToString(str, arrayType->mElementType);
str += "<";
str += StrFormat("%d", arrayType->mLength);
str += ">";
return;
}
} }
str += "<UnknownType>"; str += "<UnknownType>";
} }

View file

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

View file

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

View file

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

View file

@ -4864,13 +4864,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
else else
{ {
callInst = mModule->mBfIRBuilder->CreateCall(funcCallInst, irArgs); callInst = mModule->mBfIRBuilder->CreateCall(funcCallInst, irArgs);
if (hasResult) if ((hasResult) && (!methodDef->mName.IsEmpty()) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->SetName(callInst, methodDef->mName); mModule->mBfIRBuilder->SetName(callInst, methodDef->mName);
} }
if (expectCallingConvention != BfIRCallingConv_CDecl) if ((expectCallingConvention != BfIRCallingConv_CDecl) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->SetCallCallingConv(callInst, expectCallingConvention); mModule->mBfIRBuilder->SetCallCallingConv(callInst, expectCallingConvention);
if (methodDef->mNoReturn) if ((methodDef->mNoReturn) && (!methodInstance->mIsIntrinsic))
mModule->mBfIRBuilder->Call_AddAttribute(callInst, -1, BfIRAttribute_NoReturn); mModule->mBfIRBuilder->Call_AddAttribute(callInst, -1, BfIRAttribute_NoReturn);
bool hadAttrs = false; bool hadAttrs = false;
@ -4881,7 +4881,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
int paramCount = methodInstance->GetParamCount(); int paramCount = methodInstance->GetParamCount();
for ( ; argIdx < callIRArgCount ; ) for ( ; argIdx < callIRArgCount ; )
{ {
if (methodInstance->mIsIntrinsic)
break;
if (argIdx == methodInstance->GetStructRetIdx()) if (argIdx == methodInstance->GetStructRetIdx())
{ {
mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_StructRet); 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) 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) if (moduleMethodInstance.mMethodInstance == NULL)
return BfTypedValue(); return BfTypedValue();
if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner())) 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()); auto castedTarget = mModule->Cast(methodMatcher->mTargetSrc, target, moduleMethodInstance.mMethodInstance->GetOwner());
BF_ASSERT(castedTarget); BF_ASSERT(castedTarget);
target = castedTarget; target = castedTarget;
} }
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, false, methodMatcher->mArguments); 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; SizedArray<BfExpression*, 2> argSrcs;
argSrcs.push_back(unaryOpExpr); 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())) if ((result.mType != NULL) && (methodMatcher.mSelfType != NULL) && (result.mType->IsSelf()))
{ {
BF_ASSERT(mModule->IsInGeneric()); BF_ASSERT(mModule->IsInGeneric());
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType); result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
} }
if (isPostOp) if ((methodMatcher.mBestMethodInstance) && (methodMatcher.mBestMethodInstance.mMethodInstance->mIsIntrinsic) &&
result = args[0].mTypedValue; ((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; 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(); methodMatcher.FlushAmbiguityError();

View file

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

View file

@ -2167,7 +2167,14 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
BfIRType irType; BfIRType irType;
BfIRMDNode diType; BfIRMDNode diType;
bool trackDIType = false; 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()) if (type->IsPointer())
{ {
BfPointerType* pointerType = (BfPointerType*)type; BfPointerType* pointerType = (BfPointerType*)type;
@ -2281,6 +2288,19 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
irType = CreateStructType(name); irType = CreateStructType(name);
StructSetBody(irType, members, false); 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()) else if (type->IsSizedArray())
{ {
BfSizedArrayType* arrayType = (BfSizedArrayType*)type; BfSizedArrayType* arrayType = (BfSizedArrayType*)type;
@ -2375,8 +2395,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
} }
} }
else if (type->IsTypeInstance()) else if (type->IsTypeInstance())
{ {
BfTypeInstance* typeInstance = type->ToTypeInstance();
auto typeDef = typeInstance->mTypeDef; auto typeDef = typeInstance->mTypeDef;
BfIRMDNode diForwardDecl; BfIRMDNode diForwardDecl;
@ -2524,14 +2543,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
#ifdef BFIR_RENTRY_CHECK #ifdef BFIR_RENTRY_CHECK
ReEntryCheck reEntryCheck(&mDefReentrySet, type); ReEntryCheck reEntryCheck(&mDefReentrySet, type);
#endif #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)); //BF_ASSERT(WantsDbgDefinition(type));
llvm::SmallVector<BfIRMDNode, 8> diFieldTypes; llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;
@ -2539,6 +2551,9 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
bool isPacked = false; bool isPacked = false;
bool isUnion = false; bool isUnion = false;
bool isCRepr = false; bool isCRepr = false;
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
bool underlyingArrayIsVector = false;
if (typeInstance->IsBoxed()) if (typeInstance->IsBoxed())
{ {
@ -2549,8 +2564,18 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
isCRepr = typeInstance->mIsCRepr; isCRepr = typeInstance->mIsCRepr;
isPacked = typeInstance->mIsPacked; isPacked = typeInstance->mIsPacked;
isUnion = typeInstance->mIsUnion; 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; BfSizedVector<BfFieldInstance*, 8> orderedFields;
if ((type->IsUnion()) && (!type->IsEnum())) if ((type->IsUnion()) && (!type->IsEnum()))
@ -3058,6 +3083,13 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine)
if (typeInstance == NULL) if (typeInstance == NULL)
return; return;
BfType* underlyingArrayType = NULL;
int underlyingArraySize = -1;
bool underlyingIsVector = false;
typeInstance->GetUnderlyingArray(underlyingArrayType, underlyingArraySize, underlyingIsVector);
if (underlyingArraySize > 0)
return;
auto typeDef = typeInstance->mTypeDef; auto typeDef = typeInstance->mTypeDef;
#ifdef BFIR_RENTRY_CHECK #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 BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values)
{ {
BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstStruct, type, values); BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstStruct, type, values);
@ -4516,9 +4555,9 @@ void BfIRBuilder::AddPhiIncoming(BfIRValue phi, BfIRValue value, BfIRBlock comin
NEW_CMD_INSERTED; 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; NEW_CMD_INSERTED;
return retVal; return retVal;
} }

View file

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

View file

@ -134,6 +134,8 @@ struct BuiltinEntry
static const BuiltinEntry gIntrinEntries[] = static const BuiltinEntry gIntrinEntries[] =
{ {
{"abs"}, {"abs"},
{"add"},
{"and"},
{"atomic_add"}, {"atomic_add"},
{"atomic_and"}, {"atomic_and"},
{"atomic_cmpstore"}, {"atomic_cmpstore"},
@ -153,21 +155,35 @@ static const BuiltinEntry gIntrinEntries[] =
{"atomic_xor"}, {"atomic_xor"},
{"bswap"}, {"bswap"},
{"cast"}, {"cast"},
{"cos"}, {"cos"},
{"div"},
{"eq"},
{"floor"}, {"floor"},
{"free"}, {"free"},
{"gt"},
{"gte"},
{"log"}, {"log"},
{"log10"}, {"log10"},
{"log2"}, {"log2"},
{"lt"},
{"lte"},
{"malloc"}, {"malloc"},
{"memcpy"}, {"memcpy"},
{"memmove"}, {"memmove"},
{"memset"}, {"memset"},
{"mod"},
{"mul"},
{"neq"},
{"not"},
{"or"},
{"pow"}, {"pow"},
{"powi"}, {"powi"},
{"round"}, {"round"},
{"shuffle"},
{"sin"}, {"sin"},
{"sqrt"}, {"sqrt"},
{"sub"},
{"xor"},
}; };
#define CMD_PARAM(ty, name) ty name; Read(name); #define CMD_PARAM(ty, name) ty name; Read(name);
@ -1049,6 +1065,33 @@ void BfIRCodeGen::AddNop()
callInst->addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoUnwind); 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) bool BfIRCodeGen::TryMemCpy(llvm::Value* ptr, llvm::Value* val)
{ {
auto valType = val->getType(); auto valType = val->getType();
@ -1110,6 +1153,31 @@ bool BfIRCodeGen::TryMemCpy(llvm::Value* ptr, llvm::Value* val)
return true; 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) void BfIRCodeGen::CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile)
{ {
auto sizeConst = llvm::dyn_cast<llvm::ConstantInt>(size); auto sizeConst = llvm::dyn_cast<llvm::ConstantInt>(size);
@ -1273,7 +1341,10 @@ void BfIRCodeGen::HandleNextCmd()
{ {
CMD_PARAM(int, typeId); CMD_PARAM(int, typeId);
CMD_PARAM(llvm::Type*, type); CMD_PARAM(llvm::Type*, type);
GetTypeEntry(typeId).mLLVMType = type; auto& typeEntry = GetTypeEntry(typeId);
typeEntry.mLLVMType = type;
if (typeEntry.mInstLLVMType == NULL)
typeEntry.mInstLLVMType = type;
} }
break; break;
case BfIRCmd_SetInstType: case BfIRCmd_SetInstType:
@ -1359,6 +1430,13 @@ void BfIRCodeGen::HandleNextCmd()
SetResult(curId, llvm::ArrayType::get(elementType, length)); SetResult(curId, llvm::ArrayType::get(elementType, length));
} }
break; break;
case BfIRCmd_GetVectorType:
{
CMD_PARAM(llvm::Type*, elementType);
CMD_PARAM(int, length);
SetResult(curId, llvm::VectorType::get(elementType, length));
}
break;
case BfIRCmd_CreateConstStruct: case BfIRCmd_CreateConstStruct:
{ {
CMD_PARAM(llvm::Type*, type); CMD_PARAM(llvm::Type*, type);
@ -1854,8 +1932,9 @@ void BfIRCodeGen::HandleNextCmd()
CMD_PARAM(llvm::Value*, val); CMD_PARAM(llvm::Value*, val);
CMD_PARAM(llvm::Value*, ptr); CMD_PARAM(llvm::Value*, ptr);
CMD_PARAM(bool, isVolatile); CMD_PARAM(bool, isVolatile);
if (!TryMemCpy(ptr, val)) if ((!TryMemCpy(ptr, val)) &&
(!TryVectorCpy(ptr, val)))
SetResult(curId, mIRBuilder->CreateStore(val, ptr, isVolatile)); SetResult(curId, mIRBuilder->CreateStore(val, ptr, isVolatile));
} }
break; break;
@ -1865,7 +1944,8 @@ void BfIRCodeGen::HandleNextCmd()
CMD_PARAM(llvm::Value*, ptr); CMD_PARAM(llvm::Value*, ptr);
CMD_PARAM(int, alignment); CMD_PARAM(int, alignment);
CMD_PARAM(bool, isVolatile); CMD_PARAM(bool, isVolatile);
if (!TryMemCpy(ptr, val)) if ((!TryMemCpy(ptr, val)) &&
(!TryVectorCpy(ptr, val)))
SetResult(curId, mIRBuilder->CreateAlignedStore(val, ptr, alignment, isVolatile)); SetResult(curId, mIRBuilder->CreateAlignedStore(val, ptr, alignment, isVolatile));
} }
break; break;
@ -2116,29 +2196,11 @@ void BfIRCodeGen::HandleNextCmd()
break; break;
case BfIRCmd_GetIntrinsic: case BfIRCmd_GetIntrinsic:
{ {
CMD_PARAM(String, intrinName);
CMD_PARAM(int, intrinId); CMD_PARAM(int, intrinId);
CMD_PARAM(llvm::Type*, returnType); CMD_PARAM(llvm::Type*, returnType);
CMD_PARAM(CmdParamVec<llvm::Type*>, paramTypes); 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; llvm::Function* func = NULL;
struct _Intrinsics struct _Intrinsics
@ -2152,43 +2214,74 @@ void BfIRCodeGen::HandleNextCmd()
static _Intrinsics intrinsics[] = static _Intrinsics intrinsics[] =
{ {
{ llvm::Intrinsic::fabs, 0, -1}, { llvm::Intrinsic::fabs, 0, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicAdd, { (llvm::Intrinsic::ID)-2, -1}, // add,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicAnd, { (llvm::Intrinsic::ID)-2, -1}, // and,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpStore, { (llvm::Intrinsic::ID)-2, -1}, // AtomicAdd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpStore_Weak, { (llvm::Intrinsic::ID)-2, -1}, // AtomicAnd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicCmpXChg, { (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpStore,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicFence, { (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpStore_Weak,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicLoad, { (llvm::Intrinsic::ID)-2, -1}, // AtomicCmpXChg,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicMax, { (llvm::Intrinsic::ID)-2, -1}, // AtomicFence,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicMin, { (llvm::Intrinsic::ID)-2, -1}, // AtomicLoad,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicNAnd, { (llvm::Intrinsic::ID)-2, -1}, // AtomicMax,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicOr, { (llvm::Intrinsic::ID)-2, -1}, // AtomicMin,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicStore, { (llvm::Intrinsic::ID)-2, -1}, // AtomicNAnd,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicSub, { (llvm::Intrinsic::ID)-2, -1}, // AtomicOr,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicUMax, { (llvm::Intrinsic::ID)-2, -1}, // AtomicStore,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicUMin, { (llvm::Intrinsic::ID)-2, -1}, // AtomicSub,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXChg, { (llvm::Intrinsic::ID)-2, -1}, // AtomicUMax,
{ (llvm::Intrinsic::ID)-1, -1}, // AtomicXor, { (llvm::Intrinsic::ID)-2, -1}, // AtomicUMin,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicXChg,
{ (llvm::Intrinsic::ID)-2, -1}, // AtomicXor,
{ llvm::Intrinsic::bswap, -1}, { llvm::Intrinsic::bswap, -1},
{ (llvm::Intrinsic::ID)-1, -1}, // cast, { (llvm::Intrinsic::ID)-2, -1}, // cast,
{ llvm::Intrinsic::cos, 0, -1}, { llvm::Intrinsic::cos, 0, -1},
{ (llvm::Intrinsic::ID)-2, -1}, // div
{ (llvm::Intrinsic::ID)-2, -1}, // eq
{ llvm::Intrinsic::floor, 0, -1}, { 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::log, 0, -1},
{ llvm::Intrinsic::log10, 0, -1}, { llvm::Intrinsic::log10, 0, -1},
{ llvm::Intrinsic::log2, 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::memcpy, 0, 1, 2},
{ llvm::Intrinsic::memmove, 0, 2}, { llvm::Intrinsic::memmove, 0, 2},
{ llvm::Intrinsic::memset, 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::pow, 0, -1},
{ llvm::Intrinsic::powi, 0, -1}, { llvm::Intrinsic::powi, 0, -1},
{ llvm::Intrinsic::round, 0, -1}, { llvm::Intrinsic::round, 0, -1},
{ llvm::Intrinsic::sin, 0, -1}, { (llvm::Intrinsic::ID)-2, -1}, // shuffle
{ llvm::Intrinsic::sqrt, 0, -1}, { 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); 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; CmdParamVec<llvm::Type*> useParams;
if (intrinsics[intrinId].mArg0 != -1) if (intrinsics[intrinId].mArg0 != -1)
{ {
@ -2319,6 +2412,236 @@ void BfIRCodeGen::HandleNextCmd()
switch (intrinsicData->mIntrinsic) 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:
case BfIRIntrinsic_AtomicCmpStore_Weak: case BfIRIntrinsic_AtomicCmpStore_Weak:
case BfIRIntrinsic_AtomicCmpXChg: case BfIRIntrinsic_AtomicCmpXChg:
@ -2326,7 +2649,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[3]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[3]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant success ordering on Atomic_CmpXChg"); FatalError("Non-constant success ordering on Atomic_CmpXChg");
break; break;
} }
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue(); auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2365,7 +2688,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[4]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[4]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant fail ordering on Atomic_CmpXChg"); FatalError("Non-constant fail ordering on Atomic_CmpXChg");
break; break;
} }
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue(); auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2381,7 +2704,7 @@ void BfIRCodeGen::HandleNextCmd()
failOrdering = llvm::AtomicOrdering::SequentiallyConsistent; failOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
break; break;
default: default:
Fail("Invalid fail ordering on Atomic_CmpXChg"); FatalError("Invalid fail ordering on Atomic_CmpXChg");
break; break;
} }
} }
@ -2427,7 +2750,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[0]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[0]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant success ordering on AtomicFence"); FatalError("Non-constant success ordering on AtomicFence");
break; break;
} }
@ -2460,7 +2783,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant success ordering on AtomicLoad"); FatalError("Non-constant success ordering on AtomicLoad");
break; break;
} }
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue(); auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2490,7 +2813,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[1]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant success ordering on AtomicLoad"); FatalError("Non-constant success ordering on AtomicLoad");
break; break;
} }
auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue(); auto memoryKind = (BfIRAtomicOrdering)memoryKindConst->getSExtValue();
@ -2569,7 +2892,7 @@ void BfIRCodeGen::HandleNextCmd()
auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[2]); auto memoryKindConst = llvm::dyn_cast<llvm::ConstantInt>(args[2]);
if (memoryKindConst == NULL) if (memoryKindConst == NULL)
{ {
Fail("Non-constant ordering on atomic operation"); FatalError("Non-constant ordering on atomic operation");
break; break;
} }
@ -2676,7 +2999,7 @@ void BfIRCodeGen::HandleNextCmd()
} }
break; break;
default: default:
Fail("Unhandled intrinsic"); FatalError("Unhandled intrinsic");
} }
break; break;
} }
@ -3115,7 +3438,10 @@ void BfIRCodeGen::HandleNextCmd()
{ {
CMD_PARAM(int, typeId); CMD_PARAM(int, typeId);
CMD_PARAM(llvm::MDNode*, type); 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; break;
case BfIRCmd_DbgSetInstType: case BfIRCmd_DbgSetInstType:
@ -4537,17 +4863,16 @@ bool BfIRCodeGen::WriteIR(const StringImpl& outFileName, StringImpl& error)
} }
int BfIRCodeGen::GetIntrinsicId(const StringImpl& name) 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); auto itr = std::lower_bound(std::begin(gIntrinEntries), std::end(gIntrinEntries), name);
if (itr != std::end(gIntrinEntries) && strcmp(itr->mName, name.c_str()) == 0) if (itr != std::end(gIntrinEntries) && strcmp(itr->mName, name.c_str()) == 0)
{ {
int id = (int)(itr - gIntrinEntries); int id = (int)(itr - gIntrinEntries);
return id; return id;
} }
if (name.StartsWith("shuffle"))
return BfIRIntrinsic_Shuffle;
return -1; return -1;
} }

View file

@ -19,6 +19,7 @@ enum BfIRCodeGenEntryKind
class BfIRIntrinsicData class BfIRIntrinsicData
{ {
public: public:
String mName;
BfIRIntrinsic mIntrinsic; BfIRIntrinsic mIntrinsic;
llvm::Type* mReturnType; llvm::Type* mReturnType;
}; };
@ -98,7 +99,9 @@ public:
void SetResult(int id, llvm::MDNode* value); void SetResult(int id, llvm::MDNode* value);
void CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile = false); void CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile = false);
void AddNop(); void AddNop();
llvm::Value* TryToVector(llvm::Value* value);
bool TryMemCpy(llvm::Value* ptr, llvm::Value* val); bool TryMemCpy(llvm::Value* ptr, llvm::Value* val);
bool TryVectorCpy(llvm::Value* ptr, llvm::Value* val);
public: public:
BfIRCodeGen(); BfIRCodeGen();
@ -147,7 +150,7 @@ public:
llvm::BasicBlock* GetLLVMBlock(int streamId); llvm::BasicBlock* GetLLVMBlock(int streamId);
llvm::MDNode* GetLLVMMetadata(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 else
{ {
auto _HandleMethod = [&](BfMethodInstance* methodInstance)
{
if ((methodInstance != NULL) && (methodInstance->mDeclModule != NULL))
methodInstance->mDeclModule = this;
};
for (auto& methodGroup : typeInst->mMethodInstanceGroups) for (auto& methodGroup : typeInst->mMethodInstanceGroups)
{
if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)) (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference))
{ {
oldOnDemandCount++; oldOnDemandCount++;
} }
_HandleMethod(methodGroup.mDefault);
if (methodGroup.mMethodSpecializationMap != NULL)
for (auto& kv : *methodGroup.mMethodSpecializationMap)
_HandleMethod(kv.mValue);
}
} }
if (typeInst->IsDeleting()) if (typeInst->IsDeleting())
typeIdx--; typeIdx--;
@ -4068,8 +4081,14 @@ void BfModule::EmitEquals(BfTypedValue leftValue, BfTypedValue rightValue, BfIRB
{ {
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);
exprEvaluator.mExpectingType = mCurMethodInstance->mReturnType; 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(); BfTypedValue result = exprEvaluator.GetResult();
if (result.mType != GetPrimitiveType(BfTypeCode_Boolean))
{
// Fail?
}
if ((result) && (!result.mType->IsVar())) if ((result) && (!result.mType->IsVar()))
{ {
auto nextBB = mBfIRBuilder->CreateBlock("next"); auto nextBB = mBfIRBuilder->CreateBlock("next");
@ -6520,9 +6539,8 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor
auto methodOwner = methodInstance->GetOwner(); auto methodOwner = methodInstance->GetOwner();
auto methodDef = methodInstance->mMethodDef; auto methodDef = methodInstance->mMethodDef;
auto methodDeclaration = methodDef->GetMethodDeclaration(); auto methodDeclaration = methodDef->GetMethodDeclaration();
bool hasExternSpecifier = (methodDeclaration != NULL) && (methodDeclaration->mExternSpecifier != NULL); if (!methodDef->mIsExtern)
if (!hasExternSpecifier)
return BfIRFunction(); return BfIRFunction();
if (methodInstance->GetCustomAttributes() == NULL) if (methodInstance->GetCustomAttributes() == NULL)
@ -6542,33 +6560,44 @@ BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool repor
{ {
int stringId = constant->mInt32; int stringId = constant->mInt32;
auto entry = mContext->mStringObjectIdMap[stringId]; auto entry = mContext->mStringObjectIdMap[stringId];
int intrinId = BfIRCodeGen::GetIntrinsicId(entry.mString); String intrinName = entry.mString;
if (intrinId != -1)
// 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); if (intrinId == BfIRIntrinsic_Malloc)
} {
else if (intrinId == BfIRIntrinsic_Free) return GetBuiltInFunc(BfBuiltInFuncType_Malloc);
{ }
return GetBuiltInFunc(BfBuiltInFuncType_Free); else if (intrinId == BfIRIntrinsic_Free)
} {
return GetBuiltInFunc(BfBuiltInFuncType_Free);
}
SizedArray<BfIRType, 2> paramTypes; SizedArray<BfIRType, 2> paramTypes;
for (auto& param : methodInstance->mParams) for (auto& param : methodInstance->mParams)
paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType)); paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
return mBfIRBuilder->GetIntrinsic(intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes); 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) else if (reportFailure)
error = "Intrinsic name must be a constant string"; error = "Intrinsic name must be a constant string";
if (reportFailure) if (reportFailure)
{ {
BfAstNode* ref = methodDeclaration->mAttributes; Fail(error, customAttribute.mRef);
Fail(error, ref);
} }
} }
} }
@ -9415,20 +9444,9 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
return func; return func;
} }
if (auto methodDeclaration = methodDef->GetMethodDeclaration()) auto intrinsic = GetIntrinsic(methodInstance);
{ if (intrinsic)
if (methodDeclaration->mExternSpecifier != NULL) return intrinsic;
{
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;*/
}
}
if (methodInstance->GetImportCallKind() != BfImportCallKind_None) if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
{ {
@ -10550,7 +10568,7 @@ void BfModule::FinishAttributeState(BfAttributeState* attributeState)
Warn(0, "Unused attributes", attributeState->mSrc); 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) 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); BF_ASSERT(val);
mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx())); mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
mBfIRBuilder->CreateRetVoid(); mBfIRBuilder->CreateRetVoid();
return;
} }
else
if (mCurMethodInstance->mReturnType->IsValuelessType())
{ {
if (mCurMethodInstance->mReturnType->IsValuelessType()) mBfIRBuilder->CreateRetVoid();
{ return;
mBfIRBuilder->CreateRetVoid(); }
}
else if (mCurMethodInstance->mReturnType->IsStruct()) if (mCurMethodInstance->mReturnType->IsStruct())
{ {
BfTypeCode loweredReturnType = BfTypeCode_None; BfTypeCode loweredReturnType = BfTypeCode_None;
BfTypeCode loweredReturnType2 = BfTypeCode_None; BfTypeCode loweredReturnType2 = BfTypeCode_None;
mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2); mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
if (loweredReturnType != BfTypeCode_None)
{
auto retVal = CreateAlloca(mCurMethodInstance->mReturnType); auto retVal = CreateAlloca(mCurMethodInstance->mReturnType);
mBfIRBuilder->CreateStore(val, retVal); mBfIRBuilder->CreateStore(val, retVal);
@ -13590,13 +13625,12 @@ void BfModule::CreateReturn(BfIRValue val)
auto ptrReturnValue = mBfIRBuilder->CreateBitCast(retVal, irRetType); auto ptrReturnValue = mBfIRBuilder->CreateBitCast(retVal, irRetType);
auto loadedReturnValue = mBfIRBuilder->CreateLoad(ptrReturnValue); auto loadedReturnValue = mBfIRBuilder->CreateLoad(ptrReturnValue);
mBfIRBuilder->CreateRet(loadedReturnValue); mBfIRBuilder->CreateRet(loadedReturnValue);
} return;
else }
{
BF_ASSERT(val);
mBfIRBuilder->CreateRet(val);
}
} }
BF_ASSERT(val);
mBfIRBuilder->CreateRet(val);
} }
void BfModule::EmitReturn(BfIRValue 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); 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); BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
void FinishAttributeState(BfAttributeState* attributeState); 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(); void ProcessCustomAttributeData();
bool TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue, StringImpl& str); bool TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue, StringImpl& str);
BfVariant TypedValueToVariant(BfAstNode* refNode, const BfTypedValue& value, bool allowUndef = false); BfVariant TypedValueToVariant(BfAstNode* refNode, const BfTypedValue& value, bool allowUndef = false);

View file

@ -1908,7 +1908,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
CheckCircularDataError(); CheckCircularDataError();
bool underlyingTypeDeferred = false; bool underlyingTypeDeferred = false;
BfType* underlyingType = NULL; BfType* underlyingType = NULL;
if (typeInstance->mBaseType != NULL) if (typeInstance->mBaseType != NULL)
{ {
if (typeInstance->IsTypedPrimitive()) if (typeInstance->IsTypedPrimitive())
@ -2390,7 +2390,6 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
BF_ASSERT(typeInstance->mBaseType == baseTypeInst); BF_ASSERT(typeInstance->mBaseType == baseTypeInst);
} }
if (auto genericTypeInst = typeInstance->ToGenericTypeInstance()) if (auto genericTypeInst = typeInstance->ToGenericTypeInstance())
{ {
@ -2595,7 +2594,14 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
bool isUnion = false; bool isUnion = false;
bool isCRepr = false; bool isCRepr = false;
bool isOrdered = 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 if (isPacked) // Packed infers ordered
isOrdered = true; isOrdered = true;
typeInstance->mIsUnion = isUnion; typeInstance->mIsUnion = isUnion;
@ -3150,7 +3156,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
if (isUnion) 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 // '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; bool hadNonSplattable = false;
@ -3426,7 +3436,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (checkType->IsMethodRef()) 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 // handle embedded methodRefs
hadNonSplattable = true; hadNonSplattable = true;
} }

View file

@ -658,9 +658,13 @@ bool BfMethodInstance::HasParamsArray()
} }
int BfMethodInstance::GetStructRetIdx() 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; auto owner = mMethodInstanceGroup->mOwner;
if (owner->mModule->mCompiler->mOptions.mPlatformType != BfPlatformType_Windows) if (owner->mModule->mCompiler->mOptions.mPlatformType != BfPlatformType_Windows)
return 0; return 0;
@ -688,7 +692,7 @@ bool BfMethodInstance::HasSelf()
} }
bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2) bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2)
{ {
return mReturnType->GetLoweredType(mMethodDef->mIsStatic ? BfTypeUsage_Return_Static : BfTypeUsage_Return_NonStatic, loweredTypeCode, 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); auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType); returnType = module->mBfIRBuilder->MapType(voidType);
} }
else if (mReturnType->IsComposite()) else if (GetStructRetIdx() != -1)
{ {
auto voidType = module->GetPrimitiveType(BfTypeCode_None); auto voidType = module->GetPrimitiveType(BfTypeCode_None);
returnType = module->mBfIRBuilder->MapType(voidType); returnType = module->mBfIRBuilder->MapType(voidType);
@ -1558,10 +1562,35 @@ BfPrimitiveType* BfTypeInstance::GetDiscriminatorType(int* outDataIdx)
return (BfPrimitiveType*)fieldInstance.mResolvedType; 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) bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode, BfTypeCode* outTypeCode2)
{ {
if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (IsBoxed()) || (mIsSplattable)) if ((mTypeDef->mTypeCode != BfTypeCode_Struct) || (IsBoxed()) || (mIsSplattable))
return false; return false;
if (mHasUnderlyingArray)
return false;
if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows)
{ {

View file

@ -1744,6 +1744,7 @@ public:
bool mIsUnion; bool mIsUnion;
bool mIsPacked; bool mIsPacked;
bool mIsSplattable; bool mIsSplattable;
bool mHasUnderlyingArray;
bool mTypeIncomplete; bool mTypeIncomplete;
bool mTypeFailed; bool mTypeFailed;
bool mTypeWarned; bool mTypeWarned;
@ -1770,6 +1771,7 @@ public:
mRevision = -1; mRevision = -1;
mIsReified = true; mIsReified = true;
mIsSplattable = false; mIsSplattable = false;
mHasUnderlyingArray = false;
mIsPacked = false; mIsPacked = false;
mBaseType = NULL; mBaseType = NULL;
mCustomAttributes = NULL; mCustomAttributes = NULL;
@ -1879,6 +1881,7 @@ public:
int GetIFaceVMethodSize(); int GetIFaceVMethodSize();
BfType* GetUnionInnerType(bool* wantSplat = NULL); BfType* GetUnionInnerType(bool* wantSplat = NULL);
BfPrimitiveType* GetDiscriminatorType(int* outDataIdx = NULL); BfPrimitiveType* GetDiscriminatorType(int* outDataIdx = NULL);
void GetUnderlyingArray(BfType*& type, int& size, bool& isVector);
bool HasEquivalentLayout(BfTypeInstance* compareTo); bool HasEquivalentLayout(BfTypeInstance* compareTo);
BfIRConstHolder* GetOrCreateConstHolder(); BfIRConstHolder* GetOrCreateConstHolder();
BfIRValue CreateConst(BfConstant* fromConst, BfIRConstHolder* fromHolder); 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]); 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) else if (mmDwMmDisplayType == DwMmDisplayType_Int)
{ {
int xmmRegVals[4]; int xmmRegVals[4];
@ -6860,7 +6888,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
xmmRegVals[xmmMinor] = xmmReg.mInt32; xmmRegVals[xmmMinor] = xmmReg.mInt32;
} }
headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]); headerStr = StrFormat("(%d, %d, %d, %d)", xmmRegVals[0], xmmRegVals[1], xmmRegVals[2], xmmRegVals[3]);
} }
else // Float else // Float
{ {
float xmmRegVals[4]; float xmmRegVals[4];
@ -8904,7 +8932,7 @@ DbgTypedValue WinDebugger::GetRegister(const StringImpl& regName, DbgLanguage la
return typedVal; return typedVal;
} }
if (mmDisplayType == DwMmDisplayType_Int) if ((mmDisplayType == DwMmDisplayType_Byte) || (mmDisplayType == DwMmDisplayType_Short) || (mmDisplayType == DwMmDisplayType_Int))
{ {
DbgTypedValue typedVal; DbgTypedValue typedVal;
typedVal.mType = dbgModule->GetPrimitiveType(DbgType_i32, language); typedVal.mType = dbgModule->GetPrimitiveType(DbgType_i32, language);