From c92bc523db3178a0834ae7c4794e1cd43c3afc27 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 28 Feb 2020 09:20:43 -0800 Subject: [PATCH] Added constant string appending with + operator, const string fixes --- IDEHelper/Backend/BeCOFFObject.cpp | 2 +- IDEHelper/Backend/BeContext.cpp | 8 ++++ IDEHelper/Backend/BeIRCodeGen.cpp | 11 ++++- IDEHelper/Compiler/BfConstResolver.cpp | 15 +++++-- IDEHelper/Compiler/BfConstResolver.h | 1 + IDEHelper/Compiler/BfExprEvaluator.cpp | 52 ++++++++++++++++++++---- IDEHelper/Compiler/BfExprEvaluator.h | 1 + IDEHelper/Compiler/BfIRBuilder.cpp | 39 +++++++++++++++--- IDEHelper/Compiler/BfIRBuilder.h | 15 +++++-- IDEHelper/Compiler/BfIRCodeGen.cpp | 8 ++++ IDEHelper/Compiler/BfModule.cpp | 17 +++----- IDEHelper/Compiler/BfResolvedTypeUtils.h | 4 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 4 +- IDEHelper/Tests/src/Operators.bf | 15 +++++++ 14 files changed, 158 insertions(+), 34 deletions(-) diff --git a/IDEHelper/Backend/BeCOFFObject.cpp b/IDEHelper/Backend/BeCOFFObject.cpp index 935b8b8c..2a8da92f 100644 --- a/IDEHelper/Backend/BeCOFFObject.cpp +++ b/IDEHelper/Backend/BeCOFFObject.cpp @@ -1247,7 +1247,7 @@ void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgV { if (auto beConst = BeValueDynCast(dbgVar->mValue)) { - if (!beConst->mType->IsPointer()) + if ((beConst->mType != NULL) && (!beConst->mType->IsPointer())) { int64 writeVal = beConst->mInt64; if (beConst->mType->mTypeCode == BfTypeCode_Single) diff --git a/IDEHelper/Backend/BeContext.cpp b/IDEHelper/Backend/BeContext.cpp index 696de679..0842c431 100644 --- a/IDEHelper/Backend/BeContext.cpp +++ b/IDEHelper/Backend/BeContext.cpp @@ -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; } diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 841747be..575ec538 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -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,9 +1639,10 @@ void BeIRCodeGen::HandleNextCmd() { globalVariable->mAlign = varType->mAlign; BF_ASSERT(varType->mAlign > 0); + BF_ASSERT(mBeContext->AreTypesEqual(varType, initializer->GetType())); } else - globalVariable->mAlign = -1; + globalVariable->mAlign = -1; SetResult(curId, globalVariable); } diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 67467965..85352380 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -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); } } } @@ -168,7 +177,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo mModule->mBfIRBuilder->SetInsertPoint(prevInsertBlock); }*/ - mModule->FixIntUnknown(mResult); + mModule->FixIntUnknown(mResult); return mResult; } @@ -360,7 +369,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch auto arrayType = mModule->mBfIRBuilder->GetSizedArrayType(mModule->mBfIRBuilder->MapType(expandedParamsElementType), (int)expandedParamsConstValues.size()); auto constArray = mModule->mBfIRBuilder->CreateConstArray(arrayType, expandedParamsConstValues); llvmArgs.push_back(constArray); - } + } return true; } \ No newline at end of file diff --git a/IDEHelper/Compiler/BfConstResolver.h b/IDEHelper/Compiler/BfConstResolver.h index 6615d0b9..0c0cbc2d 100644 --- a/IDEHelper/Compiler/BfConstResolver.h +++ b/IDEHelper/Compiler/BfConstResolver.h @@ -15,6 +15,7 @@ enum BfConstResolveFlags BfConstResolveFlag_ExplicitCast = 1, BfConstResolveFlag_NoCast = 2, BfConstResolveFlag_AllowSoftFail = 4, + BfConstResolveFlag_RemapFromStringId = 8 }; class BfConstResolver : public BfExprEvaluator diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 1303712a..4f6bb4de 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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))) { - if ((binaryOp != BfBinaryOp_Equality) && (binaryOp != BfBinaryOp_InEquality)) - { - //mModule->Fail("Invalid operation for objects", opToken); - _OpFail(); - return; - } + AddStrings(leftValue, rightValue, opToken); + return; } + + if ((binaryOp != BfBinaryOp_Equality) && (binaryOp != BfBinaryOp_InEquality)) + { + //mModule->Fail("Invalid operation for objects", opToken); + _OpFail(); + return; + } if (resultType->IsInterface()) { diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 7f4faba0..4918d570 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -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); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 5e9fd064..d6392e74 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -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) { - BfIRType retType = WriteCmd(BfIRCmd_GetSizedArrayType, elementType, length); - NEW_CMD_INSERTED_IRTYPE; - return retType; + if (mIgnoreWrites) + { + auto constSizedArrayType = mTempAlloc.Alloc(); + 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& values) diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index 562a2a5c..610b4fd1 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -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; @@ -894,9 +903,9 @@ public: void Write(int val); void Write(int64 val); void Write(const StringImpl& str); - void Write(const BfIRValue& irValue); + 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); diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 9fb721b7..40f410e0 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -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) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 41f0988b..c4fa885b 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1442,19 +1442,15 @@ BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, boo { String stringDataName = StrFormat("__bfStrData%d", stringId); - BfIRType strCharType; - // - { - SetAndRestoreValue 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); @@ -1501,7 +1497,8 @@ 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 prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue prevMethodInstance(mCurMethodInstance, NULL); - BfConstResolver constResolver(this); - BfMethodState methodState; SetAndRestoreValue prevMethodState(mCurMethodState, &methodState); methodState.mTempKind = BfMethodState::TempKind_Static; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index ec6445f8..e35b0d05 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -409,10 +409,11 @@ public: BfTypeInstance* FindUnderlyingTypeInstance(); virtual BfModule* GetModule(); - + 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; } diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 98cbabfa..eb841d85 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -1479,9 +1479,9 @@ 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); + initValue = GetDefaultTypedValue(resolvedType); } else if (varDecl->mInitializer->IsA()) { diff --git a/IDEHelper/Tests/src/Operators.bf b/IDEHelper/Tests/src/Operators.bf index bb4ffb8e..6c3dbd53 100644 --- a/IDEHelper/Tests/src/Operators.bf +++ b/IDEHelper/Tests/src/Operators.bf @@ -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"); + } } }