#include "BeIRCodeGen.h" #include "../Compiler/BfIRCodeGen.h" #include "BeDbgModule.h" #include "BeefySysLib/util/BeefPerf.h" #include "llvm/IR/DIBuilder.h" #include "BeefySysLib/util/AllocDebug.h" #include "BeefySysLib/util/Hash.h" #include "BeModule.h" #include "BeContext.h" #include "../Compiler/CeMachine.h" #ifdef _DEBUG #define BE_EXTRA_CHECKS #endif USING_NS_BF; //#define CODEGEN_TRACK #ifdef CODEGEN_TRACK #include "../Compiler/MemReporter.h" MemReporter gBEMemReporter; CritSect gBEMemReporterCritSect; int gBEMemReporterSize = 0; #define BE_MEM_START \ int startPos = mStream->GetReadPos(); #define BE_MEM_END(name) \ gBEMemReporter.Add(name, mStream->GetReadPos() - startPos); static const char* gIRCmdNames[] = { "Module_Start", "Module_SetTargetTriple", "Module_AddModuleFlag", "WriteIR", "SetType", "SetInstType", "PrimitiveType", "CreateStruct", "StructSetBody", "Type", "TypeInst", "TypeInstPtr", "GetType", "GetPointerToFuncType", "GetPointerToType", "GetSizedArrayType", "CreateConstStruct", "CreateConstStructZero", "CreateConstArray", "CreateConstString", "SetName", "CreateUndefValue", "NumericCast", "CmpEQ", "CmpNE", "CmpSLT", "CmpULT", "CmpSLE", "CmpULE", "CmpSGT", "CmpUGT", "CmpSGE", "CmpUGE", "Add", "Sub", "Mul", "SDiv", "UDiv", "SRem", "URem", "And", "Or", "Xor", "Shl", "AShr", "LShr", "Neg", "Not", "BitCast", "PtrToInt", "IntToPtr", "InboundsGEP1_32", "InboundsGEP2_32", "InBoundsGEP1", "InBoundsGEP2", "IsNull", "IsNotNull", "ExtractValue", "InsertValue", "Alloca", "AllocaArray", "SetAllocaAlignment", "SetAllocaNoChkStkHint", "SetAllocaForceMem", "LifetimeStart", "LifetimeEnd", "LifetimeExtend", "ValueScopeStart", "ValueScopeRetain", "ValueScopeSoftEnd", "ValueScopeHardEnd", "Load", "AlignedLoad", "Store", "AlignedStore", "MemSet", "Fence", "StackSave", "StackRestore", "GlobalVariable", "GlobalVar_SetUnnamedAddr", "GlobalVar_SetInitializer", "GlobalVar_SetAlignment", "GlobalStringPtr", "CreateBlock", "MaybeChainNewBlock", "AddBlock", "DropBlocks", "MergeBlockDown", "SetInsertPoint", "SetInsertPointAtStart", "EraseFromParent", "DeleteBlock", "EraseInstFromParent", "CreateBr", "CreateBr_NoCollapse", "CreateCondBr", "MoveBlockToEnd", "CreateSwitch", "AddSwitchCase", "SetSwitchDefaultDest", "CreatePhi", "AddPhiIncoming", "GetIntrinsic", "CreateFunctionType", "CreateFunction", "EnsureFunctionPatchable", "RemapBindFunction", "SetActiveFunction", "CreateCall", "SetCallCallingConv", "SetFuncCallingConv", "SetTailCall", "SetCallAttribute", "CreateRet", "CreateRetVoid", "CreateUnreachable", "Call_AddAttribute", "Call_AddAttribute1", "Func_AddAttribute", "Func_AddAttribute1", "Func_SetParamName", "Func_DeleteBody", "Func_EraseFromParent", "Func_SetLinkage", "SaveDebugLocation", "RestoreDebugLocation", "ClearDebugLocation", "ClearDebugLocationInst", "UpdateDebugLocation", "SetCurrentDebugLocation", "Nop", "EnsureInstructionAt", "StatementStart", "ObjectAccessCheck", "DbgInit", "DbgFinalize", "DbgCreateCompileUnit", "DbgCreateFile", "ConstValueI64", "DbgGetCurrentLocation", "DbgSetType", "DbgSetInstType", "DbgGetType", "DbgGetTypeInst", "DbgTrackDITypes", "DbgCreateNamespace", "DbgCreateImportedModule", "DbgCreateBasicType", "DbgCreateStructType", "DbgCreateEnumerationType", "DbgCreatePointerType", "DbgCreateReferenceType", "DbgCreateConstType", "DbgCreateArtificialType", "DbgCreateArrayType", "DbgCreateReplaceableCompositeType", "DbgCreateForwardDecl", "DbgCreateSizedForwardDecl", "BeIRCmd_DbgSetTypeSize", "DbgReplaceAllUses", "DbgDeleteTemporary", "DbgMakePermanent", "CreateEnumerator", "DbgCreateMemberType", "DbgStaticCreateMemberType", "DbgCreateInheritance", "DbgCreateMethod", "DbgCreateFunction", "DbgCreateParameterVariable", "DbgCreateSubroutineType", "DbgCreateAutoVariable", "DbgInsertValueIntrinsic", "DbgInsertDeclare", "DbgLifetimeEnd", "DbgCreateGlobalVariable", "DbgCreateLexicalBlock", "DbgCreateLexicalBlockFile", "DbgCreateAnnotation" }; BF_STATIC_ASSERT(BF_ARRAY_COUNT(gIRCmdNames) == BfIRCmd_COUNT); #else #define BE_MEM_START #define BE_MEM_END(name) #endif #pragma warning(disable:4146) #define CMD_PARAM(ty, name) ty name; Read(name); BeIRCodeGen::BeIRCodeGen() { mBfIRBuilder = NULL; mStream = NULL; mActiveFunction = NULL; mBeContext = NULL; mBeModule = NULL; mHasDebugLoc = false; mDebugging = false; mCmdCount = 0; } BeIRCodeGen::~BeIRCodeGen() { BF_ASSERT(mSavedDebugLocs.size() == 0); delete mBeModule; delete mBeContext; delete mStream; } void BeIRCodeGen::Hash(BeHashContext& hashCtx) { // if (mBeModule->mModuleName == "IDE_IDEApp") // { // hashCtx.mDbgViz = true; // NOP; // } hashCtx.Mixin(mPtrSize); hashCtx.Mixin(mIsOptimized); if (mBeModule != NULL) mBeModule->Hash(hashCtx); Array structHashList; for (auto beType : mBeContext->mTypes) { if (!beType->IsStruct()) continue; auto beStructType = (BeStructType*)beType; if (beStructType->mHashId != -1) continue; structHashList.Add(beStructType); } structHashList.Sort([](BeStructType* lhs, BeStructType* rhs) { return lhs->mName < rhs->mName; }); for (auto beStructType : structHashList) { beStructType->HashReference(hashCtx); } } bool BeIRCodeGen::IsModuleEmpty() { if (!mBeModule->mFunctions.IsEmpty()) return false; if (!mBeModule->mGlobalVariables.IsEmpty()) return false; return true; } void BeIRCodeGen::FatalError(const StringImpl& err) { String failStr = "Fatal Error in Module: "; if (mBeModule != NULL) failStr += mBeModule->mModuleName; failStr += "\n"; if (mBeModule != NULL) { BeDumpContext dumpCtx; if (mActiveFunction != NULL) { failStr += "Function: "; failStr += mActiveFunction->mName; failStr += "\n"; } if (mBeModule->mCurDbgLoc != NULL) { failStr += "DbgLoc: "; dumpCtx.ToString(failStr, mBeModule->mCurDbgLoc); failStr += "\n"; } } failStr += err; BF_FATAL(failStr); } void BeIRCodeGen::NotImpl() { BF_FATAL("Not implemented"); } BeType* BeIRCodeGen::GetBeType(BfTypeCode typeCode, bool& isSigned) { isSigned = false; BeTypeCode beTypeCode = BeTypeCode_None; switch (typeCode) { case BfTypeCode_None: beTypeCode = BeTypeCode_None; break; case BfTypeCode_NullPtr: beTypeCode = BeTypeCode_NullPtr; break; case BfTypeCode_Boolean: beTypeCode = BeTypeCode_Boolean; break; case BfTypeCode_Int8: isSigned = true; beTypeCode = BeTypeCode_Int8; break; case BfTypeCode_UInt8: case BfTypeCode_Char8: beTypeCode = BeTypeCode_Int8; break; case BfTypeCode_Int16: isSigned = true; beTypeCode = BeTypeCode_Int16; break; case BfTypeCode_Char16: case BfTypeCode_UInt16: beTypeCode = BeTypeCode_Int16; break; case BfTypeCode_Int32: isSigned = true; beTypeCode = BeTypeCode_Int32; break; case BfTypeCode_UInt32: case BfTypeCode_Char32: beTypeCode = BeTypeCode_Int32; break; case BfTypeCode_Int64: isSigned = true; beTypeCode = BeTypeCode_Int64; break; case BfTypeCode_UInt64: beTypeCode = BeTypeCode_Int64; break; case BfTypeCode_IntPtr: BF_FATAL("Illegal"); /*isSigned = true; if (mModule->mSystem->mPtrSize == 4) return llvm::Type::getInt32Ty(*mLLVMContext); else return llvm::Type::getInt64Ty(*mLLVMContext);*/ case BfTypeCode_UIntPtr: BF_FATAL("Illegal"); /*if (mModule->mSystem->mPtrSize == 4) return llvm::Type::getInt32Ty(*mLLVMContext); else return llvm::Type::getInt64Ty(*mLLVMContext);*/ case BfTypeCode_Float: isSigned = true; beTypeCode = BeTypeCode_Float; break; case BfTypeCode_Double: isSigned = true; beTypeCode = BeTypeCode_Double; break; } return mBeContext->GetPrimitiveType(beTypeCode); } BeIRTypeEntry& BeIRCodeGen::GetTypeEntry(int typeId) { BeIRTypeEntry& typeEntry = mTypes[typeId]; if (typeEntry.mTypeId == -1) typeEntry.mTypeId = typeId; return typeEntry; } void BeIRCodeGen::FixValues(BeStructType* structType, CmdParamVec& values) { if (values.size() >= structType->mMembers.size()) return; int readIdx = values.size() - 1; values.resize(structType->mMembers.size()); for (int i = (int)values.size() - 1; i >= 0; i--) { if (mBeContext->AreTypesEqual(values[readIdx]->GetType(), structType->mMembers[i].mType)) { values[i] = values[readIdx]; readIdx--; } else if (structType->mMembers[i].mType->IsSizedArray()) { auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = structType->mMembers[i].mType; values[i] = beConst; } else { FatalError("Malformed structure values"); } } } void BeIRCodeGen::FixValues(BeStructType* structType, SizedArrayImpl& values) { if (values.size() >= structType->mMembers.size()) return; int readIdx = values.size() - 1; values.resize(structType->mMembers.size()); for (int i = (int)values.size() - 1; i >= 0; i--) { if (mBeContext->AreTypesEqual(values[readIdx]->GetType(), structType->mMembers[i].mType)) { values[i] = values[readIdx]; readIdx--; } else if (structType->mMembers[i].mType->IsSizedArray()) { auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = structType->mMembers[i].mType; values[i] = beConst; } else { FatalError("Malformed structure values"); } } } void BeIRCodeGen::Init(const BfSizedArray& buffer) { BP_ZONE("BeIRCodeGen::Init"); BF_ASSERT(mStream == NULL); mStream = new ChunkedDataBuffer(); mStream->InitFlatRef(buffer.mVals, buffer.mSize); #ifdef CODEGEN_TRACK AutoCrit autoCrit(gBEMemReporterCritSect); AutoMemReporter autoMemReporter(&gBEMemReporter, "BeIRCodeGen"); #endif // { BP_ZONE("BeIRCodeGen::ProcessBfIRData.HandleNextCmds"); while (mStream->GetReadPos() < buffer.mSize) { if (mFailed) break; HandleNextCmd(); } } BF_ASSERT((mFailed) || (mStream->GetReadPos() == buffer.mSize)); } void BeIRCodeGen::Process() { BP_ZONE("BeIRCodeGen::process"); //mDebugging |= ((mBeModule->mDbgModule != NULL) && (mBeModule->mDbgModule->mFileName == "ClassQ")); if (mDebugging) { String dbgStr; dbgStr = mBeModule->ToString(); OutputDebugStr(dbgStr); } mBeModule->DoInlining(); if (mDebugging) { String dbgStr = "-------------- AFTER INLINING --------------\n"; dbgStr += mBeModule->ToString(); OutputDebugStr(dbgStr); } } void BeIRCodeGen::ProcessBfIRData(const BfSizedArray& buffer) { BP_ZONE("BeIRCodeGen::ProcessBfIRData"); Init(buffer); Process(); } BfTypeCode BeIRCodeGen::GetTypeCode(BeType * type, bool isSigned) { switch (type->mTypeCode) { case BeTypeCode_Int8: return (isSigned) ? BfTypeCode_Int8 : BfTypeCode_UInt8; case BeTypeCode_Int16: return (isSigned) ? BfTypeCode_Int16 : BfTypeCode_UInt16; case BeTypeCode_Int32: return (isSigned) ? BfTypeCode_Int32 : BfTypeCode_UInt32; case BeTypeCode_Int64: return (isSigned) ? BfTypeCode_Int64 : BfTypeCode_UInt64; case BeTypeCode_Float: return BfTypeCode_Float; case BeTypeCode_Double: return BfTypeCode_Double; default: return BfTypeCode_None; } } void BeIRCodeGen::SetResult(int id, BeValue* value) { BeIRCodeGenEntry entry; entry.mKind = BeIRCodeGenEntryKind_Value; entry.mBeValue = value; mResults.TryAdd(id, entry); } void BeIRCodeGen::SetResult(int id, BeType* type) { BeIRCodeGenEntry entry; entry.mKind = BeIRCodeGenEntryKind_Type; entry.mBeType = type; mResults.TryAdd(id, entry); } void BeIRCodeGen::SetResult(int id, BeBlock* value) { BeIRCodeGenEntry entry; entry.mKind = BeIRCodeGenEntryKind_Block; entry.mBeBlock = value; mResults.TryAdd(id, entry); } void BeIRCodeGen::SetResult(int id, BeMDNode* md) { BeIRCodeGenEntry entry; entry.mKind = BeIRCodeGenEntryKind_Metadata; entry.mBeMetadata = md; mResults.TryAdd(id, entry); } int64 BeIRCodeGen::ReadSLEB128() { int64 val = 0; int64 shift = 0; uint8 byteVal; do { byteVal = mStream->Read(); val |= ((int64)(byteVal & 0x7f)) << shift; shift += 7; } while (byteVal >= 128); // Sign extend negative numbers. if ((byteVal & 0x40) && (shift < 64)) val |= (-1ULL) << shift; return val; } void BeIRCodeGen::Read(StringImpl& str) { BE_MEM_START; int len = (int)ReadSLEB128(); str.Append('?', len); mStream->Read((void*)str.c_str(), len); BE_MEM_END("String"); } void BeIRCodeGen::Read(int& i) { BE_MEM_START; i = (int)ReadSLEB128(); BE_MEM_END("int"); } void BeIRCodeGen::Read(int64& i) { BE_MEM_START; i = ReadSLEB128(); BE_MEM_END("int64"); } void BeIRCodeGen::Read(Val128& i) { i.mLow = (uint64)ReadSLEB128(); i.mHigh = (uint64)ReadSLEB128(); } void BeIRCodeGen::Read(bool& val) { BE_MEM_START; val = mStream->Read() != 0; BE_MEM_END("bool"); } void BeIRCodeGen::Read(int8& val) { val = mStream->Read(); } void BeIRCodeGen::Read(BeIRTypeEntry*& type) { BE_MEM_START; int typeId = (int)ReadSLEB128(); type = &GetTypeEntry(typeId); BE_MEM_END("BeIRTypeEntry"); } void BeIRCodeGen::Read(BeType*& beType) { BE_MEM_START; BfIRType::TypeKind typeKind = (BfIRType::TypeKind)mStream->Read(); if (typeKind == BfIRType::TypeKind::TypeKind_None) { beType = NULL; BE_MEM_END("BeType"); return; } if (typeKind == BfIRType::TypeKind::TypeKind_Stream) { int streamId = (int)ReadSLEB128(); if (streamId == -1) { beType = NULL; BE_MEM_END("BeType"); return; } auto& result = mResults[streamId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Type); beType = result.mBeType; BE_MEM_END("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(); if (typeKind == BfIRType::TypeKind::TypeKind_TypeCode) { bool isSigned = false; beType = GetBeType((BfTypeCode)typeId, isSigned); return; } auto& typeEntry = GetTypeEntry(typeId); if (typeKind == BfIRType::TypeKind::TypeKind_TypeId) beType = typeEntry.mBeType; else if (typeKind == BfIRType::TypeKind::TypeKind_TypeInstId) beType = typeEntry.mInstBeType; else if (typeKind == BfIRType::TypeKind::TypeKind_TypeInstPtrId) beType = mBeContext->GetPointerTo(typeEntry.mInstBeType); BE_MEM_END("BeType"); } void BeIRCodeGen::Read(BeFunctionType*& beType) { BE_MEM_START; int streamId = (int)ReadSLEB128(); auto& result = mResults[streamId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Type); beType = (BeFunctionType*)result.mBeType; BE_MEM_END("BeFunctionType"); } void BeIRCodeGen::Read(BeValue*& beValue) { BE_MEM_START; BfIRParamType paramType = (BfIRParamType)mStream->Read(); if (paramType == BfIRParamType_None) { beValue = NULL; BE_MEM_END("ParamType_None"); } else if (paramType == BfIRParamType_Const) { BfTypeCode typeCode = (BfTypeCode)mStream->Read(); BfConstType constType = (BfConstType)typeCode; if (constType == BfConstType_GlobalVar) { CMD_PARAM(int, streamId); if (streamId == -1) { int streamId = mCmdCount++; CMD_PARAM(BeType*, varType); CMD_PARAM(bool, isConstant); BfIRLinkageType linkageType = (BfIRLinkageType)mStream->Read(); CMD_PARAM(BeConstant*, initializer); CMD_PARAM(String, name); CMD_PARAM(bool, isTLS); BF_ASSERT(varType != NULL); auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; globalVariable->mType = varType; globalVariable->mIsConstant = isConstant; globalVariable->mLinkageType = linkageType; globalVariable->mInitializer = initializer; globalVariable->mName = name; globalVariable->mIsTLS = isTLS; globalVariable->mAlign = varType->mAlign; globalVariable->mUnnamedAddr = false; globalVariable->mStorageKind = BfIRStorageKind_Normal; if (initializer != NULL) BF_ASSERT(varType->mAlign > 0); SetResult(streamId, globalVariable); beValue = globalVariable; } else beValue = GetBeValue(streamId); beValue->mRefCount++; BE_MEM_END("ParamType_Const_GlobalVar"); return; } else if ((constType == BfConstType_BitCast) || (constType == BfConstType_BitCastNull)) { CMD_PARAM(BeConstant*, target); CMD_PARAM(BeType*, toType); auto castedVal = mBeModule->mAlloc.Alloc(); castedVal->mInt64 = target->mInt64; castedVal->mType = toType; castedVal->mTarget = target; BF_ASSERT(target->GetType() != NULL); BF_ASSERT(!target->GetType()->IsComposite()); beValue = castedVal; BE_MEM_END("ParamType_Const_BitCast"); return; } else if (constType == BfConstType_GEP32_1) { CMD_PARAM(BeConstant*, target); CMD_PARAM(int, idx0); BF_ASSERT(target->GetType()->IsPointer()); auto gepConstant = mBeModule->mAlloc.Alloc(); gepConstant->mTarget = target; gepConstant->mIdx0 = idx0; beValue = gepConstant; BE_MEM_END("ParamType_Const_GEP32_1"); return; } else if (constType == BfConstType_GEP32_2) { CMD_PARAM(BeConstant*, target); CMD_PARAM(int, idx0); CMD_PARAM(int, idx1); BF_ASSERT(target->GetType()->IsPointer()); auto gepConstant = mBeModule->mAlloc.Alloc(); gepConstant->mTarget = target; gepConstant->mIdx0 = idx0; gepConstant->mIdx1 = idx1; beValue = gepConstant; BE_MEM_END("ParamType_Const_GEP32_2"); return; } else if (constType == BfConstType_ExtractValue) { CMD_PARAM(BeConstant*, target); CMD_PARAM(int, idx0); auto gepConstant = mBeModule->mAlloc.Alloc(); gepConstant->mTarget = target; gepConstant->mIdx0 = idx0; beValue = gepConstant; BE_MEM_END("ParamType_Const_ExtractValue"); return; } else if (constType == BfConstType_PtrToInt) { CMD_PARAM(BeConstant*, target); BfTypeCode toTypeCode = (BfTypeCode)mStream->Read(); BF_ASSERT(target->GetType()->IsPointer()); bool isSigned = false; BeType* toType = GetBeType(toTypeCode, isSigned); auto castedVal = mBeModule->mAlloc.Alloc(); castedVal->mInt64 = target->mInt64; castedVal->mType = toType; castedVal->mTarget = target; BF_ASSERT(target->GetType() != NULL); beValue = castedVal; BE_MEM_END("ParamType_Const_PtrToInt"); return; } else if (constType == BfConstType_IntToPtr) { CMD_PARAM(BeConstant*, target); CMD_PARAM(BeType*, toType); auto castedVal = mBeModule->mAlloc.Alloc(); castedVal->mInt64 = target->mInt64; castedVal->mType = toType; castedVal->mTarget = target; BF_ASSERT(target->GetType() != NULL); BF_ASSERT(!target->GetType()->IsComposite()); BF_ASSERT(toType->IsPointer()); beValue = castedVal; BE_MEM_END("ParamType_Const_IntToPtr"); return; } else if (constType == BfConstType_AggZero) { CMD_PARAM(BeType*, type); auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = type; beValue = beConst; BE_MEM_END("ParamType_Const_AggZero"); return; } else if (constType == BfConstType_Agg) { CMD_PARAM(BeType*, type); CMD_PARAM(CmdParamVec, values); if (type->IsSizedArray()) { auto arrayType = (BeSizedArrayType*)type; int fillCount = (int)(arrayType->mLength - values.size()); if (fillCount > 0) { auto lastValue = values.back(); for (int i = 0; i < fillCount; i++) values.push_back(lastValue); } } else if (type->IsVector()) { auto vecType = (BeVectorType*)type; int fillCount = (int)(vecType->mLength - values.size()); if (fillCount > 0) { auto lastValue = values.back(); for (int i = 0; i < fillCount; i++) values.push_back(lastValue); } } else { BF_ASSERT(type->IsStruct()); } auto constStruct = mBeModule->mOwnedValues.Alloc(); constStruct->mType = type; if (type->IsStruct()) FixValues((BeStructType*)type, values); for (int i = 0; i < (int)values.size(); i++) { auto val = values[i]; BeConstant* constant = BeValueDynCast(val); if (type->IsSizedArray()) { auto arrayType = (BeSizedArrayType*)type; auto memberType = constant->GetType(); if (memberType != arrayType->mElementType) Fail("ConstAgg array member type mismatch"); } else if (type->IsVector()) { auto vecType = (BeVectorType*)type; auto memberType = constant->GetType(); if (memberType != vecType->mElementType) Fail("ConstAgg vector member type mismatch"); } else { BF_ASSERT(type->IsStruct()); auto structType = (BeStructType*)type; auto valType = constant->GetType(); if (structType->mIsOpaque) { Fail("ConstAgg with opaque struct"); } else if (valType != structType->mMembers[i].mType) { if (valType->IsSizedArray()) { auto valSizedType = (BeSizedArrayType*)valType; if (valSizedType->mSize == 0) { constant->mType = structType->mMembers[i].mType; constStruct->mMemberValues.Add(constant); continue; } } Fail("ConstAgg struct member type mismatch"); } } constStruct->mMemberValues.Add(constant); } beValue = constStruct; BE_MEM_END("ParamType_Const_Array"); return; } else if (constType == BfConstType_ArrayZero8) { CMD_PARAM(int, count); auto beType = mBeContext->CreateSizedArrayType(mBeContext->GetPrimitiveType(BeTypeCode_Int8), count); auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = beType; beValue = beConst; return; } else if (constType == BfConstType_Undef) { CMD_PARAM(BeType*, type); auto constUndef = mBeModule->mOwnedValues.Alloc(); constUndef->mType = type; beValue = constUndef; return; } else if (constType == BfConstType_TypeOf) { CMD_PARAM(BeType*, type); beValue = mReflectDataMap[type]; BF_ASSERT(beValue != NULL); return; } else if (constType == BfConstType_TypeOf_Comptime) { CMD_PARAM(BeType*, typeType); CMD_PARAM(int, bfTypeId); auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = typeType; beConst->mBfTypeId = bfTypeId; beValue = beConst; return; } else if (constType == BfConstType_TypeOf_WithData) { CMD_PARAM(BeType*, type); CMD_PARAM(BeValue*, value); mReflectDataMap[type] = value; beValue = value; return; } bool isSigned = false; BeType* llvmConstType = GetBeType(typeCode, isSigned); if (typeCode == BfTypeCode_Float) { float f; mStream->Read(&f, sizeof(float)); beValue = mBeModule->GetConstant(llvmConstType, f); BE_MEM_END("ParamType_Single"); } else if (typeCode == BfTypeCode_Double) { double d; mStream->Read(&d, sizeof(double)); beValue = mBeModule->GetConstant(llvmConstType, d); BE_MEM_END("ParamType_Const_Double"); } else if (typeCode == BfTypeCode_Boolean) { CMD_PARAM(bool, boolVal); beValue = mBeModule->GetConstant(llvmConstType, boolVal); BE_MEM_END("ParamType_Const_Boolean"); } else if (typeCode == BfTypeCode_None) { beValue = NULL; BE_MEM_END("ParamType_Const_None"); } else if (typeCode == BfTypeCode_NullPtr) { CMD_PARAM(BeType*, nullType); beValue = mBeModule->GetConstantNull((BePointerType*)nullType); BE_MEM_END("ParamType_Const_NullPtr"); } else if (BfIRBuilder::IsInt(typeCode)) { int64 intVal = ReadSLEB128(); auto constVal = mBeModule->GetConstant(llvmConstType, intVal); beValue = constVal; BE_MEM_END("ParamType_Const_Int"); } else { BF_FATAL("Unhandled"); } } else if (paramType == BfIRParamType_Arg) { int argIdx = mStream->Read(); beValue = mBeModule->GetArgument(argIdx); BE_MEM_END("ParamType_Arg"); } else if (paramType == BfIRParamType_StreamId_Abs8) { int cmdId = mStream->Read(); auto& result = mResults[cmdId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Value); beValue = result.mBeValue; BE_MEM_END("ParamType_StreamId"); } else if (paramType == BfIRParamType_StreamId_Rel) { int cmdId = mCmdCount - (int)ReadSLEB128(); auto& result = mResults[cmdId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Value); beValue = result.mBeValue; BE_MEM_END("ParamType_StreamId"); } else { int cmdId = mCmdCount - (paramType - BfIRParamType_StreamId_Back1) - 1; auto& result = mResults[cmdId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Value); beValue = result.mBeValue; BE_MEM_END("ParamType_StreamId"); } if (beValue != NULL) beValue->mRefCount++; } void BeIRCodeGen::Read(BeConstant*& llvmConstant) { BE_MEM_START; BeValue* value; Read(value); if (value == NULL) { llvmConstant = NULL; } else { BF_ASSERT(BeValueDynCast(value)); llvmConstant = (BeConstant*)value; } BE_MEM_END("BeConstant"); } void BeIRCodeGen::Read(BeFunction*& beFunc) { BE_MEM_START; int streamId = (int)ReadSLEB128(); if (streamId == -1) { beFunc = NULL; return; } auto& result = mResults[streamId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Value); BF_ASSERT(BeValueDynCast(result.mBeValue)); beFunc = (BeFunction*)result.mBeValue; BE_MEM_END("BeFunction"); beFunc->mRefCount++; } void BeIRCodeGen::Read(BeBlock*& beBlock) { BE_MEM_START; int streamId = (int)ReadSLEB128(); auto& result = mResults[streamId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Block); beBlock = (BeBlock*)result.mBeType; BE_MEM_END("BeBlock"); beBlock->mRefCount++; } void BeIRCodeGen::Read(BeMDNode*& llvmMD) { BE_MEM_START; int streamId = (int)ReadSLEB128(); if (streamId == -1) { llvmMD = NULL; return; } auto& result = mResults[streamId]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Metadata); llvmMD = result.mBeMetadata; BE_MEM_END("BeMDNode"); if (llvmMD != NULL) llvmMD->mRefCount++; } void BeIRCodeGen::HandleNextCmd() { if (mFailed) { mStream->SetReadPos(mStream->GetSize()); return; } int curId = mCmdCount; BfIRCmd cmd = (BfIRCmd)mStream->Read(); mCmdCount++; #ifdef CODEGEN_TRACK gBEMemReporter.BeginSection(gIRCmdNames[cmd]); gBEMemReporter.Add(1); #endif switch (cmd) { case BfIRCmd_Module_Start: { CMD_PARAM(String, moduleName); CMD_PARAM(int, ptrSize); CMD_PARAM(bool, isOptimized); BF_ASSERT(mBeModule == NULL); mPtrSize = ptrSize; mIsOptimized = isOptimized; mBeContext = new BeContext(); mBeModule = new BeModule(moduleName, mBeContext); mBeModule->mBeIRCodeGen = this; mBeContext->mPointerSize = ptrSize; for (auto constInt : mConfigConsts) { auto constVal = mBeModule->mAlloc.Alloc(); constVal->mType = mBeContext->GetPrimitiveType(BeTypeCode_Int32); constVal->mInt64 = constInt; mBeModule->mConfigConsts32.Add(constVal); constVal = mBeModule->mAlloc.Alloc(); constVal->mType = mBeContext->GetPrimitiveType(BeTypeCode_Int64); constVal->mInt64 = constInt; mBeModule->mConfigConsts64.Add(constVal); } } break; case BfIRCmd_Module_SetTargetTriple: { CMD_PARAM(String, targetTriple); CMD_PARAM(String, targetCPU); mBeModule->mTargetTriple = targetTriple; mBeModule->mTargetCPU = targetCPU; } break; case BfIRCmd_Module_AddModuleFlag: { CMD_PARAM(String, flag); CMD_PARAM(int, val); //mBeModule->addModuleFlag(BeModule::Warning, flag, val); } break; case BfIRCmd_WriteIR: { /*CMD_PARAM(String, fileName); std::error_code ec; Beraw_fd_ostream outStream(fileName.c_str(), ec, Besys::fs::OpenFlags::F_Text); if (ec) { Fail("Failed writing IR '" + fileName + "': " + ec.message()); } else mBeModule->print(outStream, NULL);*/ } break; case BfIRCmd_Abort: { Fail("Stream aborted"); } break; case BfIRCmd_SetType: { CMD_PARAM(int, typeId); CMD_PARAM(BeType*, type); auto& typeEntry = GetTypeEntry(typeId); typeEntry.mBeType = type; if (typeEntry.mInstBeType == NULL) typeEntry.mInstBeType = type; } break; case BfIRCmd_SetInstType: { CMD_PARAM(int, typeId); CMD_PARAM(BeType*, type); GetTypeEntry(typeId).mInstBeType = type; } break; case BfIRCmd_PrimitiveType: { BfTypeCode typeCode = (BfTypeCode)mStream->Read(); bool isSigned = false; SetResult(curId, GetBeType(typeCode, isSigned)); } break; case BfIRCmd_CreateStruct: { CMD_PARAM(String, typeName); SetResult(curId, mBeContext->CreateStruct(typeName)); } break; case BfIRCmd_CreateAnonymousStruct: { CMD_PARAM(CmdParamVec, members); BeStructType* structType = mBeContext->CreateStruct(members); SetResult(curId, structType); } break; case BfIRCmd_StructSetBody: { CMD_PARAM(BeType*, type); CMD_PARAM(CmdParamVec, members); CMD_PARAM(int, instSize); CMD_PARAM(int, instAlign); CMD_PARAM(bool, isPacked); if ((type == NULL) || (type->mTypeCode != BeTypeCode_Struct)) { Fail("StructSetBody invalid type"); break; } bool failed = false; for (auto member : members) { if (member->mSize < 0) { Fail("StructSetBody invalid member type"); failed = true; } } if (!failed) { BF_ASSERT(type->mTypeCode == BeTypeCode_Struct); auto structType = (BeStructType*)type; mBeContext->SetStructBody(structType, members, isPacked); structType->mSize = instSize; structType->mAlign = instAlign; } } break; case BfIRCmd_Type: { CMD_PARAM(BeIRTypeEntry*, typeEntry); auto type = typeEntry->mBeType; SetResult(curId, type); } break; case BfIRCmd_TypeInst: { CMD_PARAM(BeIRTypeEntry*, typeEntry); SetResult(curId, typeEntry->mInstBeType); } break; case BfIRCmd_TypeInstPtr: { CMD_PARAM(BeIRTypeEntry*, typeEntry); SetResult(curId, mBeContext->GetPointerTo(typeEntry->mInstBeType)); } break; case BfIRCmd_GetType: { CMD_PARAM(BeValue*, value); auto type = value->GetType(); SetResult(curId, type); } break; case BfIRCmd_GetPointerToFuncType: { CMD_PARAM(BeFunctionType*, funcType); SetResult(curId, mBeContext->GetPointerTo(funcType)); } break; case BfIRCmd_GetPointerToType: { CMD_PARAM(BeType*, type); SetResult(curId, mBeContext->GetPointerTo(type)); } break; case BfIRCmd_GetSizedArrayType: { CMD_PARAM(BeType*, elementType); CMD_PARAM(int, length); SetResult(curId, mBeContext->CreateSizedArrayType(elementType, length)); } break; case BfIRCmd_GetVectorType: { CMD_PARAM(BeType*, elementType); CMD_PARAM(int, length); SetResult(curId, mBeContext->CreateVectorType(elementType, length)); } break; case BfIRCmd_CreateConstAgg: { CMD_PARAM(BeType*, type); CMD_PARAM(CmdParamVec, values); auto constStruct = mBeModule->mOwnedValues.Alloc(); constStruct->mType = type; if (type->IsStruct()) { FixValues((BeStructType*)type, values); BF_ASSERT(((BeStructType*)type)->mMembers.size() == values.size()); for (int i = 0; i < (int)values.size(); i++) { auto val = values[i]; BF_ASSERT(mBeContext->AreTypesEqual(((BeStructType*)type)->mMembers[i].mType, val->GetType())); constStruct->mMemberValues.push_back(BeValueDynCast(val)); } } else { BF_ASSERT(type->IsSizedArray()); auto arrayType = (BeSizedArrayType*)type; int fillCount = (int)(arrayType->mLength - values.size()); if (fillCount > 0) { auto lastValue = values.back(); for (int i = 0; i < fillCount; i++) values.push_back(lastValue); } BF_ASSERT(arrayType->mLength == values.size()); for (int i = 0; i < (int)values.size(); i++) { auto val = values[i]; BF_ASSERT(mBeContext->AreTypesEqual(((BeSizedArrayType*)type)->mElementType, val->GetType())); constStruct->mMemberValues.push_back(BeValueDynCast(val)); } } SetResult(curId, constStruct); } break; case BfIRCmd_CreateConstStructZero: { CMD_PARAM(BeType*, type); auto beConst = mBeModule->mAlloc.Alloc(); beConst->mType = type; SetResult(curId, beConst); } break; case BfIRCmd_CreateConstString: { CMD_PARAM(String, str); auto constStruct = mBeModule->mOwnedValues.Alloc(); constStruct->mString = str; auto charType = mBeContext->GetPrimitiveType(BeTypeCode_Int8); constStruct->mType = mBeContext->CreateSizedArrayType(charType, str.length() + 1); SetResult(curId, constStruct); } break; case BfIRCmd_ConfigConst: { CMD_PARAM(int, constIdx); BfTypeCode typeCode = (BfTypeCode)mStream->Read(); if (typeCode == BfTypeCode_IntPtr) typeCode = (mPtrSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64; BeConstant* constVal = (typeCode == BfTypeCode_Int32) ? mBeModule->mConfigConsts32[constIdx] : mBeModule->mConfigConsts64[constIdx]; SetResult(curId, constVal); } break; case BfIRCmd_SetName: { CMD_PARAM(BeValue*, val); CMD_PARAM(String, name); val->SetName(name); } break; case BfIRCmd_CreateUndefValue: { CMD_PARAM(BeType*, type); SetResult(curId, mBeModule->CreateUndefValue(type)); } break; case BfIRCmd_NumericCast: { CMD_PARAM(BeValue*, val); CMD_PARAM(bool, valIsSigned); BfTypeCode typeCode = (BfTypeCode)mStream->Read(); auto valType = val->GetType(); if ((!valType->IsIntable()) && (!valType->IsFloat())) { Fail("Invalid NumericCast target"); } BfTypeCode valTypeCode = GetTypeCode(valType, valIsSigned); if (auto srcCastConstant = BeValueDynCast(val)) { BeType* toType = GetBeType(typeCode, valIsSigned); auto castedVal = mBeModule->mAlloc.Alloc(); castedVal->mInt64 = srcCastConstant->mInt64; castedVal->mType = toType; castedVal->mTarget = srcCastConstant->mTarget; SetResult(curId, castedVal); break; } bool toSigned = false; auto toBeType = GetBeType(typeCode, toSigned); BeValue* retVal = mBeModule->CreateNumericCast(val, toBeType, valIsSigned, toSigned); SetResult(curId, retVal); } break; case BfIRCmd_CmpEQ: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); if (lhs->GetType() != rhs->GetType()) Fail("Type mismatch for CmpEQ"); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_EQ, lhs, rhs)); } break; case BfIRCmd_CmpNE: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_NE, lhs, rhs)); } break; case BfIRCmd_CmpSLT: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_SLT, lhs, rhs)); } break; case BfIRCmd_CmpULT: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_ULT, lhs, rhs)); } break; case BfIRCmd_CmpSLE: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_SLE, lhs, rhs)); } break; case BfIRCmd_CmpULE: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_ULE, lhs, rhs)); } break; case BfIRCmd_CmpSGT: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_SGT, lhs, rhs)); } break; case BfIRCmd_CmpUGT: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_UGT, lhs, rhs)); } break; case BfIRCmd_CmpSGE: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_SGE, lhs, rhs)); } break; case BfIRCmd_CmpUGE: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_UGE, lhs, rhs)); } break; case BfIRCmd_Add: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); CMD_PARAM(int8, overflowCheckKind); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_Add, lhs, rhs, (BfOverflowCheckKind)overflowCheckKind)); } break; case BfIRCmd_Sub: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); CMD_PARAM(int8, overflowCheckKind); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_Subtract, lhs, rhs, (BfOverflowCheckKind)overflowCheckKind)); } break; case BfIRCmd_Mul: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); CMD_PARAM(int8, overflowCheckKind); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_Multiply, lhs, rhs, (BfOverflowCheckKind)overflowCheckKind)); } break; case BfIRCmd_SDiv: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_SDivide, lhs, rhs)); } break; case BfIRCmd_UDiv: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_UDivide, lhs, rhs)); } break; case BfIRCmd_SRem: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_SModulus, lhs, rhs)); } break; case BfIRCmd_URem: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_UModulus, lhs, rhs)); } break; case BfIRCmd_And: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_BitwiseAnd, lhs, rhs)); } break; case BfIRCmd_Or: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_BitwiseOr, lhs, rhs)); } break; case BfIRCmd_Xor: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_ExclusiveOr, lhs, rhs)); } break; case BfIRCmd_Shl: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_LeftShift, lhs, rhs)); } break; case BfIRCmd_AShr: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_ARightShift, lhs, rhs)); } break; case BfIRCmd_LShr: { CMD_PARAM(BeValue*, lhs); CMD_PARAM(BeValue*, rhs); SetResult(curId, mBeModule->CreateBinaryOp(BeBinaryOpKind_RightShift, lhs, rhs)); } break; case BfIRCmd_Neg: { CMD_PARAM(BeValue*, val); auto negInst = mBeModule->AllocInst(); negInst->mValue = val; SetResult(curId, negInst); } break; case BfIRCmd_Not: { CMD_PARAM(BeValue*, val); auto negInst = mBeModule->AllocInst(); negInst->mValue = val; SetResult(curId, negInst); } break; case BfIRCmd_BitCast: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeType*, toType); if (auto funcVal = BeValueDynCast(val)) { auto beConst = mBeModule->mAlloc.Alloc(); beConst->mTarget = funcVal; BF_ASSERT(funcVal->mType != NULL); beConst->mType = toType; SetResult(curId, beConst); break; } SetResult(curId, mBeModule->CreateBitCast(val, toType)); } break; case BfIRCmd_PtrToInt: { CMD_PARAM(BeValue*, val); auto typeCode = (BfTypeCode)mStream->Read(); bool isSigned = false; auto beType = GetBeType(typeCode, isSigned); BF_ASSERT(beType != NULL); auto numericCastInst = mBeModule->AllocInst(); numericCastInst->mValue = val; numericCastInst->mValSigned = false; numericCastInst->mToType = beType; numericCastInst->mToSigned = isSigned; SetResult(curId, numericCastInst); } break; case BfIRCmd_IntToPtr: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeType*, toType); auto bitcastInst = mBeModule->AllocInst(); bitcastInst->mValue = val; bitcastInst->mToType = toType; SetResult(curId, bitcastInst); } break; case BfIRCmd_InboundsGEP1_32: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, idx0); BF_ASSERT(val->GetType()->IsPointer()); BeType* int32Type = mBeContext->GetPrimitiveType(BeTypeCode_Int32); SetResult(curId, mBeModule->CreateGEP(val, mBeModule->GetConstant(int32Type, (int64)idx0), NULL)); } break; case BfIRCmd_InboundsGEP2_32: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, idx0); CMD_PARAM(int, idx1); BF_ASSERT(val->GetType()->IsPointer()); BeType* int32Type = mBeContext->GetPrimitiveType(BeTypeCode_Int32); SetResult(curId, mBeModule->CreateGEP(val, mBeModule->GetConstant(int32Type, (int64)idx0), mBeModule->GetConstant(int32Type, (int64)idx1))); } break; case BfIRCmd_InBoundsGEP1: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeValue*, idx0); BF_ASSERT(val->GetType()->IsPointer()); SetResult(curId, mBeModule->CreateGEP(val, idx0, NULL)); } break; case BfIRCmd_InBoundsGEP2: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeValue*, idx0); CMD_PARAM(BeValue*, idx1); BF_ASSERT(val->GetType()->IsPointer()); SetResult(curId, mBeModule->CreateGEP(val, idx0, idx1)); } break; case BfIRCmd_IsNull: { CMD_PARAM(BeValue*, val); BF_ASSERT(val->GetType()->IsPointer()); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_EQ, val, mBeModule->GetConstantNull((BePointerType*)val->GetType()))); } break; case BfIRCmd_IsNotNull: { CMD_PARAM(BeValue*, val); BF_ASSERT(val->GetType()->IsPointer()); SetResult(curId, mBeModule->CreateCmp(BeCmpKind_NE, val, mBeModule->GetConstantNull((BePointerType*)val->GetType()))); } break; case BfIRCmd_ExtractValue: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, idx); BF_ASSERT(val->GetType()->IsComposite()); auto extractValueInst = mBeModule->AllocInst(); extractValueInst->mAggVal = val; extractValueInst->mIdx = idx; SetResult(curId, extractValueInst); } break; case BfIRCmd_InsertValue: { CMD_PARAM(BeValue*, agg); CMD_PARAM(BeValue*, val); CMD_PARAM(int, idx); auto insertValueInst = mBeModule->AllocInst(); insertValueInst->mAggVal = agg; insertValueInst->mMemberVal = val; insertValueInst->mIdx = idx; SetResult(curId, insertValueInst); } break; case BfIRCmd_Alloca: { CMD_PARAM(BeType*, type); if (type->IsStruct()) { BF_ASSERT(!((BeStructType*)type)->mIsOpaque); } auto allocaInst = mBeModule->CreateAlloca(type); allocaInst->mAlign = type->mAlign; SetResult(curId, allocaInst); } break; case BfIRCmd_AllocaArray: { CMD_PARAM(BeType*, type); CMD_PARAM(BeValue*, arraySize); if (auto constant = BeValueDynCast(arraySize)) { //BF_ASSERT(constant->mInt64 >= 0); } auto allocaInst = mBeModule->AllocInst(); allocaInst->mType = type; allocaInst->mAlign = type->mAlign; allocaInst->mArraySize = arraySize; SetResult(curId, allocaInst); } break; case BfIRCmd_SetAllocaAlignment: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, alignment); auto inst = BeValueDynCast(val); inst->mAlign = alignment; //TODO: Implement /*inst->setAlignment(alignment);*/ } break; case BfIRCmd_AliasValue: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mPtr = val; SetResult(curId, inst); } break; case BfIRCmd_LifetimeStart: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mPtr = val; SetResult(curId, inst); } break; case BfIRCmd_LifetimeEnd: { CMD_PARAM(BeValue*, val); #ifdef _DEBUG val->mLifetimeEnded = true; #endif auto inst = mBeModule->AllocInst(); inst->mPtr = val; SetResult(curId, inst); } break; case BfIRCmd_LifetimeSoftEnd: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mPtr = val; SetResult(curId, inst); } break; case BfIRCmd_LifetimeExtend: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mPtr = val; SetResult(curId, inst); } break; case BfIRCmd_ValueScopeStart: { auto inst = mBeModule->AllocInst(); SetResult(curId, inst); } break; case BfIRCmd_ValueScopeRetain: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mValue = val; } break; case BfIRCmd_ValueScopeSoftEnd: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mScopeStart = (BeValueScopeStartInst*)val; inst->mIsSoft = true; //TODO: Is this always correct? This keeps there from being nops inserted on block opens ( { ) inst->mDbgLoc = NULL; } break; case BfIRCmd_ValueScopeHardEnd: { CMD_PARAM(BeValue*, val); auto inst = mBeModule->AllocInst(); inst->mScopeStart = (BeValueScopeStartInst*)val; inst->mIsSoft = false; //TODO: Is this always correct? This keeps there from being nops inserted on block opens ( { ) inst->mDbgLoc = NULL; } break; case BfIRCmd_SetAllocaNoChkStkHint: { CMD_PARAM(BeValue*, val); auto inst = BeValueDynCast(val); inst->mNoChkStk = true; } break; case BfIRCmd_SetAllocaForceMem: { CMD_PARAM(BeValue*, val); auto inst = BeValueDynCast(val); inst->mForceMem = true; } break; case BfIRCmd_Load: { CMD_PARAM(BeValue*, val); #ifdef _DEBUG auto ptrType = val->GetType(); BF_ASSERT(ptrType->IsPointer()); // We call via a function pointer so there's never a reason to allow loading of a funcPtr BF_ASSERT(((BePointerType*)ptrType)->mElementType->mTypeCode != BeTypeCode_Function); // Disallow loading from a NULL constant if (val->GetTypeId() == BeConstant::TypeId) { if (auto constant = BeValueDynCast(val)) { BF_ASSERT(constant->mTarget != NULL); } } #endif CMD_PARAM(bool, isVolatile); SetResult(curId, mBeModule->CreateLoad(val, isVolatile)); } break; case BfIRCmd_AlignedLoad: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, alignment); CMD_PARAM(bool, isVolatile); #ifdef _DEBUG // Disallow loading from a NULL constant if (val->GetTypeId() == BeConstant::TypeId) { if (auto constant = BeValueDynCast(val)) { BF_ASSERT(constant->mTarget != NULL); } } auto ptrType = val->GetType(); BF_ASSERT(ptrType->IsPointer()); #endif SetResult(curId, mBeModule->CreateAlignedLoad(val, alignment, isVolatile)); } break; case BfIRCmd_Store: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeValue*, ptr); #ifdef _DEBUG auto ptrType = ptr->GetType(); auto valType = val->GetType(); if ((!ptrType->IsPointer()) || (!mBeContext->AreTypesEqual(((BePointerType*)ptrType)->mElementType, valType))) { String errStr; errStr += "BfIRCmd_Store Match Failure:\n"; BeDumpContext dumpCtx; errStr += "Val: "; dumpCtx.ToString(errStr, val); errStr += "\nPtr: "; dumpCtx.ToString(errStr, ptr); FatalError(errStr); } #endif CMD_PARAM(bool, isVolatile); SetResult(curId, mBeModule->CreateStore(val, ptr, isVolatile)); } break; case BfIRCmd_AlignedStore: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeValue*, ptr); CMD_PARAM(int, alignment); CMD_PARAM(bool, isVolatile); #ifdef _DEBUG auto ptrType = ptr->GetType(); auto valType = val->GetType(); if ((!ptrType->IsPointer()) || (!mBeContext->AreTypesEqual(((BePointerType*)ptrType)->mElementType, valType))) { String errStr; errStr += "BfIRCmd_Store Match Failure:\n"; BeDumpContext dumpCtx; errStr += "Val: "; dumpCtx.ToString(errStr, val); errStr += "\nPtr: "; dumpCtx.ToString(errStr, ptr); FatalError(errStr); } #endif SetResult(curId, mBeModule->CreateAlignedStore(val, ptr, alignment, isVolatile)); } break; case BfIRCmd_MemSet: { auto inst = mBeModule->AllocInst(); Read(inst->mAddr); Read(inst->mVal); Read(inst->mSize); Read(inst->mAlignment); SetResult(curId, inst); } break; case BfIRCmd_Fence: { BfIRFenceType fenceType = (BfIRFenceType)mStream->Read(); mBeModule->AllocInst(); } break; case BfIRCmd_StackSave: { SetResult(curId, mBeModule->AllocInst()); } break; case BfIRCmd_StackRestore: { CMD_PARAM(BeValue*, stackVal); auto stackRestoreInst = mBeModule->AllocInst(); stackRestoreInst->mStackVal = stackVal; SetResult(curId, stackRestoreInst); } break; case BfIRCmd_GlobalVariable: { CMD_PARAM(BeType*, varType); CMD_PARAM(bool, isConstant); BfIRLinkageType linkageType = (BfIRLinkageType)mStream->Read(); CMD_PARAM(StringT<256>, name); CMD_PARAM(bool, isTLS); CMD_PARAM(BeConstant*, initializer); BF_ASSERT(varType != NULL); auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; globalVariable->mType = varType; globalVariable->mIsConstant = isConstant; globalVariable->mLinkageType = linkageType; globalVariable->mInitializer = initializer; globalVariable->mName = name; globalVariable->mIsTLS = isTLS; globalVariable->mUnnamedAddr = false; globalVariable->mStorageKind = BfIRStorageKind_Normal; if (initializer != NULL) { globalVariable->mAlign = varType->mAlign; BF_ASSERT(varType->mAlign > 0); BF_ASSERT(mBeContext->AreTypesEqual(varType, initializer->GetType())); } else globalVariable->mAlign = -1; SetResult(curId, globalVariable); } break; case BfIRCmd_GlobalVar_SetUnnamedAddr: { CMD_PARAM(BeValue*, val); CMD_PARAM(bool, unnamedAddr); BF_ASSERT(BeValueDynCast(val) != NULL); ((BeGlobalVariable*)val)->mUnnamedAddr = true; } break; case BfIRCmd_GlobalVar_SetInitializer: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeConstant*, initializer); BF_ASSERT(BeValueDynCast(val) != NULL); auto globalVariable = (BeGlobalVariable*)val; globalVariable->mInitializer = initializer; if (globalVariable->mInitializer != NULL) { globalVariable->mAlign = globalVariable->mType->mAlign; BF_ASSERT(globalVariable->mAlign != -1); } } break; case BfIRCmd_GlobalVar_SetAlignment: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, alignment); BF_ASSERT(BeValueDynCast(val) != NULL); auto globalVariable = (BeGlobalVariable*)val; globalVariable->mAlign = alignment; BF_ASSERT(alignment > 0); if (globalVariable->mInitializer != NULL) { BF_ASSERT(globalVariable->mAlign != -1); } } break; case BfIRCmd_GlobalVar_SetStorageKind: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, storageKind); BF_ASSERT(BeValueDynCast(val) != NULL); auto globalVariable = (BeGlobalVariable*)val; globalVariable->mStorageKind = (BfIRStorageKind)storageKind; } break; case BfIRCmd_GlobalStringPtr: { CMD_PARAM(String, str); auto constStruct = mBeModule->mOwnedValues.Alloc(); constStruct->mString = str; auto charType = mBeContext->GetPrimitiveType(BeTypeCode_Int8); constStruct->mType = mBeContext->CreateSizedArrayType(charType, str.length() + 1); auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; globalVariable->mType = constStruct->mType; globalVariable->mIsConstant = true; globalVariable->mLinkageType = BfIRLinkageType_Internal; globalVariable->mInitializer = constStruct; globalVariable->mName = StrFormat("__str%d", (int)mBeModule->mGlobalVariables.size() - 1); globalVariable->mIsTLS = false; globalVariable->mAlign = 1; globalVariable->mUnnamedAddr = false; auto castedVal = mBeModule->mAlloc.Alloc(); castedVal->mType = mBeContext->GetPointerTo(charType); castedVal->mTarget = globalVariable; SetResult(curId, castedVal); //SetResult(curId, globalVariable); } break; case BfIRCmd_SetReflectTypeData: { CMD_PARAM(BeType*, type); CMD_PARAM(BeValue*, value); mReflectDataMap[type] = value; } break; case BfIRCmd_CreateBlock: { CMD_PARAM(String, name); CMD_PARAM(bool, addNow); auto block = mBeModule->CreateBlock(name); if (addNow) mBeModule->AddBlock(mActiveFunction, block); SetResult(curId, block); } break; case BfIRCmd_MaybeChainNewBlock: { CMD_PARAM(String, name); auto newBlock = mBeModule->GetInsertBlock(); if (!newBlock->IsEmpty()) { auto bb = mBeModule->CreateBlock(name); mBeModule->CreateBr(bb); mBeModule->AddBlock(mActiveFunction, bb); mBeModule->SetInsertPoint(bb); newBlock = bb; } SetResult(curId, newBlock); } break; case BfIRCmd_AddBlock: { CMD_PARAM(BeBlock*, block); mBeModule->AddBlock(mActiveFunction, block); } break; case BfIRCmd_DropBlocks: { CMD_PARAM(BeBlock*, startingBlock); auto& basicBlockList = mActiveFunction->mBlocks; int postExitBlockIdx = -1; /*auto itr = basicBlockList.begin(); while (itr != basicBlockList.end()) { auto block = *itr; if (block == startingBlock) { basicBlockList.erase(itr, basicBlockList.end()); break; } ++itr; }*/ for (int i = 0; i < (int)basicBlockList.size(); i++) { if (basicBlockList[i] == startingBlock) { basicBlockList.RemoveRange(i, basicBlockList.size() - i); break; } } } break; case BfIRCmd_MergeBlockDown: { CMD_PARAM(BeBlock*, fromBlock); CMD_PARAM(BeBlock*, intoBlock); for (auto inst : fromBlock->mInstructions) inst->mParentBlock = intoBlock; if (!fromBlock->mInstructions.IsEmpty()) intoBlock->mInstructions.Insert(0, &fromBlock->mInstructions[0], fromBlock->mInstructions.size()); mBeModule->RemoveBlock(mActiveFunction, fromBlock); } break; case BfIRCmd_GetInsertBlock: { SetResult(curId, mBeModule->mActiveBlock); } break; case BfIRCmd_SetInsertPoint: { CMD_PARAM(BeBlock*, block); mBeModule->SetInsertPoint(block); } break; case BfIRCmd_SetInsertPointAtStart: { CMD_PARAM(BeBlock*, block); mBeModule->SetInsertPointAtStart(block); } break; case BfIRCmd_EraseFromParent: { CMD_PARAM(BeBlock*, block); mBeModule->RemoveBlock(mActiveFunction, block); } break; case BfIRCmd_DeleteBlock: { CMD_PARAM(BeBlock*, block); } break; case BfIRCmd_EraseInstFromParent: { CMD_PARAM(BeValue*, instVal); BeInst* inst = (BeInst*)instVal; bool wasRemoved = inst->mParentBlock->mInstructions.Remove(inst); BF_ASSERT(wasRemoved); #ifdef _DEBUG inst->mWasRemoved = true; #endif } break; case BfIRCmd_CreateBr: { CMD_PARAM(BeBlock*, block); mBeModule->CreateBr(block); } break; case BfIRCmd_CreateBr_Fake: { CMD_PARAM(BeBlock*, block); auto inst = mBeModule->CreateBr(block); inst->mIsFake = true; } break; case BfIRCmd_CreateBr_NoCollapse: { CMD_PARAM(BeBlock*, block); auto inst = mBeModule->CreateBr(block); inst->mNoCollapse = true; } break; case BfIRCmd_CreateCondBr: { CMD_PARAM(BeValue*, condVal); CMD_PARAM(BeBlock*, trueBlock); CMD_PARAM(BeBlock*, falseBlock); mBeModule->CreateCondBr(condVal, trueBlock, falseBlock); } break; case BfIRCmd_MoveBlockToEnd: { CMD_PARAM(BeBlock*, block); mBeModule->RemoveBlock(mActiveFunction, block); mBeModule->AddBlock(mActiveFunction, block); } break; case BfIRCmd_CreateSwitch: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeBlock*, dest); CMD_PARAM(int, numCases); auto switchInst = mBeModule->AllocInstOwned(); switchInst->mValue = val; switchInst->mDefaultBlock = dest; switchInst->mCases.Reserve(numCases); SetResult(curId, switchInst); } break; case BfIRCmd_AddSwitchCase: { CMD_PARAM(BeValue*, switchVal); CMD_PARAM(BeValue*, caseVal); CMD_PARAM(BeBlock*, caseBlock); BeSwitchCase switchCase; switchCase.mValue = (BeConstant*)caseVal; switchCase.mBlock = caseBlock; ((BeSwitchInst*)switchVal)->mCases.push_back(switchCase); } break; case BfIRCmd_SetSwitchDefaultDest: { CMD_PARAM(BeValue*, switchVal); CMD_PARAM(BeBlock*, caseBlock); ((BeSwitchInst*)switchVal)->mDefaultBlock = caseBlock; } break; case BfIRCmd_CreatePhi: { CMD_PARAM(BeType*, type); CMD_PARAM(int, incomingCount); auto phiInst = mBeModule->AllocInstOwned(); phiInst->mType = type; SetResult(curId, phiInst); } break; case BfIRCmd_AddPhiIncoming: { CMD_PARAM(BeValue*, phiValue); CMD_PARAM(BeValue*, value); CMD_PARAM(BeBlock*, comingFrom); if (phiValue->GetType() != value->GetType()) { Fail("AddPhiIncoming type mismatch"); break; } auto phiIncoming = mBeModule->mAlloc.Alloc(); phiIncoming->mBlock = comingFrom; phiIncoming->mValue = value; ((BePhiInst*)phiValue)->mIncoming.push_back(phiIncoming); } break; case BfIRCmd_GetIntrinsic: { CMD_PARAM(String, intrinName); CMD_PARAM(int, intrinId); CMD_PARAM(BeType*, returnType); CMD_PARAM(CmdParamVec, paramTypes); auto intrin = mBeModule->mAlloc.Alloc(); intrin->mName = intrinName; intrin->mKind = (BfIRIntrinsic)intrinId; intrin->mReturnType = returnType; SetResult(curId, intrin); } break; case BfIRCmd_CreateFunctionType: { CMD_PARAM(BeType*, resultType); CMD_PARAM(CmdParamVec, paramTypes); CMD_PARAM(bool, isVarArg); auto functionType = mBeContext->CreateFunctionType(resultType, paramTypes, isVarArg); SetResult(curId, functionType); } break; case BfIRCmd_CreateFunction: { CMD_PARAM(BeFunctionType*, type); BfIRLinkageType linkageType = (BfIRLinkageType)mStream->Read(); CMD_PARAM(String, name); SetResult(curId, mBeModule->CreateFunction(type, linkageType, name)); } break; case BfIRCmd_SetFunctionName: { CMD_PARAM(BeValue*, func); CMD_PARAM(String, name); BeFunction* beFunc = BeValueDynCast(func); beFunc->mName = name; } break; case BfIRCmd_EnsureFunctionPatchable: { } break; case BfIRCmd_RemapBindFunction: { CMD_PARAM(BeValue*, func); // We need to store this value to a data segment so we get a symbol we can remap during hot swap // We actually do this to ensure that we don't bind to the NEW method but rather the old one- so // delegate equality checks still work BeFunction* beFunc = BeValueDynCast(func); if (beFunc != NULL) { if (beFunc->mRemapBindVar == NULL) { auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; globalVariable->mType = beFunc->mType; globalVariable->mIsConstant = true; globalVariable->mLinkageType = BfIRLinkageType_External; globalVariable->mInitializer = beFunc; globalVariable->mName = StrFormat("bf_hs_preserve@%s_%s", beFunc->mName.c_str(), mBeModule->mModuleName.c_str()); globalVariable->mIsTLS = false; globalVariable->mAlign = 8; globalVariable->mUnnamedAddr = false; beFunc->mRemapBindVar = globalVariable; /*if (mBeModule->mDbgModule != NULL) { auto dbgGlobalVariable = mBeModule->mDbgModule->mGlobalVariables.Alloc(); dbgGlobalVariable->mContext = mBeContext; dbgGlobalVariable->mName = name; dbgGlobalVariable->mLinkageName = globalVariable->mName; dbgGlobalVariable->mFile = (BeDbgFile*)file; dbgGlobalVariable->mLineNum = lineNum; dbgGlobalVariable->mType = (BeDbgType*)type; dbgGlobalVariable->mIsLocalToUnit = isLocalToUnit; dbgGlobalVariable->mValue = val; dbgGlobalVariable->mDecl = decl; }*/ } SetResult(curId, mBeModule->CreateLoad(beFunc->mRemapBindVar, false)); } else SetResult(curId, func); } break; case BfIRCmd_SetActiveFunction: { CMD_PARAM(BeFunction*, func); mActiveFunction = func; mBeModule->mActiveFunction = func; } break; case BfIRCmd_CreateCall: { CMD_PARAM(BeValue*, func); CMD_PARAM(CmdParamVec, args); #ifdef BE_EXTRA_CHECKS auto funcPtrType = func->GetType(); if (funcPtrType != NULL) { BF_ASSERT(funcPtrType->IsPointer()); auto funcType = (BeFunctionType*)((BePointerType*)funcPtrType)->mElementType; BF_ASSERT(funcType->mTypeCode == BeTypeCode_Function); bool argsMatched = true; if (!funcType->mIsVarArg) { if (funcType->mParams.size() != args.size()) { argsMatched = false; } else { int argIdx = 0; for (int argIdx = 0; argIdx < (int)args.size(); argIdx++) { if (args[argIdx] == NULL) argsMatched = false; else if (funcType->mParams[argIdx].mType != args[argIdx]->GetType()) argsMatched = false; } } } if (!argsMatched) { String errStr; errStr += "BfIRCmd_CreateCall Match Failure:\n"; BeDumpContext dumpCtx; dumpCtx.ToString(errStr, func); errStr += "\n"; dumpCtx.ToString(errStr, funcType); errStr += "\n"; for (int argIdx = 0; argIdx < (int)args.size(); argIdx++) { errStr += StrFormat("ARG #%d: ", argIdx); dumpCtx.ToString(errStr, args[argIdx]); errStr += "\n"; } FatalError(errStr); } } else { BF_ASSERT(func->GetTypeId() == BeIntrinsic::TypeId); } #endif SetResult(curId, mBeModule->CreateCall(func, args)); } break; case BfIRCmd_SetCallCallingConv: { CMD_PARAM(BeValue*, callInst); BfIRCallingConv callingConv = (BfIRCallingConv)mStream->Read(); ((BeCallInst*)callInst)->mCallingConv = callingConv; } break; case BfIRCmd_SetFuncCallingConv: { CMD_PARAM(BeFunction*, func); BfIRCallingConv callingConv = (BfIRCallingConv)mStream->Read(); func->mCallingConv = callingConv; } break; case BfIRCmd_SetTailCall: { CMD_PARAM(BeValue*, callInstVal); BeCallInst* callInst = (BeCallInst*)callInstVal; callInst->mTailCall = true; } break; case BfIRCmd_SetCallAttribute: { CMD_PARAM(BeValue*, callInstVal); CMD_PARAM(int, paramIdx); BfIRAttribute attribute = (BfIRAttribute)mStream->Read(); BeCallInst* callInst = (BeCallInst*)callInstVal; if (attribute == BfIRAttribute_NoReturn) callInst->mNoReturn = true; } break; case BfIRCmd_CreateRet: { CMD_PARAM(BeValue*, val); #ifdef BE_EXTRA_CHECKS auto retType = val->GetType(); auto funcType = mActiveFunction->GetFuncType(); BF_ASSERT(retType == funcType->mReturnType); #endif SetResult(curId, mBeModule->CreateRet(val)); } break; case BfIRCmd_CreateSetRet: { CMD_PARAM(BeValue*, val); CMD_PARAM(int, returnTypeId); SetResult(curId, mBeModule->CreateSetRet(val, returnTypeId)); } break; case BfIRCmd_CreateRetVoid: { mBeModule->CreateRetVoid(); } break; case BfIRCmd_CreateUnreachable: { mBeModule->AllocInst(); } break; case BfIRCmd_Call_AddAttribute: { CMD_PARAM(BeValue*, callInstVal); CMD_PARAM(int, argIdx); BfIRAttribute attribute = (BfIRAttribute)mStream->Read(); BeCallInst* callInst = (BeCallInst*)callInstVal; if (argIdx > 0) { if (attribute == BfIRAttribute_StructRet) { auto valType = callInst->mArgs[argIdx - 1].mValue->GetType(); BF_ASSERT(valType->IsPointer()); callInst->mArgs[argIdx - 1].mStructRet = true; } else if (attribute == BfIRAttribute_ZExt) callInst->mArgs[argIdx - 1].mZExt = true; else if (attribute == BfIRAttribute_NoAlias) callInst->mArgs[argIdx - 1].mNoAlias = true; else if (attribute == BfIRAttribute_NoCapture) callInst->mArgs[argIdx - 1].mNoCapture = true; else if (attribute == BfIRAttribute_ByVal) { } else BF_FATAL("Unhandled"); } else { if (attribute == BfIRAttribute_NoReturn) callInst->mNoReturn = true; else BF_FATAL("Unhandled"); } } break; case BfIRCmd_Call_AddAttribute1: { CMD_PARAM(BeValue*, inst); CMD_PARAM(int, argIdx); BfIRAttribute attribute = (BfIRAttribute)mStream->Read(); CMD_PARAM(int, arg); BeCallInst* callInst = BeValueDynCast(inst); if (callInst != NULL) { if (argIdx > 0) { if (attribute == BfIRAttribute_Dereferencable) { callInst->mArgs[argIdx - 1].mDereferenceableSize = arg; if (auto func = BeValueDynCast(callInst->mFunc)) { BF_ASSERT(func->mParams[argIdx - 1].mDereferenceableSize == arg); } } else if (attribute == BfIRAttribute_ByVal) { callInst->mArgs[argIdx - 1].mByRefSize = arg; if (auto func = BeValueDynCast(callInst->mFunc)) { BF_ASSERT((func->mParams[argIdx - 1].mByValSize == arg) || (func->mParams[argIdx - 1].mByValSize == -1)); } } else BF_FATAL("Unhandled"); } else { BF_FATAL("Unhandled"); } } } break; case BfIRCmd_Func_AddAttribute: { CMD_PARAM(BeFunction*, func); CMD_PARAM(int, argIdx); BfIRAttribute attribute = (BfIRAttribute)mStream->Read(); if (argIdx > 0) { if (attribute == BfIRAttribute_StructRet) func->mParams[argIdx - 1].mStructRet = true; else if (attribute == BfIRAttribute_NoAlias) func->mParams[argIdx - 1].mNoAlias = true; else if (attribute == BfIRAttribute_NoCapture) func->mParams[argIdx - 1].mNoCapture = true; else if (attribute == BfIRAttribute_ZExt) func->mParams[argIdx - 1].mZExt = true; else BF_FATAL("Unhandled"); } else { if (attribute == BfIRAttribute_VarRet) func->mIsVarReturn = true; else if (attribute == BFIRAttribute_AlwaysInline) func->mAlwaysInline = true; else if (attribute == BFIRAttribute_NoUnwind) func->mNoUnwind = true; else if (attribute == BFIRAttribute_UWTable) func->mUWTable = true; else if (attribute == BfIRAttribute_NoReturn) func->mNoReturn = true; else if (attribute == BFIRAttribute_NoFramePointerElim) func->mNoFramePointerElim = true; else if (attribute == BFIRAttribute_DllExport) func->mIsDLLExport = true; else if (attribute == BFIRAttribute_DllImport) func->mIsDLLImport = true; else if (attribute == BFIRAttribute_NoRecurse) { } else if (attribute == BFIRAttribute_Constructor) { } else if (attribute == BFIRAttribute_Destructor) { } else BF_FATAL("Unhandled"); } } break; case BfIRCmd_Func_AddAttribute1: { CMD_PARAM(BeFunction*, func); CMD_PARAM(int, argIdx); BfIRAttribute attribute = (BfIRAttribute)mStream->Read(); CMD_PARAM(int, arg); // This is for adding things like Dereferencable, which we don't use if (argIdx > 0) { if (attribute == BfIRAttribute_Dereferencable) func->mParams[argIdx - 1].mDereferenceableSize = arg; else if (attribute == BfIRAttribute_ByVal) func->mParams[argIdx - 1].mByValSize = arg; else BF_FATAL("Unhandled"); } else BF_FATAL("Unhandled"); } break; case BfIRCmd_Func_SetParamName: { CMD_PARAM(BeFunction*, func); CMD_PARAM(int, argIdx); CMD_PARAM(String, name); if (argIdx > 0) func->mParams[argIdx - 1].mName = name; } break; case BfIRCmd_Func_DeleteBody: { CMD_PARAM(BeFunction*, func); func->mBlocks.Clear(); } break; case BfIRCmd_Func_SafeRename: { CMD_PARAM(BeFunction*, func); func->mName += StrFormat("__RENAME%d", curId); } break; case BfIRCmd_Func_SafeRenameFrom: { CMD_PARAM(BeFunction*, func); CMD_PARAM(String, prevName); if (func->mName == prevName) func->mName += StrFormat("__RENAME%d", curId); } break; case BfIRCmd_Func_SetLinkage: { CMD_PARAM(BeFunction*, func); BfIRLinkageType linkageType = (BfIRLinkageType)mStream->Read(); func->mLinkageType = linkageType; } break; case BfIRCmd_SaveDebugLocation: { mSavedDebugLocs.push_back(mBeModule->GetCurrentDebugLocation()); } break; case BfIRCmd_RestoreDebugLocation: { mBeModule->SetCurrentDebugLocation(mSavedDebugLocs[mSavedDebugLocs.size() - 1]); mSavedDebugLocs.pop_back(); } break; case BfIRCmd_DupDebugLocation: { mBeModule->DupCurrentDebugLocation(); } break; case BfIRCmd_ClearDebugLocation: { mBeModule->SetCurrentDebugLocation(NULL); } break; case BfIRCmd_ClearDebugLocationInst: { CMD_PARAM(BeValue*, instValue); auto inst = (BeInst*)instValue; inst->mDbgLoc = NULL; } break; case BfIRCmd_ClearDebugLocationInstLast: { if ((mBeModule->mActiveBlock != NULL) && (!mBeModule->mActiveBlock->mInstructions.IsEmpty())) { auto inst = mBeModule->mActiveBlock->mInstructions.back(); inst->mDbgLoc = NULL; } } break; case BfIRCmd_UpdateDebugLocation: { CMD_PARAM(BeValue*, instValue); auto inst = (BeInst*)instValue; inst->mDbgLoc = mBeModule->mCurDbgLoc; } break; case BfIRCmd_SetCurrentDebugLocation: { CMD_PARAM(int, line); CMD_PARAM(int, column); CMD_PARAM(BeMDNode*, diScope); CMD_PARAM(BeMDNode*, diInlinedAt); BF_ASSERT(diScope != NULL); mBeModule->SetCurrentDebugLocation(line - 1, column - 1, diScope, (BeDbgLoc*)diInlinedAt); } break; case BfIRCmd_Nop: { mBeModule->CreateNop(); } break; case BfIRCmd_EnsureInstructionAt: { mBeModule->AllocInst(); } break; case BfIRCmd_StatementStart: { } break; case BfIRCmd_ObjectAccessCheck: { CMD_PARAM(BeValue*, val); CMD_PARAM(bool, useAsm); auto inst = mBeModule->AllocInst(); inst->mValue = val; SetResult(curId, mBeModule->GetInsertBlock()); } break; case BfIRCmd_Comptime_Error: { CMD_PARAM(int32, error); auto inst = mBeModule->AllocInst(); inst->mError = error; SetResult(curId, inst); } break; case BfIRCmd_Comptime_GetBfType: { CMD_PARAM(int32, typeId); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mTypeId = typeId; inst->mResultType = resultType; SetResult(curId, inst); } break; case BfIRCmd_Comptime_GetReflectType: { CMD_PARAM(int32, typeId); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mTypeId = typeId; inst->mResultType = resultType; SetResult(curId, inst); } break; case BfIRCmd_Comptime_DynamicCastCheck: { CMD_PARAM(BeValue*, value); CMD_PARAM(int32, typeId); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mValue = value; inst->mTypeId = typeId; inst->mResultType = resultType; SetResult(curId, inst); } break; case BfIRCmd_Comptime_GetVirtualFunc: { CMD_PARAM(BeValue*, value); CMD_PARAM(int32, virtualTableIdx); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mValue = value; inst->mVirtualTableIdx = virtualTableIdx; inst->mResultType = resultType; SetResult(curId, inst); } break; case BfIRCmd_Comptime_GetInterfaceFunc: { CMD_PARAM(BeValue*, value); CMD_PARAM(int32, ifaceTypeId); CMD_PARAM(int32, methodIdx); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mValue = value; inst->mIFaceTypeId = ifaceTypeId; inst->mMethodIdx = methodIdx; inst->mResultType = resultType; SetResult(curId, inst); } break; case BfIRCmd_DbgInit: { /*mDIBuilder = new BeDIBuilder(*mBeModule); */ mBeModule->mDbgModule = new BeDbgModule(); mBeModule->mDbgModule->mBeModule = mBeModule; } break; case BfIRCmd_DbgFinalize: { /*for (auto typeEntryPair : mTypes) { auto& typeEntry = typeEntryPair.second; if (typeEntry.mInstDIType != NULL) typeEntry.mInstDIType->resolveCycles(); } mDIBuilder->finalize();*/ } break; case BfIRCmd_DbgCreateCompileUnit: { CMD_PARAM(int, lang); CMD_PARAM(String, fileName); CMD_PARAM(String, directory); CMD_PARAM(String, producer); CMD_PARAM(bool, isOptimized); CMD_PARAM(String, flags); CMD_PARAM(int, runtimeVer); CMD_PARAM(bool, linesOnly); mBeModule->mDbgModule->mFileName = fileName; mBeModule->mDbgModule->mDirectory = directory; mBeModule->mDbgModule->mProducer = producer; //mDebugging = fileName == "TestToots"; SetResult(curId, mBeModule->mDbgModule); } break; case BfIRCmd_DbgCreateFile: { CMD_PARAM(String, fileName); CMD_PARAM(String, directory); CMD_PARAM(Val128, md5Hash); auto dbgFile = mBeModule->mDbgModule->mFiles.Alloc(); dbgFile->mFileName = fileName; dbgFile->mDirectory = directory; dbgFile->mMD5Hash = md5Hash; dbgFile->mIdx = (int)mBeModule->mDbgModule->mFiles.size() - 1; SetResult(curId, dbgFile); } break; case BfIRCmd_DbgGetCurrentLocation: { SetResult(curId, mBeModule->mCurDbgLoc); } break; case BfIRCmd_DbgSetType: { CMD_PARAM(int, typeId); CMD_PARAM(BeMDNode*, type); auto& typeEntry = GetTypeEntry(typeId); typeEntry.mDIType = BeValueDynCast(type); if (typeEntry.mInstDIType == NULL) typeEntry.mInstDIType = BeValueDynCast(type); } break; case BfIRCmd_DbgSetInstType: { CMD_PARAM(int, typeId); CMD_PARAM(BeMDNode*, type); GetTypeEntry(typeId).mInstDIType = BeValueDynCast(type); } break; case BfIRCmd_DbgGetType: { CMD_PARAM(int, typeId); if (mBeModule->mCeMachine != NULL) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mTypeId = typeId; SetResult(curId, dbgType); } else SetResult(curId, GetTypeEntry(typeId).mDIType); } break; case BfIRCmd_DbgGetTypeInst: { CMD_PARAM(int, typeId); auto result = GetTypeEntry(typeId).mInstDIType; //BF_ASSERT(result); SetResult(curId, result); } break; case BfIRCmd_DbgTrackDITypes: { CMD_PARAM(int, typeId); auto& typeEntry = GetTypeEntry(typeId); /*if (typeEntry.mDIType != NULL) BeMetadataTracking::track(*(BeMetadata**)&typeEntry.mDIType); if (typeEntry.mInstDIType != NULL) BeMetadataTracking::track(*(BeMetadata**)&typeEntry.mInstDIType);*/ //NotImpl(); } break; case BfIRCmd_DbgCreateNamespace: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); auto dbgNamespace = mBeModule->mOwnedValues.Alloc(); dbgNamespace->mScope = scope; dbgNamespace->mName = name; SetResult(curId, dbgNamespace); } break; case BfIRCmd_DbgCreateImportedModule: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(BeMDNode*, namespaceNode); CMD_PARAM(int, lineNum); /*SetResult(curId, mDIBuilder->createImportedModule((BeDIScope*)context, (BeDINamespace*)namespaceNode, lineNum));*/ //NotImpl(); } break; case BfIRCmd_DbgCreateBasicType: { CMD_PARAM(String, name); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(int, encoding); auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); dbgType->mEncoding = encoding; SetResult(curId, dbgType); } break; case BfIRCmd_DbgCreateStructType: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(int, flags); CMD_PARAM(BeMDNode*, derivedFrom); CMD_PARAM(CmdParamVec, members); auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = context; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); dbgType->mDerivedFrom = BeValueDynCast(derivedFrom); dbgType->mDefFile = (BeDbgFile*)file; dbgType->mDefLine = lineNum - 1; dbgType->mIsFullyDefined = true; dbgType->SetMembers(members); SetResult(curId, dbgType); } break; case BfIRCmd_DbgCreateEnumerationType: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(CmdParamVec, members); CMD_PARAM(BeMDNode*, underlyingType); auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = context; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); dbgType->mIsFullyDefined = true; dbgType->mElementType = BeValueDynCast(underlyingType); for (auto member : members) { if (auto enumMember = BeValueDynCast(member)) { dbgType->mMembers.push_back(enumMember); } else NotImpl(); } //dbgType->mDefFile = (BeDbgFile*)file; //dbgType->mDefLine = line - 1; SetResult(curId, dbgType); } break; case BfIRCmd_DbgCreatePointerType: { CMD_PARAM(BeMDNode*, elementTypeNode); BeDbgType* elementType = BeValueDynCast(elementTypeNode); if (elementType == NULL) { if (auto dbgTypeId = BeValueDynCast(elementTypeNode)) { auto bfElementType = mBeModule->mCeMachine->mCeModule->mContext->mTypes[dbgTypeId->mTypeId]; auto bfPtrType = mBeModule->mCeMachine->mCeModule->CreatePointerType(bfElementType); auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mTypeId = bfPtrType->mTypeId; SetResult(curId, dbgType); break; } } BeDbgType* useType = elementType->FindDerivedType(BeDbgPointerType::TypeId); if (useType == NULL) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mElement = elementType; dbgType->mSize = mPtrSize; dbgType->mAlign = mPtrSize; elementType->mDerivedTypes.PushFront(dbgType, &mBeModule->mAlloc); useType = dbgType; } SetResult(curId, useType); } break; case BfIRCmd_DbgCreateReferenceType: { CMD_PARAM(BeMDNode*, elementTypeNode); BeDbgType* elementType = BeValueDynCast(elementTypeNode); if (elementType == NULL) { if (auto dbgTypeId = BeValueDynCast(elementTypeNode)) { auto bfElementType = mBeModule->mCeMachine->mCeModule->mContext->mTypes[dbgTypeId->mTypeId]; auto bfPtrType = mBeModule->mCeMachine->mCeModule->CreateRefType(bfElementType); auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mTypeId = bfPtrType->mTypeId; SetResult(curId, dbgType); break; } } auto useType = mBeModule->mDbgModule->CreateReferenceType(elementType); SetResult(curId, useType); } break; case BfIRCmd_DbgCreateConstType: { CMD_PARAM(BeMDNode*, elementTypeNode); BeDbgType* elementType = BeValueDynCast(elementTypeNode); if (elementType == NULL) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mElement = elementTypeNode; SetResult(curId, dbgType); break; } BeDbgType* useType = elementType->FindDerivedType(BeDbgConstType::TypeId); if (useType == NULL) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mElement = elementType; elementType->mDerivedTypes.PushFront(dbgType, &mBeModule->mAlloc); useType = dbgType; } SetResult(curId, useType); } break; case BfIRCmd_DbgCreateArtificialType: { CMD_PARAM(BeMDNode*, diType); //auto dbgType = mBeModule->mOwnedValues.Alloc(); //dbgType->mElement = (BeDbgType*)diType; // Does the artificial thing do anything for us actually? auto dbgType = diType; SetResult(curId, dbgType); } break; case BfIRCmd_DbgCreateArrayType: { CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(BeMDNode*, elementType); CMD_PARAM(int64, numElements); auto dbgArray = mBeModule->mDbgModule->mTypes.Alloc(); dbgArray->mSize = (int)(sizeInBits / 8); dbgArray->mAlign = (int)(alignInBits / 8); dbgArray->mElement = BeValueDynCast(elementType); dbgArray->mNumElements = numElements; SetResult(curId, dbgArray); } break; case BfIRCmd_DbgCreateReplaceableCompositeType: { CMD_PARAM(int, tag); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, scope); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, line); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(int, flags); if (tag == llvm::dwarf::DW_TAG_structure_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = scope; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); dbgType->mDefFile = (BeDbgFile*)file; dbgType->mDefLine = line - 1; SetResult(curId, dbgType); } else if (tag == llvm::dwarf::DW_TAG_enumeration_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = scope; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); //dbgType->mDefFile = (BeDbgFile*)file; //dbgType->mDefLine = line - 1; SetResult(curId, dbgType); } else NotImpl(); } break; case BfIRCmd_DbgCreateForwardDecl: { CMD_PARAM(int, tag); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, scope); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, line); if (tag == llvm::dwarf::DW_TAG_structure_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = scope; dbgType->mName = name; dbgType->mDefFile = (BeDbgFile*)file; dbgType->mDefLine = line; SetResult(curId, dbgType); } else if (tag == llvm::dwarf::DW_TAG_enumeration_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = scope; dbgType->mName = name; SetResult(curId, dbgType); } else NotImpl(); } break; case BfIRCmd_DbgCreateSizedForwardDecl: { CMD_PARAM(int, tag); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, scope); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, line); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); if (tag == llvm::dwarf::DW_TAG_structure_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mDefFile = (BeDbgFile*)file; dbgType->mDefLine = line; dbgType->mScope = scope; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); SetResult(curId, dbgType); } else if (tag == llvm::dwarf::DW_TAG_enumeration_type) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mScope = scope; dbgType->mName = name; dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); SetResult(curId, dbgType); } else NotImpl(); } break; case BeIRCmd_DbgSetTypeSize: { CMD_PARAM(BeMDNode*, mdType); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); if (auto dbgType = BeValueDynCast(mdType)) { dbgType->mSize = (int)(sizeInBits / 8); dbgType->mAlign = (int)(alignInBits / 8); } } break; case BfIRCmd_DbgReplaceAllUses: { CMD_PARAM(BeMDNode*, diPrevNode); CMD_PARAM(BeMDNode*, diNewNode); /*diPrevNode->replaceAllUsesWith(diNewNode); */ NotImpl(); } break; case BfIRCmd_DbgDeleteTemporary: { CMD_PARAM(BeMDNode*, diNode); /*BeMDNode::deleteTemporary(diNode);*/ NotImpl(); } break; case BfIRCmd_DbgMakePermanent: { CMD_PARAM(BeMDNode*, diNode); CMD_PARAM(BeMDNode*, diBaseType); CMD_PARAM(CmdParamVec, members); if (auto dbgType = BeValueDynCast(diNode)) { dbgType->SetMembers(members); } else if (auto dbgType = BeValueDynCast(diNode)) { dbgType->mElementType = BeValueDynCast(diBaseType); dbgType->SetMembers(members); } else NotImpl(); SetResult(curId, diNode); break; } case BfIRCmd_CreateEnumerator: { CMD_PARAM(String, name); CMD_PARAM(int64, val); auto enumValue = mBeModule->mOwnedValues.Alloc(); enumValue->mName = name; enumValue->mValue = val; SetResult(curId, enumValue); } break; case BfIRCmd_DbgCreateMemberType: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNumber); CMD_PARAM(int64, sizeInBits); CMD_PARAM(int64, alignInBits); CMD_PARAM(int64, offsetInBits); CMD_PARAM(int, flags); CMD_PARAM(BeMDNode*, type); BF_ASSERT(type != NULL); auto dbgMember = mBeModule->mOwnedValues.Alloc(); dbgMember->mName = name; dbgMember->mType = BeValueDynCast(type); dbgMember->mOffset = (int)(offsetInBits / 8); dbgMember->mFlags = flags; SetResult(curId, dbgMember); } break; case BfIRCmd_DbgStaticCreateMemberType: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNumber); CMD_PARAM(BeMDNode*, type); CMD_PARAM(int, flags); CMD_PARAM(BeConstant*, val); BF_ASSERT(type != NULL); auto dbgMember = mBeModule->mOwnedValues.Alloc(); dbgMember->mName = name; dbgMember->mType = BeValueDynCast(type); dbgMember->mOffset = -1; dbgMember->mStaticValue = val; dbgMember->mFlags = flags; dbgMember->mIsStatic = true; SetResult(curId, dbgMember); } break; case BfIRCmd_DbgCreateInheritance: { CMD_PARAM(BeMDNode*, type); CMD_PARAM(BeMDNode*, baseType); CMD_PARAM(int64, baseOffset); CMD_PARAM(int, flags); auto dbgInheritance = mBeModule->mAlloc.Alloc(); dbgInheritance->mBaseType = BeValueDynCast(baseType); SetResult(curId, dbgInheritance); } break; case BfIRCmd_DbgCreateMethod: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(String, name); CMD_PARAM(String, linkageName); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(BeMDNode*, type); CMD_PARAM(bool, isLocalToUnit); CMD_PARAM(bool, isDefinition); CMD_PARAM(int, vk); CMD_PARAM(int, vIndex); CMD_PARAM(BeMDNode*, vTableHolder); CMD_PARAM(int, flags); CMD_PARAM(bool, isOptimized); CMD_PARAM(BeValue*, fn); CMD_PARAM(CmdParamVec, genericArgs); CMD_PARAM(CmdParamVec, genericConstValueArgs); auto dbgFunc = mBeModule->mOwnedValues.Alloc(); dbgFunc->mScope = context; dbgFunc->mFile = (BeDbgFile*)file; dbgFunc->mLine = lineNum - 1; dbgFunc->mType = (BeDbgFunctionType*)type; dbgFunc->mName = name; dbgFunc->mLinkageName = linkageName; dbgFunc->mValue = (BeFunction*)fn; dbgFunc->mIsLocalToUnit = isLocalToUnit; dbgFunc->mVK = vk; dbgFunc->mVIndex = vIndex; dbgFunc->mIsStaticMethod = (flags & llvm::DINode::FlagStaticMember) != 0; dbgFunc->mFlags = flags; for (auto arg : genericArgs) { BF_ASSERT(arg != NULL); dbgFunc->mGenericArgs.Add(BeValueDynCast(arg)); } for (auto genericConstValue : genericConstValueArgs) dbgFunc->mGenericConstValueArgs.Add(genericConstValue); if (dbgFunc->mValue != NULL) dbgFunc->mValue->mDbgFunction = dbgFunc; dbgFunc->mIdx = (int)mBeModule->mDbgModule->mFuncs.size(); mBeModule->mDbgModule->mFuncs.push_back(dbgFunc); SetResult(curId, dbgFunc); } break; case BfIRCmd_DbgCreateFunction: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(String, name); CMD_PARAM(String, linkageName); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(BeMDNode*, type); CMD_PARAM(bool, isLocalToUnit); CMD_PARAM(bool, isDefinition); CMD_PARAM(int, scopeLine); CMD_PARAM(int, flags); CMD_PARAM(bool, isOptimized); CMD_PARAM(BeValue*, fn); auto dbgFunc = mBeModule->mOwnedValues.Alloc(); dbgFunc->mScope = context; dbgFunc->mFile = (BeDbgFile*)file; dbgFunc->mLine = lineNum - 1; dbgFunc->mType = (BeDbgFunctionType*)type; dbgFunc->mName = name; dbgFunc->mLinkageName = linkageName; dbgFunc->mValue = (BeFunction*)fn; dbgFunc->mIsLocalToUnit = isLocalToUnit; dbgFunc->mFlags = flags; /*if (auto dbgStructType = BeValueDynCast(context)) { // This will get added to the struct later } else { }*/ if (dbgFunc->mValue != NULL) dbgFunc->mValue->mDbgFunction = dbgFunc; dbgFunc->mIdx = (int)mBeModule->mDbgModule->mFuncs.size(); mBeModule->mDbgModule->mFuncs.push_back(dbgFunc); SetResult(curId, dbgFunc); } break; case BfIRCmd_DbgCreateParameterVariable: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(int, argNo); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(BeMDNode*, type); CMD_PARAM(bool, alwaysPreserve); CMD_PARAM(int, flags); BF_ASSERT(type != NULL); auto dbgFunc = (BeDbgFunction*)scope; auto dbgVar = mBeModule->mOwnedValues.Alloc(); dbgVar->mName = name; dbgVar->mType = type; dbgVar->mParamNum = argNo - 1; int argIdx = argNo - 1; //for (int i = ; i <= argNo - 1; i++) while (argIdx >= (int)dbgFunc->mVariables.size()) dbgFunc->mVariables.push_back(NULL); if (dbgFunc->mVariables[argIdx] == NULL) dbgFunc->mVariables[argIdx] = dbgVar; else { BF_ASSERT(dbgFunc->mVariables[argIdx]->mParamNum == -1); dbgFunc->mVariables.Insert(argIdx, dbgVar); } //mActiveFunction->mDbgFunction->mVariables.push_back(dbgVar); //dbgVar->mValue = mBeModule->GetArgument(argNo - 1); SetResult(curId, dbgVar); } break; case BfIRCmd_DbgCreateSubroutineType: { CMD_PARAM(CmdParamVec, elements); auto dbgFuncType = mBeModule->mOwnedValues.Alloc(); if (!elements.empty()) { dbgFuncType->mReturnType = BeValueDynCast(elements[0]); for (int i = 1; i < (int)elements.size(); i++) dbgFuncType->mParams.push_back(BeValueDynCast(elements[i])); } SetResult(curId, dbgFuncType); } break; case BfIRCmd_DbgCreateAutoVariable: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNo); CMD_PARAM(BeMDNode*, type); CMD_PARAM(int, initType); BF_ASSERT(type != NULL); auto dbgVar = mBeModule->mOwnedValues.Alloc(); dbgVar->mName = name; dbgVar->mType = type; dbgVar->mScope = scope; dbgVar->mInitType = (BfIRInitType)initType; mActiveFunction->mDbgFunction->mVariables.push_back(dbgVar); BF_ASSERT(name != "__CRASH_AUTOVARIABLE__"); SetResult(curId, dbgVar); } break; case BfIRCmd_DbgInsertValueIntrinsic: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeMDNode*, varInfo); auto dbgVar = BeValueDynCast(varInfo); //dbgVar->mValue = val; //dbgVar->mDeclDbgLoc = mBeModule->mCurDbgLoc; if (val == NULL) { val = mBeModule->GetConstant(mBeContext->GetPrimitiveType(BeTypeCode_Int32), (int64)0); } auto inst = mBeModule->AllocInst(); inst->mValue = val; inst->mDbgVar = dbgVar; inst->mIsValue = true; SetResult(curId, inst); } break; case BfIRCmd_DbgInsertDeclare: { CMD_PARAM(BeValue*, val); CMD_PARAM(BeMDNode*, varInfo); CMD_PARAM(BeValue*, insertBefore); auto dbgVar = BeValueDynCast(varInfo); //dbgVar->mValue = val; //dbgVar->mDeclDbgLoc = mBeModule->mCurDbgLoc; auto inst = mBeModule->mAlloc.Alloc(); inst->mValue = val; inst->mDbgVar = dbgVar; inst->mIsValue = false; if (insertBefore == NULL) mBeModule->AddInst(inst); else NotImpl(); SetResult(curId, inst); } break; case BfIRCmd_DbgLifetimeEnd: { CMD_PARAM(BeMDNode*, varInfo); auto inst = mBeModule->AllocInst(); inst->mPtr = varInfo; } break; case BfIRCmd_DbgCreateGlobalVariable: { CMD_PARAM(BeMDNode*, context); CMD_PARAM(String, name); CMD_PARAM(String, linkageName); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(BeMDNode*, type); CMD_PARAM(bool, isLocalToUnit); CMD_PARAM(BeConstant*, val); CMD_PARAM(BeMDNode*, decl); auto dbgGlobalVariable = mBeModule->mDbgModule->mGlobalVariables.Alloc(); dbgGlobalVariable->mContext = context; dbgGlobalVariable->mName = name; dbgGlobalVariable->mLinkageName = linkageName; dbgGlobalVariable->mFile = (BeDbgFile*)file; dbgGlobalVariable->mLineNum = lineNum; dbgGlobalVariable->mType = type; dbgGlobalVariable->mIsLocalToUnit = isLocalToUnit; dbgGlobalVariable->mValue = val; dbgGlobalVariable->mDecl = decl; SetResult(curId, dbgGlobalVariable); } break; case BfIRCmd_DbgCreateLexicalBlock: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(BeMDNode*, file); CMD_PARAM(int, lineNum); CMD_PARAM(int, col); auto dbgLexicalBlock = mBeModule->mOwnedValues.Alloc(); BF_ASSERT(BeValueDynCast(file) != NULL); dbgLexicalBlock->mFile = (BeDbgFile*)file; dbgLexicalBlock->mScope = scope; dbgLexicalBlock->mId = mBeModule->mCurLexBlockId++; SetResult(curId, dbgLexicalBlock); } break; case BfIRCmd_DbgCreateAnnotation: { CMD_PARAM(BeMDNode*, scope); CMD_PARAM(String, name); CMD_PARAM(BeValue*, value); if (auto dbgFunc = BeValueDynCast(scope)) { auto beType = value->GetType(); BeDbgType** dbgTypePtr; if (mOnDemandTypeMap.TryAdd(beType, NULL, &dbgTypePtr)) { auto dbgType = mBeModule->mDbgModule->mTypes.Alloc(); dbgType->mSize = beType->mSize; dbgType->mAlign = beType->mAlign; dbgType->mEncoding = llvm::dwarf::DW_ATE_signed; *dbgTypePtr = dbgType; } auto dbgVar = mBeModule->mOwnedValues.Alloc(); dbgVar->mName = "#" + name; dbgVar->mType = *dbgTypePtr; dbgVar->mValue = value; dbgVar->mScope = scope; dbgFunc->mVariables.Add(dbgVar); auto inst = mBeModule->AllocInst(); inst->mValue = value; inst->mDbgVar = dbgVar; inst->mIsValue = true; } else NotImpl(); } break; default: BF_FATAL("Unhandled"); break; } #ifdef CODEGEN_TRACK gBEMemReporter.EndSection(); gBEMemReporterSize += mStream->GetReadPos() - curId; #endif } void BeIRCodeGen::SetConfigConst(int idx, int value) { BF_ASSERT(idx == (int)mConfigConsts.size()); mConfigConsts.Add(value); } BeValue* BeIRCodeGen::TryGetBeValue(int id) { auto& result = mResults[id]; if (result.mKind != BeIRCodeGenEntryKind_Value) return NULL; #ifdef BE_EXTRA_CHECKS BF_ASSERT(!result.mBeValue->mLifetimeEnded); BF_ASSERT(!result.mBeValue->mWasRemoved); #endif return result.mBeValue; } BeValue* BeIRCodeGen::GetBeValue(int id) { auto& result = mResults[id]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Value); #ifdef BE_EXTRA_CHECKS BF_ASSERT(!result.mBeValue->mLifetimeEnded); BF_ASSERT(!result.mBeValue->mWasRemoved); #endif return result.mBeValue; } BeType* BeIRCodeGen::GetBeType(int id) { auto& result = mResults[id]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Type); return result.mBeType; } BeBlock* BeIRCodeGen::GetBeBlock(int id) { auto& result = mResults[id]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Block); return result.mBeBlock; } BeMDNode* BeIRCodeGen::GetBeMetadata(int id) { auto& result = mResults[id]; BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Metadata); return result.mBeMetadata; } BeType* BeIRCodeGen::GetBeTypeById(int id) { return GetTypeEntry(id).mBeType; } BeState BeIRCodeGen::GetState() { BeState state; state.mActiveFunction = mActiveFunction; state.mSavedDebugLocs = mSavedDebugLocs; state.mHasDebugLoc = mHasDebugLoc; state.mActiveBlock = mBeModule->mActiveBlock; state.mInsertPos = mBeModule->mInsertPos; state.mCurDbgLoc = mBeModule->mCurDbgLoc; state.mPrevDbgLocInline = mBeModule->mPrevDbgLocInline; state.mLastDbgLoc = mBeModule->mLastDbgLoc; return state; } void BeIRCodeGen::SetState(const BeState& state) { mActiveFunction = state.mActiveFunction; mBeModule->mActiveFunction = mActiveFunction; mSavedDebugLocs = state.mSavedDebugLocs; mHasDebugLoc = state.mHasDebugLoc; mBeModule->mActiveBlock = state.mActiveBlock; mBeModule->mInsertPos = state.mInsertPos; mBeModule->mCurDbgLoc = state.mCurDbgLoc; mBeModule->mPrevDbgLocInline = state.mPrevDbgLocInline; mBeModule->mLastDbgLoc = state.mLastDbgLoc; }