mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Added constant string appending with + operator, const string fixes
This commit is contained in:
parent
41cb0052b2
commit
c92bc523db
14 changed files with 158 additions and 34 deletions
|
@ -1247,7 +1247,7 @@ void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgV
|
|||
{
|
||||
if (auto beConst = BeValueDynCast<BeConstant>(dbgVar->mValue))
|
||||
{
|
||||
if (!beConst->mType->IsPointer())
|
||||
if ((beConst->mType != NULL) && (!beConst->mType->IsPointer()))
|
||||
{
|
||||
int64 writeVal = beConst->mInt64;
|
||||
if (beConst->mType->mTypeCode == BfTypeCode_Single)
|
||||
|
|
|
@ -170,6 +170,14 @@ bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
|
|||
return true;
|
||||
case BeTypeCode_Pointer:
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -561,6 +561,14 @@ void BeIRCodeGen::Read(BeType*& beType)
|
|||
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();
|
||||
auto& typeEntry = GetTypeEntry(typeId);
|
||||
if (typeKind == BfIRType::TypeKind::TypeKind_TypeId)
|
||||
|
@ -1631,6 +1639,7 @@ void BeIRCodeGen::HandleNextCmd()
|
|||
{
|
||||
globalVariable->mAlign = varType->mAlign;
|
||||
BF_ASSERT(varType->mAlign > 0);
|
||||
BF_ASSERT(mBeContext->AreTypesEqual(varType, initializer->GetType()));
|
||||
}
|
||||
else
|
||||
globalVariable->mAlign = -1;
|
||||
|
|
|
@ -74,6 +74,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
|
|||
(toType == mResult.mType)))
|
||||
{
|
||||
auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
|
||||
|
||||
if (constant->mTypeCode == BfTypeCode_NullPtr)
|
||||
{
|
||||
return mModule->GetDefaultTypedValue(toType);
|
||||
|
@ -82,7 +83,15 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
|
|||
{
|
||||
int stringId = mModule->GetStringPoolIdx(mResult.mValue);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ enum BfConstResolveFlags
|
|||
BfConstResolveFlag_ExplicitCast = 1,
|
||||
BfConstResolveFlag_NoCast = 2,
|
||||
BfConstResolveFlag_AllowSoftFail = 4,
|
||||
BfConstResolveFlag_RemapFromStringId = 8
|
||||
};
|
||||
|
||||
class BfConstResolver : public BfExprEvaluator
|
||||
|
|
|
@ -17351,6 +17351,30 @@ bool BfExprEvaluator::CheckConstCompare(BfBinaryOp binaryOp, BfAstNode* opToken,
|
|||
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)
|
||||
{
|
||||
bool noClassify = (flags & BfBinOpFlag_NoClassify) != 0;
|
||||
|
@ -17905,6 +17929,13 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
|
||||
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
|
||||
if (binaryOp == BfBinaryOp_Subtract)
|
||||
{
|
||||
|
@ -17993,17 +18024,24 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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))
|
||||
{
|
||||
//mModule->Fail("Invalid operation for objects", opToken);
|
||||
_OpFail();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (resultType->IsInterface())
|
||||
{
|
||||
|
|
|
@ -346,6 +346,7 @@ public:
|
|||
void LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError);
|
||||
void LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreIdentifierNotFoundError);
|
||||
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(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);
|
||||
|
|
|
@ -1736,10 +1736,16 @@ void BfIRBuilder::Write(BfTypeCode typeCode)
|
|||
mStream.Write((uint8)typeCode);
|
||||
}
|
||||
|
||||
void BfIRBuilder::Write(BfIRTypeData type)
|
||||
void BfIRBuilder::Write(const BfIRTypeData& type)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2423,6 +2429,12 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
|
|||
staticValue = ConstToMemory(staticValue);
|
||||
wasMadeAddr = true;
|
||||
}
|
||||
else if (resolvedFieldType->IsPointer())
|
||||
{
|
||||
int stringId = constant->mInt32;
|
||||
const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString;
|
||||
staticValue = mModule->GetStringCharPtr(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
int stringId = constant->mInt32;
|
||||
|
@ -3260,9 +3272,26 @@ BfIRType BfIRBuilder::GetPointerTo(BfIRType type)
|
|||
|
||||
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);
|
||||
NEW_CMD_INSERTED_IRTYPE;
|
||||
return retType;
|
||||
}
|
||||
}
|
||||
|
||||
BfIRValue BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values)
|
||||
|
|
|
@ -125,7 +125,8 @@ enum BfConstType
|
|||
BfConstType_TypeOf,
|
||||
BfConstType_AggZero,
|
||||
BfConstType_Array,
|
||||
BfConstType_Undef
|
||||
BfConstType_Undef,
|
||||
BfConstType_SizedArrayType
|
||||
|
||||
};
|
||||
|
||||
|
@ -543,6 +544,7 @@ struct BfIRTypeData
|
|||
TypeKind_TypeInstId,
|
||||
TypeKind_TypeInstPtrId,
|
||||
TypeKind_Stream,
|
||||
TypeKind_SizedArray
|
||||
};
|
||||
|
||||
TypeKind mKind;
|
||||
|
@ -766,6 +768,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct BfConstantSizedArrayType
|
||||
{
|
||||
BfConstType mConstType;
|
||||
BfIRType mType;
|
||||
intptr mLength;
|
||||
};
|
||||
|
||||
struct BfConstantUndef
|
||||
{
|
||||
BfConstType mConstType;
|
||||
|
@ -896,7 +905,7 @@ public:
|
|||
void Write(const StringImpl& str);
|
||||
void Write(const BfIRValue& irValue);
|
||||
void Write(BfTypeCode typeCode);
|
||||
void Write(BfIRTypeData type);
|
||||
void Write(const BfIRTypeData& type);
|
||||
void Write(BfIRFunctionType func);
|
||||
void Write(BfIRFunction funcType);
|
||||
void Write(BfIRBlock block);
|
||||
|
|
|
@ -510,6 +510,14 @@ void BfIRCodeGen::Read(llvm::Type*& llvmType)
|
|||
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();
|
||||
auto& typeEntry = GetTypeEntry(typeId);
|
||||
if (typeKind == BfIRType::TypeKind::TypeKind_TypeId)
|
||||
|
|
|
@ -1442,19 +1442,15 @@ BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, boo
|
|||
{
|
||||
String stringDataName = StrFormat("__bfStrData%d", stringId);
|
||||
|
||||
BfIRType strCharType;
|
||||
//
|
||||
{
|
||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites);
|
||||
strCharType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)str.length() + 1);
|
||||
}
|
||||
auto charType = GetPrimitiveType(BfTypeCode_Char8);
|
||||
BfIRType irStrCharType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(charType), (int)str.length() + 1);
|
||||
|
||||
BfIRValue strConstant;
|
||||
if (define)
|
||||
{
|
||||
strConstant = mBfIRBuilder->CreateConstString(str);
|
||||
}
|
||||
BfIRValue gv = mBfIRBuilder->CreateGlobalVariable(strCharType,
|
||||
BfIRValue gv = mBfIRBuilder->CreateGlobalVariable(irStrCharType,
|
||||
true, BfIRLinkageType_External,
|
||||
strConstant, stringDataName);
|
||||
|
||||
|
@ -1502,6 +1498,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
|
|||
stringValData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams);
|
||||
}
|
||||
|
||||
mBfIRBuilder->PopulateType(stringTypeInst);
|
||||
auto stringValLiteral = mBfIRBuilder->CreateGlobalVariable(
|
||||
mBfIRBuilder->MapTypeInst(stringTypeInst),
|
||||
true,
|
||||
|
@ -3283,8 +3280,6 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
|
|||
SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
|
||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
||||
|
||||
BfConstResolver constResolver(this);
|
||||
|
||||
BfMethodState methodState;
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
|
||||
methodState.mTempKind = BfMethodState::TempKind_Static;
|
||||
|
|
|
@ -413,6 +413,7 @@ public:
|
|||
int GetStride() { return BF_ALIGN(mSize, mAlign); }
|
||||
bool IsSizeAligned() { return (mSize == 0) || (mSize % mAlign == 0); }
|
||||
virtual bool NeedsExplicitAlignment() { return !IsSizeAligned(); }
|
||||
virtual bool IsInstanceOf(BfTypeDef* typeDef) { return false; }
|
||||
|
||||
virtual bool HasBeenReferenced() { return mDefineState != BfTypeDefineState_Undefined; }
|
||||
virtual bool HasTypeFailed() { return false; }
|
||||
|
@ -1671,6 +1672,7 @@ public:
|
|||
|
||||
~BfTypeInstance();
|
||||
|
||||
virtual bool IsInstanceOf(BfTypeDef* typeDef) { return typeDef == mTypeDef; }
|
||||
virtual BfModule* GetModule() override { return mModule; }
|
||||
virtual BfTypeInstance* ToTypeInstance() override { return this; }
|
||||
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
||||
|
|
|
@ -1479,7 +1479,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
if (isConst)
|
||||
{
|
||||
BfConstResolver constResolver(this);
|
||||
initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType);
|
||||
initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_RemapFromStringId);
|
||||
if (!initValue)
|
||||
initValue = GetDefaultTypedValue(resolvedType);
|
||||
}
|
||||
|
|
|
@ -240,5 +240,20 @@ namespace Tests
|
|||
Test.Assert(iVal == 123);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue