1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-04 15:26:00 +02:00

Initial checkin

This commit is contained in:
Brian Fiete 2019-08-23 11:56:54 -07:00
parent c74712dad9
commit 078564ac9e
3242 changed files with 1616395 additions and 0 deletions

File diff suppressed because it is too large Load diff

View 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

View 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;
}

View 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

View 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

File diff suppressed because it is too large Load diff

View 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

View 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;
}

View 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
#pragma once
#include "../Beef/BfCommon.h"
NS_BF_BEGIN
NS_BF_END

File diff suppressed because it is too large Load diff

2140
IDEHelper/Backend/BeModule.h Normal file

File diff suppressed because it is too large Load diff