/// <summary> /// Maps internal debug assertions to <see cref="AssertFailed(string, string, /// int, string, int)"/> method calls. /// </summary> protected override void Implement( IRContext context, Method.Builder methodBuilder, BasicBlock.Builder builder, DebugAssertOperation debugAssert) { var location = debugAssert.Location; // Create a call to the debug-implementation wrapper while taking the // current source location into account var nextBlock = builder.SplitBlock(debugAssert); var innerBlock = methodBuilder.CreateBasicBlock( location, nameof(AssertFailed)); builder.CreateIfBranch( location, debugAssert.Condition, nextBlock, innerBlock); // Create a call to the assert implementation var innerBuilder = methodBuilder[innerBlock]; var assertFailed = innerBuilder.CreateCall( location, context.Declare(AssertFailedMethod, out var _)); // Move the debug assertion to this block var sourceMessage = debugAssert.Message.ResolveAs <StringValue>(); var message = innerBuilder.CreatePrimitiveValue( location, sourceMessage.String, sourceMessage.Encoding); assertFailed.Add(message); // Append source location information var debugLocation = debugAssert.GetLocationInfo(); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.FileName)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.Line)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, debugLocation.Method)); assertFailed.Add( innerBuilder.CreatePrimitiveValue(location, 1)); // Finish the actual assertion call and branch assertFailed.Seal(); innerBuilder.CreateBranch(location, nextBlock); // Remove the debug assertion value debugAssert.Replace(builder.CreateUndefined()); }
internal CFGBuilder( CodeGenerator codeGenerator, Method.Builder methodBuilder) { CodeGenerator = codeGenerator; Builder = methodBuilder; var mainEntry = methodBuilder.EntryBlockBuilder; EntryBlock = new Block( codeGenerator, mainEntry) { InstructionCount = 0 }; basicBlockMapping.Add(EntryBlock.BasicBlock, EntryBlock); // Create a temporary entry block to ensure that we have a single entry // block without any predecessors in all cases var internalEntryBlock = new Block( codeGenerator, methodBuilder.CreateBasicBlock( mainEntry.BasicBlock.Location, mainEntry.BasicBlock.Name)); blockMapping.Add(0, internalEntryBlock); basicBlockMapping.Add(internalEntryBlock.BasicBlock, internalEntryBlock); BuildBasicBlocks(); var visited = new HashSet <Block>(); SetupBasicBlocks(visited, internalEntryBlock, 0); WireBlocks(); // Wire the main entry block with the actual entry block mainEntry.CreateBranch( mainEntry.BasicBlock.Location, internalEntryBlock.BasicBlock); // Update control-flow structure to refresh all successor/predecessor // edge relations Blocks = methodBuilder.UpdateControlFlow(); }