Example #1
0
        /// <summary>
        /// Builds an assert implementation that calls a nested fail function based on
        /// a boolean condition (first parameter).
        /// </summary>
        protected static Method BuildDebugAssertImplementation(
            IRContext irContext,
            MethodBase debugAssertMethod,
            MethodBase assertFailedMethod)
        {
            // Create a call to the debug-implementation wrapper while taking the
            // current source location into account
            var method = irContext.Declare(debugAssertMethod, out bool created);

            if (!created)
            {
                return(method);
            }

            var location = Location.Nowhere;

            using var builder = method.CreateBuilder();
            method.AddFlags(MethodFlags.Inline);

            // Create the entry, body and exit blocks
            var entryBlock = builder.EntryBlockBuilder;
            var bodyBlock  = builder.CreateBasicBlock(location);
            var exitBlock  = builder.CreateBasicBlock(location);

            // Initialize the parameters
            var sourceParameters = debugAssertMethod.GetParameters();
            var parameters       = InlineList <Parameter> .Create(sourceParameters.Length);

            foreach (var parameter in sourceParameters)
            {
                var paramType = entryBlock.CreateType(parameter.ParameterType);
                parameters.Add(builder.AddParameter(paramType, parameter.Name));
            }

            // Check condition
            entryBlock.CreateIfBranch(
                location,
                parameters[0],
                exitBlock,
                bodyBlock);

            // Fill the body
            var assertFailed = bodyBlock.CreateCall(
                location,
                irContext.Declare(assertFailedMethod, out var _));

            for (int i = 1; i < parameters.Count; ++i)
            {
                assertFailed.Add(parameters[i]);
            }
            assertFailed.Seal();

            bodyBlock.CreateBranch(location, exitBlock);

            // Create return
            exitBlock.CreateReturn(location);

            return(method);
        }
Example #2
0
        /// <summary>
        /// Maps internal <see cref="WriteToOutput"/> values to
        /// <see cref="PrintF(string)"/> method calls.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            WriteToOutput writeToOutput)
        {
            var location = writeToOutput.Location;

            // Convert to format string constant
            var expressionString = writeToOutput.ToEscapedPrintFExpression();
            var expression       = builder.CreatePrimitiveValue(
                location,
                expressionString);

            // Create a call to the native printf
            var printFMethod = context.Declare(PrintFMethod, out bool _);
            var callBuilder  = builder.CreateCall(location, printFMethod);

            callBuilder.Add(expression);
            foreach (Value argument in writeToOutput.Arguments)
            {
                var converted = WriteToOutput.ConvertToPrintFArgument(
                    builder,
                    location,
                    argument);
                callBuilder.Add(converted);
            }

            // Replace the write node with the call
            callBuilder.Seal();
            builder.Remove(writeToOutput);
        }
        /// <summary>
        /// Maps internal <see cref="WriteToOutput"/> values to
        /// <see cref="PrintF(string, void*)"/> method calls.
        /// </summary>
        protected override void Implement(
            IRContext context,
            Method.Builder methodBuilder,
            BasicBlock.Builder builder,
            WriteToOutput writeToOutput)
        {
            var location = writeToOutput.Location;

            // Convert to format string constant
            var expressionString = writeToOutput.ToPrintFExpression();
            var expression       = builder.CreatePrimitiveValue(
                location,
                expressionString,
                Encoding.ASCII);

            // Create an argument structure that can be passed via local memory
            var argumentBuilder = builder.CreateDynamicStructure(
                location,
                writeToOutput.Count);

            foreach (Value argument in writeToOutput.Arguments)
            {
                var converted = WriteToOutput.ConvertToPrintFArgument(
                    builder,
                    location,
                    argument);
                argumentBuilder.Add(converted);
            }
            var argumentStructure = argumentBuilder.Seal();

            // Create local alloca to store all data
            var alloca = builder.CreateAlloca(
                location,
                argumentStructure.Type,
                MemoryAddressSpace.Local);

            // Store structure into chunk of local memory
            builder.CreateStore(location, alloca, argumentStructure);

            // Cast alloca to the generic address space to satisfy the requirements of
            // of the printf method
            alloca = builder.CreateAddressSpaceCast(
                location,
                alloca,
                MemoryAddressSpace.Generic);

            // Create a call to the native printf
            var printFMethod = context.Declare(PrintFMethod, out bool _);
            var callBuilder  = builder.CreateCall(location, printFMethod);

            callBuilder.Add(expression);
            callBuilder.Add(alloca);

            // Replace the write node with the call
            callBuilder.Seal();
            builder.Remove(writeToOutput);
        }
        /// <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());
        }