mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-04 15:26:00 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
2503
IDEHelper/Backend/BeCOFFObject.cpp
Normal file
2503
IDEHelper/Backend/BeCOFFObject.cpp
Normal file
File diff suppressed because it is too large
Load diff
289
IDEHelper/Backend/BeCOFFObject.h
Normal file
289
IDEHelper/Backend/BeCOFFObject.h
Normal file
|
@ -0,0 +1,289 @@
|
|||
#pragma once
|
||||
|
||||
#include "BeMCContext.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "../Compiler/BfCodeGen.h"
|
||||
#include "BeefySysLib/MemStream.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
enum BeMCSymbolKind
|
||||
{
|
||||
BeMCSymbolKind_AuxPlaceholder,
|
||||
BeMCSymbolKind_SectionDef,
|
||||
BeMCSymbolKind_SectionCOFFDef,
|
||||
BeMCSymbolKind_SectionRef,
|
||||
BeMCSymbolKind_External,
|
||||
BeMCSymbolKind_Function,
|
||||
BeMCSymbolKind_COMDAT
|
||||
};
|
||||
|
||||
class BeMCSymbol
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
BeType* mType;
|
||||
bool mIsStatic;
|
||||
bool mIsTLS;
|
||||
BeMCSymbolKind mSymKind;
|
||||
int mValue;
|
||||
int mIdx;
|
||||
int mSectionNum;
|
||||
|
||||
BeFunction* mBeFunction;
|
||||
|
||||
public:
|
||||
BeMCSymbol()
|
||||
{
|
||||
mType = NULL;
|
||||
mIsStatic = false;
|
||||
mIsTLS = false;
|
||||
mSymKind = BeMCSymbolKind_External;
|
||||
mValue = 0;
|
||||
mIdx = -1;
|
||||
mSectionNum = 0;
|
||||
|
||||
mBeFunction = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
enum BeMCRelocationKind
|
||||
{
|
||||
BeMCRelocationKind_NONE,
|
||||
BeMCRelocationKind_ADDR32NB,
|
||||
BeMCRelocationKind_ADDR64,
|
||||
BeMCRelocationKind_REL32,
|
||||
BeMCRelocationKind_SECREL,
|
||||
BeMCRelocationKind_SECTION,
|
||||
};
|
||||
|
||||
class BeMCRelocation
|
||||
{
|
||||
public:
|
||||
BeMCRelocationKind mKind;
|
||||
int mOffset;
|
||||
int mSymTableIdx;
|
||||
};
|
||||
|
||||
class BeCOFFSection
|
||||
{
|
||||
public:
|
||||
DynMemStream mData;
|
||||
Array<BeMCRelocation> mRelocs;
|
||||
int mSymbolIdx;
|
||||
int mSectionIdx;
|
||||
String mSectName;
|
||||
int mCharacteristics;
|
||||
int mSizeOverride;
|
||||
int mAlign;
|
||||
|
||||
public:
|
||||
BeCOFFSection()
|
||||
{
|
||||
mSymbolIdx = -1;
|
||||
mSectionIdx = -1;
|
||||
mCharacteristics = 0;
|
||||
mSizeOverride = 0;
|
||||
mAlign = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BeInlineLineBuilder
|
||||
{
|
||||
public:
|
||||
Array<uint8> mData;
|
||||
int mCurLine;
|
||||
int mCurCodePos;
|
||||
BeDbgLoc* mStartDbgLoc;
|
||||
bool mEnded;
|
||||
Array<BeDbgVariable*> mVariables;
|
||||
|
||||
public:
|
||||
BeInlineLineBuilder();
|
||||
|
||||
void Compress(int val);
|
||||
void WriteSigned(int val);
|
||||
void Update(BeDbgCodeEmission* codeEmission);
|
||||
void Start(BeDbgCodeEmission* codeEmission);
|
||||
void End(BeDbgCodeEmission* codeEmission);
|
||||
};
|
||||
|
||||
struct COFFArgListRef
|
||||
{
|
||||
public:
|
||||
BeDbgFunction* mFunc;
|
||||
|
||||
COFFArgListRef()
|
||||
{
|
||||
mFunc = NULL;
|
||||
}
|
||||
|
||||
COFFArgListRef(BeDbgFunction* func)
|
||||
{
|
||||
mFunc = func;
|
||||
}
|
||||
|
||||
bool operator==(const COFFArgListRef& rhsRef) const
|
||||
{
|
||||
auto lhs = mFunc;
|
||||
auto rhs = rhsRef.mFunc;
|
||||
|
||||
int lhsParamOfs = lhs->HasThis() ? 1 : 0;
|
||||
int rhsParamOfs = rhs->HasThis() ? 1 : 0;
|
||||
if (lhs->mType->mParams.size() - lhsParamOfs != rhs->mType->mParams.size() - rhsParamOfs)
|
||||
return false;
|
||||
for (int i = 0; i < (int)lhs->mType->mParams.size() - lhsParamOfs; i++)
|
||||
if (lhs->mType->mParams[i + lhsParamOfs] != rhs->mType->mParams[i + rhsParamOfs])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct COFFFuncTypeRef
|
||||
{
|
||||
public:
|
||||
BeDbgFunction* mFunc;
|
||||
|
||||
COFFFuncTypeRef()
|
||||
{
|
||||
mFunc = NULL;
|
||||
}
|
||||
|
||||
COFFFuncTypeRef(BeDbgFunction* func)
|
||||
{
|
||||
mFunc = func;
|
||||
}
|
||||
|
||||
bool operator==(const COFFFuncTypeRef& rhsRef) const
|
||||
{
|
||||
auto lhs = mFunc;
|
||||
auto rhs = rhsRef.mFunc;
|
||||
|
||||
if (lhs->mIsStaticMethod != rhs->mIsStaticMethod)
|
||||
return false;
|
||||
if (lhs->mScope != rhs->mScope)
|
||||
return false;
|
||||
if (lhs->mType->mReturnType != rhs->mType->mReturnType)
|
||||
return false;
|
||||
if (lhs->mType->mParams.size() != rhs->mType->mParams.size())
|
||||
return false;
|
||||
for (int i = 0; i < (int)lhs->mType->mParams.size(); i++)
|
||||
if (lhs->mType->mParams[i] != rhs->mType->mParams[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
NS_BF_END;
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Beefy::COFFArgListRef>
|
||||
{
|
||||
size_t operator()(const Beefy::COFFArgListRef& val)
|
||||
{
|
||||
auto func = val.mFunc;
|
||||
intptr curHash = 0;
|
||||
for (int paramIdx = func->HasThis() ? 1 : 0; paramIdx < (int)func->mType->mParams.size(); paramIdx++)
|
||||
curHash = Beefy::Hash64((intptr)func->mType->mParams[paramIdx], curHash);
|
||||
return curHash;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<Beefy::COFFFuncTypeRef>
|
||||
{
|
||||
size_t operator()(const Beefy::COFFFuncTypeRef& val)
|
||||
{
|
||||
auto func = val.mFunc;
|
||||
intptr curHash = (intptr)func->mType->mReturnType;
|
||||
for (int paramIdx = 0; paramIdx < (int)func->mType->mParams.size(); paramIdx++)
|
||||
curHash = Beefy::Hash64((intptr)func->mType->mParams[paramIdx], curHash);
|
||||
return curHash;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NS_BF_BEGIN;
|
||||
|
||||
class BeCOFFObject
|
||||
{
|
||||
public:
|
||||
bool mWriteToLib;
|
||||
|
||||
PerfManager* mPerfManager;
|
||||
DataStream* mStream;
|
||||
BumpAllocator mAlloc;
|
||||
BeModule* mBeModule;
|
||||
OwnedVector<BeMCSymbol> mSymbols;
|
||||
OwnedVector<BeCOFFSection> mDynSects;
|
||||
uint32 mTimestamp;
|
||||
|
||||
BeCOFFSection mTextSect;
|
||||
BeCOFFSection mDataSect;
|
||||
BeCOFFSection mRDataSect;
|
||||
BeCOFFSection mBSSSect;
|
||||
BeCOFFSection mTLSSect;
|
||||
BeCOFFSection mPDataSect;
|
||||
BeCOFFSection mXDataSect;
|
||||
BeCOFFSection mDebugSSect;
|
||||
BeCOFFSection mDebugTSect;
|
||||
DynMemStream mStrTable;
|
||||
int mBSSPos;
|
||||
Array<BeCOFFSection*> mUsedSections;
|
||||
Dictionary<BeValue*, BeMCSymbol*> mSymbolMap;
|
||||
Dictionary<String, BeMCSymbol*> mNamedSymbolMap;
|
||||
HashSet<COFFArgListRef> mArgListSet;
|
||||
HashSet<COFFFuncTypeRef> mFuncTypeSet;
|
||||
Deque<BeFunction*> mFuncWorkList;
|
||||
int mTTagStartPos;
|
||||
int mSTagStartPos;
|
||||
int mCurTagId;
|
||||
int mSectionStartPos;
|
||||
int mCurStringId;
|
||||
int mCurJumpTableIdx;
|
||||
bool mTypesLocked;
|
||||
|
||||
public:
|
||||
void ToString(BeMDNode* mdNode, String& str);
|
||||
int GetCVRegNum(X64CPURegister reg, int bits);
|
||||
|
||||
void DbgTAlign();
|
||||
void DbgTStartTag();
|
||||
void DbgTEndTag();
|
||||
void DbgEncodeConstant(DynMemStream& memStream, int64 val);
|
||||
void DbgEncodeString(DynMemStream& memStream, const StringImpl& str);
|
||||
void DbgMakeFuncType(BeDbgFunction* dbgFunc);
|
||||
void DbgMakeFunc(BeDbgFunction* dbgFunc);
|
||||
int DbgGetTypeId(BeDbgType* dbgType, bool doDefine = false);
|
||||
void DbgGenerateTypeInfo();
|
||||
|
||||
void DbgSAlign();
|
||||
void DbgSStartTag();
|
||||
void DbgSEndTag();
|
||||
void DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgVar);
|
||||
void DbgOutputLocalVars(BeInlineLineBuilder* curInlineBuilder, BeDbgFunction* func);
|
||||
void DbgStartSection(int sectionNum);
|
||||
void DbgEndSection();
|
||||
void DbgStartVarDefRange(BeDbgFunction* dbgFunc, BeDbgVariable* dbgVar, const BeDbgVariableLoc& varLoc, int offset, int range);
|
||||
void DbgEndLineBlock(BeDbgFunction* dbgFunc, const Array<BeDbgCodeEmission>& emissions, int blockStartPos, int emissionStartIdx, int lineCount);
|
||||
void DbgGenerateModuleInfo();
|
||||
void InitSect(BeCOFFSection& sect, const StringImpl& name, int characteristics, bool addNow, bool makeSectSymbol);
|
||||
void WriteConst(BeCOFFSection& sect, BeConstant* constVal);
|
||||
|
||||
void Generate(BeModule* module);
|
||||
|
||||
public:
|
||||
BeCOFFObject();
|
||||
void Finish();
|
||||
|
||||
bool Generate(BeModule* module, const StringImpl& fileName);
|
||||
BeMCSymbol* GetSymbol(BeValue* value, bool allowCreate = true);
|
||||
BeMCSymbol* GetSymbolRef(const StringImpl& name);
|
||||
void MarkSectionUsed(BeCOFFSection& sect, bool getSectSymbol = false);
|
||||
BeMCSymbol* GetCOMDAT(const StringImpl& name, void* data, int size, int align);
|
||||
BeCOFFSection* CreateSect(const StringImpl& name, int characteristics, bool makeSectSymbol = true);
|
||||
};
|
||||
|
||||
NS_BF_END
|
174
IDEHelper/Backend/BeContext.cpp
Normal file
174
IDEHelper/Backend/BeContext.cpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
#include "BeContext.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
BeContext::BeContext()
|
||||
{
|
||||
mPointerSize = 8;
|
||||
for (int primIdx = 0; primIdx < (int)BeTypeCode_COUNT; primIdx++)
|
||||
mPrimitiveTypes[primIdx] = NULL;
|
||||
}
|
||||
|
||||
void BeContext::NotImpl()
|
||||
{
|
||||
BF_FATAL("Not implemented");
|
||||
}
|
||||
|
||||
BeType* BeContext::GetPrimitiveType(BeTypeCode typeCode)
|
||||
{
|
||||
if (typeCode == BeTypeCode_NullPtr)
|
||||
{
|
||||
return GetPointerTo(GetPrimitiveType(BeTypeCode_None));
|
||||
}
|
||||
|
||||
if (mPrimitiveTypes[(int)typeCode] != NULL)
|
||||
return mPrimitiveTypes[(int)typeCode];
|
||||
|
||||
BeType* primType = mTypes.Alloc<BeType>();
|
||||
primType->mTypeCode = typeCode;
|
||||
switch (typeCode)
|
||||
{
|
||||
case BeTypeCode_None:
|
||||
primType->mSize = 0;
|
||||
primType->mAlign = 0;
|
||||
break;
|
||||
case BeTypeCode_NullPtr:
|
||||
primType->mSize = primType->mAlign = mPointerSize;
|
||||
break;
|
||||
case BeTypeCode_Boolean:
|
||||
primType->mSize = primType->mAlign = 1;
|
||||
break;
|
||||
case BeTypeCode_Int8:
|
||||
primType->mSize = primType->mAlign = 1;
|
||||
break;
|
||||
case BeTypeCode_Int16:
|
||||
primType->mSize = primType->mAlign = 2;
|
||||
break;
|
||||
case BeTypeCode_Int32:
|
||||
primType->mSize = primType->mAlign = 4;
|
||||
break;
|
||||
case BeTypeCode_Int64:
|
||||
primType->mSize = primType->mAlign = 8;
|
||||
break;
|
||||
case BeTypeCode_Float:
|
||||
primType->mSize = primType->mAlign = 4;
|
||||
break;
|
||||
case BeTypeCode_Double:
|
||||
primType->mSize = primType->mAlign = 8;
|
||||
break;
|
||||
}
|
||||
mPrimitiveTypes[(int)typeCode] = primType;
|
||||
return primType;
|
||||
}
|
||||
|
||||
BeStructType* BeContext::CreateStruct(const StringImpl& name)
|
||||
{
|
||||
BeStructType* structType = mTypes.Alloc<BeStructType>();
|
||||
structType->mContext = this;
|
||||
structType->mTypeCode = BeTypeCode_Struct;
|
||||
structType->mName = name;
|
||||
structType->mIsOpaque = true;
|
||||
return structType;
|
||||
}
|
||||
|
||||
BePointerType* BeContext::GetPointerTo(BeType* beType)
|
||||
{
|
||||
if (beType->mPointerType == NULL)
|
||||
{
|
||||
BePointerType* pointerType = mTypes.Alloc<BePointerType>();
|
||||
pointerType->mTypeCode = BeTypeCode_Pointer;
|
||||
pointerType->mElementType = beType;
|
||||
pointerType->mSize = mPointerSize;
|
||||
pointerType->mAlign = mPointerSize;
|
||||
beType->mPointerType = pointerType;
|
||||
|
||||
/*if (beType->IsSizedArray())
|
||||
{
|
||||
auto sizedArrayType = (BeSizedArrayType*)beType;
|
||||
pointerType->mElementType = sizedArrayType->mElementType;
|
||||
}*/
|
||||
}
|
||||
return beType->mPointerType;
|
||||
}
|
||||
|
||||
void BeContext::SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed)
|
||||
{
|
||||
int dataPos = 0;
|
||||
for (auto& beType : types)
|
||||
{
|
||||
if (!packed)
|
||||
{
|
||||
int alignSize = beType->mAlign;
|
||||
dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
|
||||
}
|
||||
BF_ASSERT(beType->mSize >= 0);
|
||||
BeStructMember member;
|
||||
member.mType = beType;
|
||||
member.mByteOffset = dataPos;
|
||||
dataPos += beType->mSize;
|
||||
structType->mAlign = std::max(structType->mAlign, beType->mAlign);
|
||||
structType->mMembers.push_back(member);
|
||||
}
|
||||
if (!packed)
|
||||
{
|
||||
int alignSize = structType->mAlign;
|
||||
dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
|
||||
}
|
||||
structType->mSize = dataPos;
|
||||
structType->mIsPacked = packed;
|
||||
structType->mIsOpaque = false;
|
||||
}
|
||||
|
||||
BeSizedArrayType* BeContext::CreateSizedArrayType(BeType* type, int length)
|
||||
{
|
||||
auto arrayType = mTypes.Alloc<BeSizedArrayType>();
|
||||
arrayType->mContext = this;
|
||||
arrayType->mTypeCode = BeTypeCode_SizedArray;
|
||||
arrayType->mElementType = type;
|
||||
arrayType->mLength = length;
|
||||
arrayType->mSize = type->mSize * length;
|
||||
arrayType->mAlign = type->mAlign;
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
BeFunctionType* BeContext::CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg)
|
||||
{
|
||||
auto funcType = mTypes.Alloc<BeFunctionType>();
|
||||
funcType->mTypeCode = BeTypeCode_Function;
|
||||
funcType->mReturnType = returnType;
|
||||
for (auto& paramType : paramTypes)
|
||||
{
|
||||
BeFunctionTypeParam funcParam;
|
||||
funcParam.mType = paramType;
|
||||
funcType->mParams.push_back(funcParam);
|
||||
}
|
||||
funcType->mIsVarArg = isVarArg;
|
||||
return funcType;
|
||||
}
|
||||
|
||||
bool BeContext::AreTypesEqual(BeType* lhs, BeType* rhs)
|
||||
{
|
||||
if (lhs == rhs)
|
||||
return true;
|
||||
|
||||
if (lhs->mTypeCode != rhs->mTypeCode)
|
||||
return false;
|
||||
|
||||
switch (lhs->mTypeCode)
|
||||
{
|
||||
case BeTypeCode_None:
|
||||
case BeTypeCode_NullPtr:
|
||||
case BeTypeCode_Boolean:
|
||||
case BeTypeCode_Int8:
|
||||
case BeTypeCode_Int16:
|
||||
case BeTypeCode_Int32:
|
||||
case BeTypeCode_Int64:
|
||||
case BeTypeCode_Float:
|
||||
case BeTypeCode_Double:
|
||||
return true;
|
||||
case BeTypeCode_Pointer:
|
||||
return AreTypesEqual(((BePointerType*)lhs)->mElementType, ((BePointerType*)rhs)->mElementType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
245
IDEHelper/Backend/BeContext.h
Normal file
245
IDEHelper/Backend/BeContext.h
Normal file
|
@ -0,0 +1,245 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "../Compiler/BfCompiler.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BePointerType;
|
||||
class BeContext;
|
||||
|
||||
enum BeTypeCode
|
||||
{
|
||||
BeTypeCode_None,
|
||||
BeTypeCode_NullPtr,
|
||||
BeTypeCode_Boolean,
|
||||
BeTypeCode_Int8,
|
||||
BeTypeCode_Int16,
|
||||
BeTypeCode_Int32,
|
||||
BeTypeCode_Int64,
|
||||
BeTypeCode_Float,
|
||||
BeTypeCode_Double,
|
||||
BeTypeCode_Struct,
|
||||
BeTypeCode_Function,
|
||||
BeTypeCode_Pointer,
|
||||
BeTypeCode_SizedArray,
|
||||
BeTypeCode_CmpResult, // Psuedo
|
||||
|
||||
BeTypeCode_COUNT
|
||||
};
|
||||
|
||||
class BeHashContext : public HashContext
|
||||
{
|
||||
public:
|
||||
int mCurHashId;
|
||||
|
||||
BeHashContext()
|
||||
{
|
||||
mCurHashId = 1;
|
||||
}
|
||||
};
|
||||
|
||||
class BeHashble
|
||||
{
|
||||
public:
|
||||
int mHashId;
|
||||
|
||||
BeHashble()
|
||||
{
|
||||
mHashId = -1;
|
||||
}
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx) = 0;
|
||||
|
||||
void HashReference(BeHashContext& hashCtx)
|
||||
{
|
||||
if (mHashId == -1)
|
||||
{
|
||||
mHashId = hashCtx.mCurHashId++;
|
||||
hashCtx.Mixin(mHashId);
|
||||
HashContent(hashCtx);
|
||||
}
|
||||
else
|
||||
hashCtx.Mixin(mHashId);
|
||||
}
|
||||
};
|
||||
|
||||
class BeType : public BeHashble
|
||||
{
|
||||
public:
|
||||
BeTypeCode mTypeCode;
|
||||
BePointerType* mPointerType;
|
||||
int mSize;
|
||||
int mAlign;
|
||||
|
||||
public:
|
||||
BeType()
|
||||
{
|
||||
mTypeCode = BeTypeCode_None;
|
||||
mPointerType = NULL;
|
||||
mSize = -1;
|
||||
mAlign = -1;
|
||||
}
|
||||
|
||||
virtual ~BeType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool IsPointer()
|
||||
{
|
||||
return (mTypeCode == BeTypeCode_Pointer) || (mTypeCode == BeTypeCode_NullPtr);
|
||||
}
|
||||
|
||||
bool IsInt()
|
||||
{
|
||||
return (mTypeCode >= BeTypeCode_Int8) && (mTypeCode <= BeTypeCode_Int64);
|
||||
}
|
||||
|
||||
bool IsIntable()
|
||||
{
|
||||
return ((mTypeCode >= BeTypeCode_Boolean) && (mTypeCode <= BeTypeCode_Int64)) || (mTypeCode == BeTypeCode_Pointer);
|
||||
}
|
||||
|
||||
bool IsIntegral()
|
||||
{
|
||||
return (mTypeCode >= BeTypeCode_Int8) && (mTypeCode <= BeTypeCode_Int64);
|
||||
}
|
||||
|
||||
bool IsFloat()
|
||||
{
|
||||
return (mTypeCode == BeTypeCode_Float) || (mTypeCode == BeTypeCode_Double);
|
||||
}
|
||||
|
||||
bool IsStruct()
|
||||
{
|
||||
return (mTypeCode == BeTypeCode_Struct);
|
||||
}
|
||||
|
||||
bool IsSizedArray()
|
||||
{
|
||||
return (mTypeCode == BeTypeCode_SizedArray);
|
||||
}
|
||||
|
||||
bool IsComposite()
|
||||
{
|
||||
return (mTypeCode == BeTypeCode_Struct) || (mTypeCode == BeTypeCode_SizedArray);
|
||||
}
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx)
|
||||
{
|
||||
BF_ASSERT(mTypeCode < BeTypeCode_Struct);
|
||||
hashCtx.Mixin(mTypeCode);
|
||||
}
|
||||
};
|
||||
|
||||
class BeStructMember
|
||||
{
|
||||
public:
|
||||
BeType* mType;
|
||||
int mByteOffset;
|
||||
};
|
||||
|
||||
class BeStructType : public BeType
|
||||
{
|
||||
public:
|
||||
BeContext* mContext;
|
||||
String mName;
|
||||
Array<BeStructMember> mMembers;
|
||||
bool mIsPacked;
|
||||
bool mIsOpaque;
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx) override
|
||||
{
|
||||
hashCtx.MixinStr(mName);
|
||||
hashCtx.Mixin(mMembers.size());
|
||||
for (auto& member : mMembers)
|
||||
{
|
||||
member.mType->HashReference(hashCtx);
|
||||
hashCtx.Mixin(member.mByteOffset);
|
||||
}
|
||||
hashCtx.Mixin(mIsPacked);
|
||||
hashCtx.Mixin(mIsOpaque);
|
||||
}
|
||||
};
|
||||
|
||||
class BePointerType : public BeType
|
||||
{
|
||||
public:
|
||||
BeType* mElementType;
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx) override
|
||||
{
|
||||
hashCtx.Mixin(BeTypeCode_Pointer);
|
||||
mElementType->HashReference(hashCtx);
|
||||
}
|
||||
};
|
||||
|
||||
class BeSizedArrayType : public BeType
|
||||
{
|
||||
public:
|
||||
BeContext* mContext;
|
||||
BeType* mElementType;
|
||||
int mLength;
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx) override
|
||||
{
|
||||
hashCtx.Mixin(BeTypeCode_SizedArray);
|
||||
hashCtx.Mixin(mLength);
|
||||
mElementType->HashReference(hashCtx);
|
||||
}
|
||||
};
|
||||
|
||||
class BeFunctionTypeParam
|
||||
{
|
||||
public:
|
||||
BeType* mType;
|
||||
};
|
||||
|
||||
class BeFunctionType : public BeType
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
BeType* mReturnType;
|
||||
std::vector<BeFunctionTypeParam> mParams;
|
||||
bool mIsVarArg;
|
||||
|
||||
virtual void HashContent(BeHashContext& hashCtx) override
|
||||
{
|
||||
hashCtx.Mixin(BeTypeCode_Function);
|
||||
hashCtx.MixinStr(mName);
|
||||
mReturnType->HashReference(hashCtx);
|
||||
hashCtx.Mixin(mParams.size());
|
||||
for (auto& param : mParams)
|
||||
{
|
||||
param.mType->HashReference(hashCtx);
|
||||
}
|
||||
hashCtx.Mixin(mIsVarArg);
|
||||
}
|
||||
};
|
||||
|
||||
class BeContext
|
||||
{
|
||||
public:
|
||||
int mPointerSize;
|
||||
//BumpAllocator mAlloc;
|
||||
BeType* mPrimitiveTypes[BeTypeCode_COUNT];
|
||||
OwnedVector<BeType> mTypes;
|
||||
|
||||
public:
|
||||
void NotImpl();
|
||||
|
||||
public:
|
||||
BeContext();
|
||||
BeType* GetPrimitiveType(BeTypeCode typeCode);
|
||||
BeStructType* CreateStruct(const StringImpl& name);
|
||||
BePointerType* GetPointerTo(BeType* beType);
|
||||
void SetStructBody(BeStructType* structType, const SizedArrayImpl<BeType*>& types, bool packed);
|
||||
BeSizedArrayType* CreateSizedArrayType(BeType* type, int length);
|
||||
BeFunctionType* CreateFunctionType(BeType* returnType, const SizedArrayImpl<BeType*>& paramTypes, bool isVarArg);
|
||||
|
||||
bool AreTypesEqual(BeType* lhs, BeType* rhs);
|
||||
};
|
||||
|
||||
NS_BF_END
|
11
IDEHelper/Backend/BeDbgModule.h
Normal file
11
IDEHelper/Backend/BeDbgModule.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "BeefySysLib/Common.h"
|
||||
#include "../Compiler/BfIRBuilder.h"
|
||||
#include "BeContext.h"
|
||||
#include "BeModule.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
NS_BF_END
|
||||
|
3049
IDEHelper/Backend/BeIRCodeGen.cpp
Normal file
3049
IDEHelper/Backend/BeIRCodeGen.cpp
Normal file
File diff suppressed because it is too large
Load diff
135
IDEHelper/Backend/BeIRCodeGen.h
Normal file
135
IDEHelper/Backend/BeIRCodeGen.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "../Compiler/BfIRBuilder.h"
|
||||
#include "BeContext.h"
|
||||
#include "BeModule.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BeModule;
|
||||
class BeDbgType;
|
||||
class BfIRBuilder;
|
||||
class ChunkedDataBuffer;
|
||||
|
||||
enum BeIRCodeGenEntryKind
|
||||
{
|
||||
BeIRCodeGenEntryKind_None,
|
||||
BeIRCodeGenEntryKind_Value,
|
||||
BeIRCodeGenEntryKind_Type,
|
||||
BeIRCodeGenEntryKind_Block,
|
||||
BeIRCodeGenEntryKind_Metadata
|
||||
};
|
||||
|
||||
struct BeIRCodeGenEntry
|
||||
{
|
||||
BeIRCodeGenEntryKind mKind;
|
||||
union
|
||||
{
|
||||
BeValue* mBeValue;
|
||||
BeType* mBeType;
|
||||
BeBlock* mBeBlock;
|
||||
BeMDNode* mBeMetadata;
|
||||
};
|
||||
};
|
||||
|
||||
class BeIRTypeEntry
|
||||
{
|
||||
public:
|
||||
int mTypeId;
|
||||
BeDbgType* mDIType;
|
||||
BeDbgType* mInstDIType;
|
||||
BeType* mBeType;
|
||||
BeType* mInstBeType;
|
||||
|
||||
public:
|
||||
BeIRTypeEntry()
|
||||
{
|
||||
mTypeId = -1;
|
||||
mDIType = NULL;
|
||||
mInstDIType = NULL;
|
||||
mBeType = NULL;
|
||||
mInstBeType = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class BeIRCodeGen : public BfIRCodeGenBase
|
||||
{
|
||||
public:
|
||||
bool mDebugging;
|
||||
|
||||
BfIRBuilder* mBfIRBuilder;
|
||||
BeFunction* mActiveFunction;
|
||||
|
||||
BeContext* mBeContext;
|
||||
BeModule* mBeModule;
|
||||
Array<BeDbgLoc*> mSavedDebugLocs;
|
||||
bool mHasDebugLoc;
|
||||
|
||||
int mCmdCount;
|
||||
Dictionary<int, BeIRCodeGenEntry> mResults;
|
||||
Dictionary<int, BeIRTypeEntry> mTypes;
|
||||
|
||||
Dictionary<BeType*, BeDbgType*> mOnDemandTypeMap;
|
||||
Array<int> mConfigConsts;
|
||||
|
||||
public:
|
||||
void NotImpl();
|
||||
BfTypeCode GetTypeCode(BeType* type, bool isSigned);
|
||||
void SetResult(int id, BeValue* value);
|
||||
void SetResult(int id, BeType* type);
|
||||
void SetResult(int id, BeBlock* value);
|
||||
void SetResult(int id, BeMDNode* md);
|
||||
|
||||
BeType* GetBeType(BfTypeCode typeCode, bool& isSigned);
|
||||
BeIRTypeEntry& GetTypeEntry(int typeId);
|
||||
|
||||
public:
|
||||
BeIRCodeGen();
|
||||
~BeIRCodeGen();
|
||||
|
||||
void Hash(BeHashContext& hashCtx);
|
||||
bool IsModuleEmpty();
|
||||
|
||||
int64 ReadSLEB128();
|
||||
void Read(StringImpl& str);
|
||||
void Read(int& i);
|
||||
void Read(int64& i);
|
||||
void Read(bool& val);
|
||||
void Read(BeIRTypeEntry*& type);
|
||||
void Read(BeType*& beType);
|
||||
void Read(BeFunctionType*& beType);
|
||||
void Read(BeValue*& beValue);
|
||||
void Read(BeConstant*& beConstant);
|
||||
void Read(BeFunction*& beFunc);
|
||||
void Read(BeBlock*& beBlock);
|
||||
void Read(BeMDNode*& beMD);
|
||||
|
||||
template <typename T>
|
||||
void Read(SizedArrayImpl<T>& vec)
|
||||
{
|
||||
int len = (int)ReadSLEB128();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
T result;
|
||||
Read(result);
|
||||
vec.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
void Init(const BfSizedArray<uint8>& buffer);
|
||||
void Process();
|
||||
|
||||
virtual void ProcessBfIRData(const BfSizedArray<uint8>& buffer) override;
|
||||
virtual void HandleNextCmd() override;
|
||||
virtual void SetConfigConst(int idx, int value) override;
|
||||
|
||||
BeValue* GetBeValue(int streamId);
|
||||
BeType* GetBeType(int streamId);
|
||||
BeBlock* GetBeBlock(int streamId);
|
||||
BeMDNode* GetBeMetadata(int streamId);
|
||||
|
||||
BeType* GetBeTypeById(int id);
|
||||
};
|
||||
|
||||
NS_BF_END
|
521
IDEHelper/Backend/BeLibManger.cpp
Normal file
521
IDEHelper/Backend/BeLibManger.cpp
Normal file
|
@ -0,0 +1,521 @@
|
|||
|
||||
#pragma warning(disable:4996)
|
||||
#include "BeLibManger.h"
|
||||
#include "BeefySysLib/util/BeefPerf.h"
|
||||
|
||||
#include "BeefySysLib/util/AllocDebug.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
BeLibManager gBfLibManager;
|
||||
|
||||
void BeLibEntry::AddSymbol(const StringImpl& sym)
|
||||
{
|
||||
mSymbols.push_back(sym);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BeLibFile::BeLibFile()
|
||||
{
|
||||
mFailed = false;
|
||||
}
|
||||
|
||||
BeLibFile::~BeLibFile()
|
||||
{
|
||||
for (auto& entry : mEntries)
|
||||
delete entry.mValue;
|
||||
for (auto& entry : mOldEntries)
|
||||
delete entry.mValue;
|
||||
}
|
||||
|
||||
bool BeLibFile::ReadLib()
|
||||
{
|
||||
BP_ZONE("BeLibFile::ReadLib");
|
||||
|
||||
char fileId[8];
|
||||
mOldFileStream.Read(fileId, 8);
|
||||
if (strncmp(fileId, "!<arch>\n", 8) != 0)
|
||||
return false;
|
||||
|
||||
const char* libStrTable = NULL;
|
||||
|
||||
Dictionary<int, BeLibEntry*> pendingLibEntryMap;
|
||||
|
||||
int memberIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
int headerFilePos = mOldFileStream.GetPos();
|
||||
|
||||
BeLibMemberHeader header;
|
||||
mOldFileStream.Read(&header, sizeof(header));
|
||||
if (mOldFileStream.mReadPastEnd)
|
||||
break;
|
||||
|
||||
int len = atoi(header.mSize);
|
||||
|
||||
if (strncmp(header.mName, "/ ", 2) == 0)
|
||||
{
|
||||
if (memberIdx == 0)
|
||||
{
|
||||
uint8* data = new uint8[len];
|
||||
mOldFileStream.Read(data, len);
|
||||
|
||||
int numSymbols = FromBigEndian(*(int32*)data);
|
||||
|
||||
uint8* strTab = data + 4 + numSymbols * 4;
|
||||
|
||||
for (int symIdx = 0; symIdx < numSymbols; symIdx++)
|
||||
{
|
||||
const char* str = (char*)strTab;
|
||||
strTab += strlen((char*)strTab) + 1;
|
||||
|
||||
int offset = FromBigEndian(((int32*)(data + 4))[symIdx]);
|
||||
|
||||
BeLibEntry* pendingEntry;
|
||||
|
||||
BeLibEntry** pendingEntryPtr = NULL;
|
||||
if (!pendingLibEntryMap.TryAdd(offset, NULL, &pendingEntryPtr))
|
||||
{
|
||||
pendingEntry = *pendingEntryPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pendingEntry = new BeLibEntry();
|
||||
pendingEntry->mLibFile = this;
|
||||
*pendingEntryPtr = pendingEntry;
|
||||
}
|
||||
|
||||
pendingEntry->mSymbols.push_back(str);
|
||||
}
|
||||
|
||||
delete data;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else if (strncmp(header.mName, "// ", 3) == 0)
|
||||
{
|
||||
libStrTable = new char[len];
|
||||
mOldFileStream.Read((uint8*)libStrTable, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
String fileName;
|
||||
if (header.mName[0] == '/')
|
||||
{
|
||||
int tabIdx = atoi(&header.mName[1]);
|
||||
for (int checkIdx = tabIdx; true; checkIdx++)
|
||||
{
|
||||
char c = libStrTable[checkIdx];
|
||||
if ((c == 0) || (c == '/'))
|
||||
{
|
||||
fileName.Append(&libStrTable[tabIdx], checkIdx - tabIdx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (header.mName[i] == '/')
|
||||
fileName.Append(&header.mName[0], i);
|
||||
}
|
||||
}
|
||||
|
||||
BeLibEntry* libEntry = NULL;
|
||||
|
||||
if (!pendingLibEntryMap.TryGetValue(headerFilePos, &libEntry))
|
||||
{
|
||||
libEntry = new BeLibEntry();
|
||||
libEntry->mLibFile = this;
|
||||
}
|
||||
|
||||
BeLibEntry** namedEntry;
|
||||
if (mOldEntries.TryAdd(fileName, NULL, &namedEntry))
|
||||
{
|
||||
*namedEntry = libEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto prevEntry = *namedEntry;
|
||||
libEntry->mNextWithSameName = prevEntry->mNextWithSameName;
|
||||
prevEntry->mNextWithSameName = libEntry;
|
||||
}
|
||||
|
||||
libEntry->mName = fileName;
|
||||
libEntry->mOldDataPos = headerFilePos;
|
||||
libEntry->mLength = len;
|
||||
}
|
||||
|
||||
len = BF_ALIGN(len, 2); // Even addr
|
||||
mOldFileStream.SetPos(headerFilePos + sizeof(BeLibMemberHeader) + len);
|
||||
|
||||
memberIdx++;
|
||||
}
|
||||
|
||||
for (auto& entry : pendingLibEntryMap)
|
||||
{
|
||||
auto libEntry = entry.mValue;
|
||||
// Not used?
|
||||
if (libEntry->mOldDataPos == -1)
|
||||
delete libEntry;
|
||||
}
|
||||
|
||||
delete libStrTable;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BeLibFile::Init(const StringImpl& filePath, bool moveFile)
|
||||
{
|
||||
bool isInitialized = false;
|
||||
|
||||
if (FileExists(filePath))
|
||||
{
|
||||
String altName;
|
||||
if (moveFile)
|
||||
{
|
||||
altName = filePath + "_";
|
||||
if (!::MoveFileA(filePath.c_str(), altName.c_str()))
|
||||
{
|
||||
::DeleteFileA(altName.c_str());
|
||||
if (!::MoveFileA(filePath.c_str(), altName.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
altName = filePath;
|
||||
mOldFilePath = altName;
|
||||
|
||||
if (!mOldFileStream.Open(altName, "rb"))
|
||||
return false;
|
||||
|
||||
if (!ReadLib())
|
||||
return false;
|
||||
}
|
||||
|
||||
String newLibName = filePath;
|
||||
mFilePath = newLibName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BeLibFile::Finish()
|
||||
{
|
||||
BP_ZONE("BeLibFile::Finish");
|
||||
|
||||
//mOldEntries.clear();
|
||||
|
||||
Dictionary<String, BeLibEntry*>* libEntryMaps[2] = { &mEntries, &mOldEntries };
|
||||
|
||||
Array<BeLibEntry*> libEntries;
|
||||
|
||||
bool isAllReferenced = true;
|
||||
for (auto entryMap : libEntryMaps)
|
||||
{
|
||||
for (auto& libEntryPair : *entryMap)
|
||||
{
|
||||
auto libEntry = libEntryPair.mValue;
|
||||
if (libEntry->mReferenced)
|
||||
libEntries.push_back(libEntry);
|
||||
else
|
||||
isAllReferenced = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((isAllReferenced) && (mEntries.IsEmpty()) && (mOldFileStream.IsOpen()))
|
||||
{
|
||||
mOldFileStream.Close();
|
||||
String altName = mFilePath + "_";
|
||||
if (::MoveFileA(altName.c_str(), mFilePath.c_str()))
|
||||
{
|
||||
return true; // There are no changes
|
||||
}
|
||||
}
|
||||
|
||||
if (!mFileStream.Open(mFilePath, "wb"))
|
||||
{
|
||||
mFailed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
mFileStream.Write("!<arch>\n", 8);
|
||||
|
||||
std::sort(libEntries.begin(), libEntries.end(),
|
||||
[&](BeLibEntry* lhs, BeLibEntry* rhs)
|
||||
{
|
||||
return lhs->mName < rhs->mName;
|
||||
});
|
||||
|
||||
int longNamesSize = 0;
|
||||
|
||||
int tabSize = 4; // num symbols
|
||||
int numSymbols = 0;
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
if (libEntry->mName.length() > 15)
|
||||
{
|
||||
longNamesSize += (int)libEntry->mName.length() + 2;
|
||||
}
|
||||
|
||||
for (auto& sym : libEntry->mSymbols)
|
||||
{
|
||||
numSymbols++;
|
||||
tabSize += 4; // Offset
|
||||
tabSize += (int)sym.length() + 1; // String table
|
||||
}
|
||||
}
|
||||
|
||||
// Determine where all these entries will be placed
|
||||
int predictPos = mFileStream.GetPos() + sizeof(BeLibMemberHeader) + BF_ALIGN(tabSize, 2);
|
||||
|
||||
if (longNamesSize > 0)
|
||||
predictPos += sizeof(BeLibMemberHeader) + BF_ALIGN(longNamesSize, 2);
|
||||
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
libEntry->mNewDataPos = predictPos;
|
||||
|
||||
predictPos += sizeof(BeLibMemberHeader);
|
||||
predictPos += BF_ALIGN(libEntry->mLength, 2);
|
||||
}
|
||||
|
||||
int tabStartPos = mFileStream.GetPos();
|
||||
|
||||
|
||||
BeLibMemberHeader header;
|
||||
header.Init("/", "0", tabSize);
|
||||
mFileStream.WriteT(header);
|
||||
|
||||
mFileStream.Write(ToBigEndian((int32)numSymbols));
|
||||
// Offset table
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
for (auto& sym : libEntry->mSymbols)
|
||||
{
|
||||
mFileStream.Write((int32)ToBigEndian(libEntry->mNewDataPos));
|
||||
}
|
||||
}
|
||||
|
||||
// String map table
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
for (auto& sym : libEntry->mSymbols)
|
||||
{
|
||||
mFileStream.Write((uint8*)sym.c_str(), (int)sym.length() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int actualTabSize = mFileStream.GetPos() - tabStartPos - sizeof(BeLibMemberHeader);
|
||||
|
||||
//return true;
|
||||
|
||||
if ((tabSize % 2) != 0)
|
||||
mFileStream.Write((uint8)0);
|
||||
|
||||
BF_ASSERT(actualTabSize == tabSize);
|
||||
|
||||
// Create long names table
|
||||
if (longNamesSize > 0)
|
||||
{
|
||||
header.Init("//", "0", longNamesSize);
|
||||
mFileStream.WriteT(header);
|
||||
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
if (libEntry->mName.length() > 15)
|
||||
{
|
||||
mFileStream.Write((uint8*)libEntry->mName.c_str(), (int)libEntry->mName.length());
|
||||
mFileStream.Write("/\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((longNamesSize % 2) != 0)
|
||||
mFileStream.Write((uint8)'\n');
|
||||
}
|
||||
|
||||
int longNamesPos = 0;
|
||||
for (auto libEntry : libEntries)
|
||||
{
|
||||
int actualPos = mFileStream.GetPos();
|
||||
BF_ASSERT(actualPos == libEntry->mNewDataPos);
|
||||
|
||||
String entryName;
|
||||
|
||||
if (libEntry->mName.length() > 15)
|
||||
{
|
||||
char idxStr[32];
|
||||
_itoa(longNamesPos, idxStr, 10);
|
||||
entryName = "/";
|
||||
entryName += idxStr;
|
||||
longNamesPos += (int)libEntry->mName.length() + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
entryName = libEntry->mName;
|
||||
entryName += "/";
|
||||
}
|
||||
|
||||
header.Init(entryName.c_str(), "644", libEntry->mLength);
|
||||
mFileStream.WriteT(header);
|
||||
|
||||
if (libEntry->mOldDataPos != -1)
|
||||
{
|
||||
uint8* data = new uint8[libEntry->mLength];
|
||||
mOldFileStream.SetPos(libEntry->mOldDataPos + sizeof(BeLibMemberHeader));
|
||||
mOldFileStream.Read(data, libEntry->mLength);
|
||||
mFileStream.Write(data, libEntry->mLength);
|
||||
delete data;
|
||||
}
|
||||
else if (libEntry->mData.size() != 0)
|
||||
{
|
||||
mFileStream.Write((uint8*)&libEntry->mData[0], (int)libEntry->mData.size());
|
||||
}
|
||||
|
||||
if ((libEntry->mLength % 2) != 0)
|
||||
mFileStream.Write((uint8)0);
|
||||
}
|
||||
|
||||
mFileStream.Close();
|
||||
mOldFileStream.Close();
|
||||
::DeleteFileA(mOldFilePath.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BeLibManager::BeLibManager()
|
||||
{
|
||||
/*BeLibFile libFile;
|
||||
libFile.Init("Hey");*/
|
||||
|
||||
/*BeLibFile libFile;
|
||||
libFile.Init("c:/beef/IDE/mintest/build/Debug_Win64/minlib/minlib__.lib");
|
||||
libFile.Finish();*/
|
||||
|
||||
/*BeLibFile libFile2;
|
||||
libFile2.Init("c:\\temp\\Beefy2D.lib_new");*/
|
||||
}
|
||||
|
||||
BeLibManager::~BeLibManager()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void BeLibManager::Clear()
|
||||
{
|
||||
BP_ZONE("BeLibManager::Clear");
|
||||
|
||||
for (auto& entry : mLibFiles)
|
||||
delete entry.mValue;
|
||||
mLibFiles.Clear();
|
||||
}
|
||||
|
||||
BeLibEntry* BeLibManager::AddFile(const StringImpl& filePath, void* data, int size)
|
||||
{
|
||||
BP_ZONE("BeLibManager::AddFile");
|
||||
|
||||
String fileDir = GetFileDir(filePath);
|
||||
String fileName = GetFileName(filePath);
|
||||
|
||||
String fixedFileDir = FixPathAndCase(fileDir);
|
||||
|
||||
AutoCrit autoCrit(mCritSect);
|
||||
|
||||
BeLibFile* libFile = NULL;
|
||||
|
||||
// if ((data == NULL) && (!mLibFiles.ContainsKey(fixedFileDir)))
|
||||
// return NULL;
|
||||
|
||||
BeLibFile** libFilePtr = NULL;
|
||||
if (!mLibFiles.TryAdd(fixedFileDir, NULL, &libFilePtr))
|
||||
{
|
||||
libFile = *libFilePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
libFile = new BeLibFile();
|
||||
*libFilePtr = libFile;
|
||||
|
||||
String libPath = GetLibFilePath(filePath);
|
||||
libFile->Init(libPath, true);
|
||||
}
|
||||
|
||||
if (libFile->mFailed)
|
||||
return NULL;
|
||||
|
||||
BeLibEntry* oldEntry = NULL;
|
||||
if (libFile->mOldEntries.TryGetValue(fileName, &oldEntry))
|
||||
{
|
||||
if (data == NULL)
|
||||
{
|
||||
oldEntry->mReferenced = true;
|
||||
return oldEntry;
|
||||
}
|
||||
|
||||
delete oldEntry;
|
||||
libFile->mOldEntries.Remove(fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BeLibEntry* libEntry = NULL;
|
||||
BeLibEntry** libEntryPtr = NULL;
|
||||
libFile->mEntries.TryAdd(fileName, NULL, &libEntryPtr);
|
||||
if (*libEntryPtr != NULL)
|
||||
{
|
||||
// It's possible that we rebuild a type (generic, probably), decide we don't have any refs so we delete the type,
|
||||
// but then we specialize methods and then have to recreate it. Thus two entries here.
|
||||
delete *libEntryPtr;
|
||||
}
|
||||
libEntry = new BeLibEntry();
|
||||
libEntry->mLibFile = libFile;
|
||||
*libEntryPtr = libEntry;
|
||||
|
||||
libEntry->mReferenced = true;
|
||||
libEntry->mName = fileName;
|
||||
libEntry->mData.Insert(0, (uint8*)data, size);
|
||||
libEntry->mLength = size;
|
||||
|
||||
return libEntry;
|
||||
}
|
||||
|
||||
bool BeLibManager::AddUsedFileName(const StringImpl& fileName)
|
||||
{
|
||||
return AddFile(fileName, NULL, -1) != NULL;
|
||||
}
|
||||
|
||||
void BeLibManager::Finish()
|
||||
{
|
||||
BP_ZONE("BeLibManager::Finish");
|
||||
|
||||
for (auto& libPair : mLibFiles)
|
||||
{
|
||||
auto libFile = libPair.mValue;
|
||||
libFile->Finish();
|
||||
delete libFile;
|
||||
}
|
||||
mLibFiles.Clear();
|
||||
}
|
||||
|
||||
String BeLibManager::GetLibFilePath(const StringImpl& objFilePath)
|
||||
{
|
||||
String fileDir = RemoveTrailingSlash(GetFileDir(objFilePath));
|
||||
return fileDir + "/" + GetFileName(fileDir) + "__.lib";
|
||||
}
|
||||
|
||||
BeLibManager* BeLibManager::Get()
|
||||
{
|
||||
return &gBfLibManager;
|
||||
}
|
||||
|
119
IDEHelper/Backend/BeLibManger.h
Normal file
119
IDEHelper/Backend/BeLibManger.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/MemStream.h"
|
||||
#include "BeefySysLib/util/CritSect.h"
|
||||
#include "BeefySysLib/util/Dictionary.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include <unordered_map>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
struct BeLibMemberHeader
|
||||
{
|
||||
char mName[16];
|
||||
char mDate[12];
|
||||
char mUserId[6];
|
||||
char mGroupId[6];
|
||||
char mMode[8];
|
||||
char mSize[10];
|
||||
char mEnd[2];
|
||||
|
||||
void Init()
|
||||
{
|
||||
const char* spaces = " ";
|
||||
memcpy(mName, spaces, 16);
|
||||
memcpy(mDate, spaces, 12);
|
||||
memcpy(mUserId, spaces, 6);
|
||||
memcpy(mGroupId, spaces, 6);
|
||||
memcpy(mMode, spaces, 8);
|
||||
memcpy(mSize, spaces, 10);
|
||||
mEnd[0] = '`';
|
||||
mEnd[1] = '\n';
|
||||
}
|
||||
|
||||
void Init(const char* name, const char* mode, int size)
|
||||
{
|
||||
Init();
|
||||
memcpy(mName, name, strlen(name));
|
||||
memcpy(mDate, "0", 1);
|
||||
memcpy(mMode, mode, strlen(mode));
|
||||
|
||||
char sizeStr[32];
|
||||
sprintf(sizeStr, "%d", size);
|
||||
memcpy(mSize, sizeStr, strlen(sizeStr));
|
||||
}
|
||||
};
|
||||
|
||||
class BeLibFile;
|
||||
|
||||
class BeLibEntry
|
||||
{
|
||||
public:
|
||||
BeLibFile* mLibFile;
|
||||
String mName;
|
||||
bool mReferenced;
|
||||
int mOldDataPos;
|
||||
int mNewDataPos;
|
||||
int mLength;
|
||||
Array<String> mSymbols;
|
||||
Array<uint8> mData;
|
||||
BeLibEntry* mNextWithSameName;
|
||||
|
||||
public:
|
||||
BeLibEntry()
|
||||
{
|
||||
mReferenced = false;
|
||||
mOldDataPos = -1;
|
||||
mNewDataPos = -1;
|
||||
mLength = 0;
|
||||
mNextWithSameName = NULL;
|
||||
}
|
||||
|
||||
void AddSymbol(const StringImpl& sym);
|
||||
};
|
||||
|
||||
class BeLibFile
|
||||
{
|
||||
public:
|
||||
String mFilePath;
|
||||
String mOldFilePath;
|
||||
FileStream mOldFileStream;
|
||||
FileStream mFileStream;
|
||||
Dictionary<String, BeLibEntry*> mOldEntries;
|
||||
Dictionary<String, BeLibEntry*> mEntries;
|
||||
bool mFailed;
|
||||
|
||||
public:
|
||||
bool ReadLib();
|
||||
|
||||
public:
|
||||
BeLibFile();
|
||||
~BeLibFile();
|
||||
|
||||
bool Init(const StringImpl& fileName, bool moveFile);
|
||||
bool Finish();
|
||||
};
|
||||
|
||||
class BeLibManager
|
||||
{
|
||||
public:
|
||||
CritSect mCritSect;
|
||||
Dictionary<String, BeLibFile*> mLibFiles;
|
||||
|
||||
public:
|
||||
BeLibManager();
|
||||
~BeLibManager();
|
||||
|
||||
void Clear();
|
||||
|
||||
BeLibEntry* AddFile(const StringImpl& fileName, void* data, int size);
|
||||
bool AddUsedFileName(const StringImpl& fileName); // Returns true if have old data for this file
|
||||
void Finish();
|
||||
|
||||
static String GetLibFilePath(const StringImpl& objFilePath);
|
||||
static BeLibManager* Get();
|
||||
};
|
||||
|
||||
|
||||
NS_BF_END
|
16463
IDEHelper/Backend/BeMCContext.cpp
Normal file
16463
IDEHelper/Backend/BeMCContext.cpp
Normal file
File diff suppressed because it is too large
Load diff
1398
IDEHelper/Backend/BeMCContext.h
Normal file
1398
IDEHelper/Backend/BeMCContext.h
Normal file
File diff suppressed because it is too large
Load diff
7
IDEHelper/Backend/BeMCX86.h
Normal file
7
IDEHelper/Backend/BeMCX86.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
NS_BF_END
|
3263
IDEHelper/Backend/BeModule.cpp
Normal file
3263
IDEHelper/Backend/BeModule.cpp
Normal file
File diff suppressed because it is too large
Load diff
2140
IDEHelper/Backend/BeModule.h
Normal file
2140
IDEHelper/Backend/BeModule.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue