1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Added constant string appending with + operator, const string fixes

This commit is contained in:
Brian Fiete 2020-02-28 09:20:43 -08:00
parent 41cb0052b2
commit c92bc523db
14 changed files with 158 additions and 34 deletions

View file

@ -1247,7 +1247,7 @@ void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgV
{ {
if (auto beConst = BeValueDynCast<BeConstant>(dbgVar->mValue)) if (auto beConst = BeValueDynCast<BeConstant>(dbgVar->mValue))
{ {
if (!beConst->mType->IsPointer()) if ((beConst->mType != NULL) && (!beConst->mType->IsPointer()))
{ {
int64 writeVal = beConst->mInt64; int64 writeVal = beConst->mInt64;
if (beConst->mType->mTypeCode == BfTypeCode_Single) if (beConst->mType->mTypeCode == BfTypeCode_Single)

View file

@ -170,6 +170,14 @@ bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
return true; return true;
case BeTypeCode_Pointer: case BeTypeCode_Pointer:
return AreTypesEqual(((BePointerType*)lhs)->mElementType, ((BePointerType*)rhs)->mElementType); return AreTypesEqual(((BePointerType*)lhs)->mElementType, ((BePointerType*)rhs)->mElementType);
case BeTypeCode_SizedArray:
{
auto lhsSizedArray = (BeSizedArrayType*)lhs;
auto rhsSizedArray = (BeSizedArrayType*)rhs;
if (lhsSizedArray->mLength != rhsSizedArray->mLength)
return false;
return AreTypesEqual(lhsSizedArray->mElementType, rhsSizedArray->mElementType);
}
} }
return false; return false;
} }

View file

@ -561,6 +561,14 @@ void BeIRCodeGen::Read(BeType*& beType)
return; return;
} }
if (typeKind == BfIRType::TypeKind::TypeKind_SizedArray)
{
CMD_PARAM(BeType*, elementType);
CMD_PARAM(int, length);
beType = mBeContext->CreateSizedArrayType(elementType, length);
return;
}
int typeId = (int)ReadSLEB128(); int typeId = (int)ReadSLEB128();
auto& typeEntry = GetTypeEntry(typeId); auto& typeEntry = GetTypeEntry(typeId);
if (typeKind == BfIRType::TypeKind::TypeKind_TypeId) if (typeKind == BfIRType::TypeKind::TypeKind_TypeId)
@ -1631,6 +1639,7 @@ void BeIRCodeGen::HandleNextCmd()
{ {
globalVariable->mAlign = varType->mAlign; globalVariable->mAlign = varType->mAlign;
BF_ASSERT(varType->mAlign > 0); BF_ASSERT(varType->mAlign > 0);
BF_ASSERT(mBeContext->AreTypesEqual(varType, initializer->GetType()));
} }
else else
globalVariable->mAlign = -1; globalVariable->mAlign = -1;

View file

@ -74,6 +74,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
(toType == mResult.mType))) (toType == mResult.mType)))
{ {
auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue); auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
if (constant->mTypeCode == BfTypeCode_NullPtr) if (constant->mTypeCode == BfTypeCode_NullPtr)
{ {
return mModule->GetDefaultTypedValue(toType); return mModule->GetDefaultTypedValue(toType);
@ -82,7 +83,15 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
{ {
int stringId = mModule->GetStringPoolIdx(mResult.mValue); int stringId = mModule->GetStringPoolIdx(mResult.mValue);
BF_ASSERT(stringId >= 0); BF_ASSERT(stringId >= 0);
return BfTypedValue(mModule->GetConstValue(stringId), toType);
if ((flags & BfConstResolveFlag_RemapFromStringId) != 0)
{
ignoreWrites.Restore();
mModule->mBfIRBuilder->PopulateType(mResult.mType);
return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType);
}
return BfTypedValue(mModule->GetConstValue32(stringId), toType);
} }
} }
} }

View file

@ -15,6 +15,7 @@ enum BfConstResolveFlags
BfConstResolveFlag_ExplicitCast = 1, BfConstResolveFlag_ExplicitCast = 1,
BfConstResolveFlag_NoCast = 2, BfConstResolveFlag_NoCast = 2,
BfConstResolveFlag_AllowSoftFail = 4, BfConstResolveFlag_AllowSoftFail = 4,
BfConstResolveFlag_RemapFromStringId = 8
}; };
class BfConstResolver : public BfExprEvaluator class BfConstResolver : public BfExprEvaluator

View file

@ -17351,6 +17351,30 @@ bool BfExprEvaluator::CheckConstCompare(BfBinaryOp binaryOp, BfAstNode* opToken,
return false; return false;
} }
void BfExprEvaluator::AddStrings(const BfTypedValue& leftValue, const BfTypedValue& rightValue, BfAstNode* refNode)
{
if ((leftValue.mValue.IsConst()) && (rightValue.mValue.IsConst()))
{
String* lhsStr = mModule->GetStringPoolString(leftValue.mValue, mModule->mBfIRBuilder);
String* rhsStr = mModule->GetStringPoolString(rightValue.mValue, mModule->mBfIRBuilder);
if ((lhsStr != NULL) && (rhsStr != NULL))
{
String resultStr = *lhsStr + *rhsStr;
BfVariant variant;
variant.mTypeCode = BfTypeCode_CharPtr;
variant.mString = &resultStr;
GetLiteral(refNode, variant);
return;
}
}
mModule->Fail("Strings can only be added when they are constants. Consider allocating a string and using Concat.", refNode);
return;
}
void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNode* rightExpression, BfBinaryOp binaryOp, BfAstNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue, BfTypedValue rightValue) void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNode* rightExpression, BfBinaryOp binaryOp, BfAstNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue, BfTypedValue rightValue)
{ {
bool noClassify = (flags & BfBinOpFlag_NoClassify) != 0; bool noClassify = (flags & BfBinOpFlag_NoClassify) != 0;
@ -17905,6 +17929,13 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (resultType->IsPointer() && otherType->IsPointer()) if (resultType->IsPointer() && otherType->IsPointer())
{ {
if ((binaryOp == BfBinaryOp_Add) && (resultType == otherType) &&
(resultType->GetUnderlyingType() == mModule->GetPrimitiveType(BfTypeCode_Char8)))
{
AddStrings(leftValue, rightValue, opToken);
return;
}
//TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types //TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types
if (binaryOp == BfBinaryOp_Subtract) if (binaryOp == BfBinaryOp_Subtract)
{ {
@ -17993,17 +18024,24 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
return; return;
} }
if ((resultType->IsFunction()) || (resultType->IsPointer()) || (resultType->IsObject()) || (resultType->IsInterface()) || (resultType->IsGenericParam())) if ((resultType->IsFunction()) || (resultType->IsPointer()) || (resultType->IsObject()) || (resultType->IsInterface()) || (resultType->IsGenericParam()))
{ {
//if ((resultType->IsFunction()) || (resultType->IsObject()) || (resultType->IsInterface()) || (resultType->IsGenericParam())) if ((binaryOp == BfBinaryOp_Add) &&
(resultType->IsInstanceOf(mModule->mCompiler->mStringTypeDef)) &&
(otherType->IsInstanceOf(mModule->mCompiler->mStringTypeDef)))
{ {
AddStrings(leftValue, rightValue, opToken);
return;
}
if ((binaryOp != BfBinaryOp_Equality) && (binaryOp != BfBinaryOp_InEquality)) if ((binaryOp != BfBinaryOp_Equality) && (binaryOp != BfBinaryOp_InEquality))
{ {
//mModule->Fail("Invalid operation for objects", opToken); //mModule->Fail("Invalid operation for objects", opToken);
_OpFail(); _OpFail();
return; return;
} }
}
if (resultType->IsInterface()) if (resultType->IsInterface())
{ {

View file

@ -346,6 +346,7 @@ public:
void LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError); void LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError);
void LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreIdentifierNotFoundError); void LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreIdentifierNotFoundError);
bool CheckConstCompare(BfBinaryOp binaryOp, BfAstNode* opToken, const BfTypedValue& leftValue, const BfTypedValue& rightValue); bool CheckConstCompare(BfBinaryOp binaryOp, BfAstNode* opToken, const BfTypedValue& leftValue, const BfTypedValue& rightValue);
void AddStrings(const BfTypedValue& leftValue, const BfTypedValue& rightValue, BfAstNode* refNode);
void PerformBinaryOperation(BfType* resultType, BfIRValue convLeftValue, BfIRValue convRightValue, BfBinaryOp binaryOp, BfAstNode* opToken); void PerformBinaryOperation(BfType* resultType, BfIRValue convLeftValue, BfIRValue convRightValue, BfBinaryOp binaryOp, BfAstNode* opToken);
void PerformBinaryOperation(BfAstNode* leftExpression, BfAstNode* rightExpression, BfBinaryOp binaryOp, BfAstNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue, BfTypedValue rightValue); void PerformBinaryOperation(BfAstNode* leftExpression, BfAstNode* rightExpression, BfBinaryOp binaryOp, BfAstNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue, BfTypedValue rightValue);
void PerformBinaryOperation(BfExpression* leftNode, BfExpression* rightNode, BfBinaryOp binaryOp, BfTokenNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue); void PerformBinaryOperation(BfExpression* leftNode, BfExpression* rightNode, BfBinaryOp binaryOp, BfTokenNode* opToken, BfBinOpFlags flags, BfTypedValue leftValue);

View file

@ -1736,10 +1736,16 @@ void BfIRBuilder::Write(BfTypeCode typeCode)
mStream.Write((uint8)typeCode); mStream.Write((uint8)typeCode);
} }
void BfIRBuilder::Write(BfIRTypeData type) void BfIRBuilder::Write(const BfIRTypeData& type)
{ {
mStream.Write((uint8)type.mKind); mStream.Write((uint8)type.mKind);
if (type.mKind != BfIRTypeData::TypeKind_None) if (type.mKind == BfIRTypeData::TypeKind_SizedArray)
{
auto sizedArrayType = (BfConstantSizedArrayType*)GetConstantById(type.mId);
Write(sizedArrayType->mType);
WriteSLEB128(sizedArrayType->mLength);
}
else if (type.mKind != BfIRTypeData::TypeKind_None)
WriteSLEB128(type.mId); WriteSLEB128(type.mId);
} }
@ -2423,6 +2429,12 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
staticValue = ConstToMemory(staticValue); staticValue = ConstToMemory(staticValue);
wasMadeAddr = true; wasMadeAddr = true;
} }
else if (resolvedFieldType->IsPointer())
{
int stringId = constant->mInt32;
const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString;
staticValue = mModule->GetStringCharPtr(str);
}
else else
{ {
int stringId = constant->mInt32; int stringId = constant->mInt32;
@ -3259,11 +3271,28 @@ BfIRType BfIRBuilder::GetPointerTo(BfIRType type)
} }
BfIRType BfIRBuilder::GetSizedArrayType(BfIRType elementType, int length) BfIRType BfIRBuilder::GetSizedArrayType(BfIRType elementType, int length)
{
if (mIgnoreWrites)
{
auto constSizedArrayType = mTempAlloc.Alloc<BfConstantSizedArrayType>();
constSizedArrayType->mConstType = BfConstType_SizedArrayType;
constSizedArrayType->mType = elementType;
constSizedArrayType->mLength = length;
int chunkId = mTempAlloc.GetChunkedId(constSizedArrayType);
BfIRType retType;
retType.mKind = BfIRTypeData::TypeKind_SizedArray;
retType.mId = chunkId;
return retType;
}
else
{ {
BfIRType retType = WriteCmd(BfIRCmd_GetSizedArrayType, elementType, length); BfIRType retType = WriteCmd(BfIRCmd_GetSizedArrayType, elementType, length);
NEW_CMD_INSERTED_IRTYPE; NEW_CMD_INSERTED_IRTYPE;
return retType; return retType;
} }
}
BfIRValue BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values) BfIRValue BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values)
{ {

View file

@ -125,7 +125,8 @@ enum BfConstType
BfConstType_TypeOf, BfConstType_TypeOf,
BfConstType_AggZero, BfConstType_AggZero,
BfConstType_Array, BfConstType_Array,
BfConstType_Undef BfConstType_Undef,
BfConstType_SizedArrayType
}; };
@ -543,6 +544,7 @@ struct BfIRTypeData
TypeKind_TypeInstId, TypeKind_TypeInstId,
TypeKind_TypeInstPtrId, TypeKind_TypeInstPtrId,
TypeKind_Stream, TypeKind_Stream,
TypeKind_SizedArray
}; };
TypeKind mKind; TypeKind mKind;
@ -766,6 +768,13 @@ public:
} }
}; };
struct BfConstantSizedArrayType
{
BfConstType mConstType;
BfIRType mType;
intptr mLength;
};
struct BfConstantUndef struct BfConstantUndef
{ {
BfConstType mConstType; BfConstType mConstType;
@ -896,7 +905,7 @@ public:
void Write(const StringImpl& str); void Write(const StringImpl& str);
void Write(const BfIRValue& irValue); void Write(const BfIRValue& irValue);
void Write(BfTypeCode typeCode); void Write(BfTypeCode typeCode);
void Write(BfIRTypeData type); void Write(const BfIRTypeData& type);
void Write(BfIRFunctionType func); void Write(BfIRFunctionType func);
void Write(BfIRFunction funcType); void Write(BfIRFunction funcType);
void Write(BfIRBlock block); void Write(BfIRBlock block);

View file

@ -510,6 +510,14 @@ void BfIRCodeGen::Read(llvm::Type*& llvmType)
return; return;
} }
if (typeKind == BfIRType::TypeKind::TypeKind_SizedArray)
{
CMD_PARAM(llvm::Type*, elementType);
CMD_PARAM(int, length);
llvmType = llvm::ArrayType::get(elementType, length);
return;
}
int typeId = (int)ReadSLEB128(); int typeId = (int)ReadSLEB128();
auto& typeEntry = GetTypeEntry(typeId); auto& typeEntry = GetTypeEntry(typeId);
if (typeKind == BfIRType::TypeKind::TypeKind_TypeId) if (typeKind == BfIRType::TypeKind::TypeKind_TypeId)

View file

@ -1442,19 +1442,15 @@ BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, boo
{ {
String stringDataName = StrFormat("__bfStrData%d", stringId); String stringDataName = StrFormat("__bfStrData%d", stringId);
BfIRType strCharType; auto charType = GetPrimitiveType(BfTypeCode_Char8);
// BfIRType irStrCharType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(charType), (int)str.length() + 1);
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites);
strCharType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)str.length() + 1);
}
BfIRValue strConstant; BfIRValue strConstant;
if (define) if (define)
{ {
strConstant = mBfIRBuilder->CreateConstString(str); strConstant = mBfIRBuilder->CreateConstString(str);
} }
BfIRValue gv = mBfIRBuilder->CreateGlobalVariable(strCharType, BfIRValue gv = mBfIRBuilder->CreateGlobalVariable(irStrCharType,
true, BfIRLinkageType_External, true, BfIRLinkageType_External,
strConstant, stringDataName); strConstant, stringDataName);
@ -1502,6 +1498,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
stringValData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams); stringValData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams);
} }
mBfIRBuilder->PopulateType(stringTypeInst);
auto stringValLiteral = mBfIRBuilder->CreateGlobalVariable( auto stringValLiteral = mBfIRBuilder->CreateGlobalVariable(
mBfIRBuilder->MapTypeInst(stringTypeInst), mBfIRBuilder->MapTypeInst(stringTypeInst),
true, true,
@ -3283,8 +3280,6 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL); SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
BfConstResolver constResolver(this);
BfMethodState methodState; BfMethodState methodState;
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState); SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
methodState.mTempKind = BfMethodState::TempKind_Static; methodState.mTempKind = BfMethodState::TempKind_Static;

View file

@ -413,6 +413,7 @@ public:
int GetStride() { return BF_ALIGN(mSize, mAlign); } int GetStride() { return BF_ALIGN(mSize, mAlign); }
bool IsSizeAligned() { return (mSize == 0) || (mSize % mAlign == 0); } bool IsSizeAligned() { return (mSize == 0) || (mSize % mAlign == 0); }
virtual bool NeedsExplicitAlignment() { return !IsSizeAligned(); } virtual bool NeedsExplicitAlignment() { return !IsSizeAligned(); }
virtual bool IsInstanceOf(BfTypeDef* typeDef) { return false; }
virtual bool HasBeenReferenced() { return mDefineState != BfTypeDefineState_Undefined; } virtual bool HasBeenReferenced() { return mDefineState != BfTypeDefineState_Undefined; }
virtual bool HasTypeFailed() { return false; } virtual bool HasTypeFailed() { return false; }
@ -1671,6 +1672,7 @@ public:
~BfTypeInstance(); ~BfTypeInstance();
virtual bool IsInstanceOf(BfTypeDef* typeDef) { return typeDef == mTypeDef; }
virtual BfModule* GetModule() override { return mModule; } virtual BfModule* GetModule() override { return mModule; }
virtual BfTypeInstance* ToTypeInstance() override { return this; } virtual BfTypeInstance* ToTypeInstance() override { return this; }
virtual bool IsDependentOnUnderlyingType() override { return true; } virtual bool IsDependentOnUnderlyingType() override { return true; }

View file

@ -1479,7 +1479,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
if (isConst) if (isConst)
{ {
BfConstResolver constResolver(this); BfConstResolver constResolver(this);
initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType); initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_RemapFromStringId);
if (!initValue) if (!initValue)
initValue = GetDefaultTypedValue(resolvedType); initValue = GetDefaultTypedValue(resolvedType);
} }

View file

@ -240,5 +240,20 @@ namespace Tests
Test.Assert(iVal == 123); Test.Assert(iVal == 123);
Test.Assert(iVal == 123.0f); Test.Assert(iVal == 123.0f);
} }
const String cStrD = "D";
const char8* cStrPD = "D";
[Test]
public static void TestStringOp()
{
const String cStr1 = "A" + "B";
const String cStr2 = cStr1 + "C" + cStrD;
Test.Assert(cStr2 == "ABCD");
const char8* cStr3 = "A" + "B";
const char8* cStr4 = cStr1 + "C" + cStrPD;
Test.Assert(StringView(cStr4) == "ABCD");
}
} }
} }