Exemplo n.º 1
0
        private void AddDebugInfoForAlloca(Alloca argSlot, IrFunction function, LocalVariableDeclaration localVar)
        {
            uint line = ( uint )localVar.Location.StartLine;
            uint col  = ( uint )localVar.Location.StartColumn;

            // Keep compiler happy on null checks by asserting on expectations
            // The items were created in this file with all necessary info so
            // these properties should never be null.
            Debug.Assert(function.DISubProgram != null, "expected function with non-null DISubProgram");
            Debug.Assert(function.DISubProgram.File != null, "expected function with non-null DISubProgram.File");
            Debug.Assert(InstructionBuilder.InsertBlock != null, "expected Instruction builder with non-null insertion block");

            DILocalVariable debugVar = Module.DIBuilder.CreateLocalVariable(scope: function.DISubProgram
                                                                            , name: localVar.Name
                                                                            , file: function.DISubProgram.File
                                                                            , line
                                                                            , type: DoubleType
                                                                            , alwaysPreserve: false
                                                                            , debugFlags: DebugInfoFlags.None
                                                                            );

            Module.DIBuilder.InsertDeclare(storage: argSlot
                                           , varInfo: debugVar
                                           , location: new DILocation(Context, line, col, function.DISubProgram)
                                           , insertAtEnd: InstructionBuilder.InsertBlock
                                           );
        }
Exemplo n.º 2
0
        /// <summary>
        /// Constructs new alloca information.
        /// </summary>
        /// <param name="index">The allocation index.</param>
        /// <param name="alloca">The alloca node.</param>
        internal AllocaInformation(int index, Alloca alloca)
        {
            Index  = index;
            Alloca = alloca;

            if (alloca.IsArrayAllocation(out var length))
            {
                ArraySize = length.Int32Value;
            }
            else if (alloca.IsSimpleAllocation)
            {
                ArraySize = 1;
            }
            else if (alloca.IsDynamicAllocation)
            {
                // Size determined at run-time.
                ArraySize = -1;
            }
            else
            {
                throw alloca.Location.GetNotSupportedException(
                          ErrorMessages.NotSupportedDynamicAllocation,
                          alloca.AllocaType);
            }
        }
Exemplo n.º 3
0
 public void Visit(Alloca alloca)
 {
     if (Get <Alloca>().AddressSpace != alloca.AddressSpace)
     {
         Fail();
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Constructs new alloca information.
        /// </summary>
        /// <param name="index">The allocation index.</param>
        /// <param name="alloca">The alloca node.</param>
        /// <param name="elementSize">The element size.</param>
        internal AllocaInformation(
            int index,
            Alloca alloca,
            int elementSize)
        {
            Index       = index;
            Alloca      = alloca;
            ElementSize = elementSize;

            var rawArrayLength = alloca.ArrayLength;
            var arrayLength    = rawArrayLength.ResolveAs <PrimitiveValue>();

            if (arrayLength != null)
            {
                ArraySize = arrayLength.Int32Value;
            }
            else
            {
                var dynamicArrayLength = rawArrayLength.ResolveAs <UndefinedValue>();
                if (dynamicArrayLength != null)
                {
                    ArraySize = -1;
                }
                else
                {
                    throw new NotSupportedException(
                              string.Format(
                                  ErrorMessages.NotSupportedDynamicAllocation,
                                  alloca.AddressSpace,
                                  rawArrayLength));
                }
            }
        }
Exemplo n.º 5
0
        public override Value?Visit(BinaryOperatorExpression binaryOperator)
        {
            binaryOperator.ValidateNotNull(nameof(binaryOperator));
            EmitLocation(binaryOperator);

            switch (binaryOperator.Op)
            {
            case BuiltInOperatorKind.Less:
            {
                var tmp = InstructionBuilder.Compare(RealPredicate.UnorderedOrLessThan
                                                     , binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                                     , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                                     ).RegisterName("cmptmp");
                return(InstructionBuilder.UIToFPCast(tmp, InstructionBuilder.Context.DoubleType)
                       .RegisterName("booltmp"));
            }

            case BuiltInOperatorKind.Pow:
            {
                var pow = GetOrDeclareFunction(new Prototype("llvm.pow.f64", "value", "power"));
                return(InstructionBuilder.Call(pow
                                               , binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               ).RegisterName("powtmp"));
            }

            case BuiltInOperatorKind.Add:
                return(InstructionBuilder.FAdd(binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               ).RegisterName("addtmp"));

            case BuiltInOperatorKind.Subtract:
                return(InstructionBuilder.FSub(binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               ).RegisterName("subtmp"));

            case BuiltInOperatorKind.Multiply:
                return(InstructionBuilder.FMul(binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               ).RegisterName("multmp"));

            case BuiltInOperatorKind.Divide:
                return(InstructionBuilder.FDiv(binaryOperator.Left.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               , binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr)
                                               ).RegisterName("divtmp"));

            case BuiltInOperatorKind.Assign:
                Alloca target = LookupVariable((( VariableReferenceExpression )binaryOperator.Left).Name);
                Value  value  = binaryOperator.Right.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr);
                InstructionBuilder.Store(value, target);
                return(value);

            default:
                throw new CodeGeneratorException($"ICE: Invalid binary operator {binaryOperator.Op}");
            }
        }
Exemplo n.º 6
0
 /// <summary>
 /// Returns true if the given alloca is contained in this collection.
 /// </summary>
 /// <param name="alloca">The alloca.</param>
 /// <returns>True, if the given alloca is contained in this collection.</returns>
 public bool Contains(Alloca alloca)
 {
     foreach (var allocaInfo in Allocas)
     {
         if (allocaInfo.Alloca == alloca)
         {
             return(true);
         }
     }
     return(false);
 }
Exemplo n.º 7
0
        /// <summary>
        /// Constructs new alloca information.
        /// </summary>
        /// <param name="index">The allocation index.</param>
        /// <param name="alloca">The alloca node.</param>
        internal AllocaInformation(int index, Alloca alloca)
        {
            Index  = index;
            Alloca = alloca;

            ArraySize = alloca.IsArrayAllocation(out var length)
                ? length.Int32Value
                : alloca.IsSimpleAllocation
                    ? 1
                    : throw new NotSupportedException(
                                  ErrorMessages.NotSupportedDynamicAllocation);
        }
Exemplo n.º 8
0
        protected static void ConvertAlloca <TConstructionData>(
            SSARewriterContext <Value> context,
            TConstructionData data,
            Alloca alloca,
            Value initValue)
            where TConstructionData : IConstructionData
        {
            alloca.Assert(data.ContainsAlloca(alloca));

            // Bind the init value and remove the allocation from the block
            context.SetValue(context.Block, alloca, initValue);
            data.AddConverted(alloca, new FieldRef(alloca));
            context.Remove(alloca);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Lowers alloca values into their appropriate counter parts.
        /// </summary>
        protected static void Lower(
            RewriterContext context,
            TypeLowering <TType> typeConverter,
            Alloca alloca)
        {
            // Compute the alloca type
            var newType   = typeConverter.ConvertType(alloca);
            var newAlloca = context.Builder.CreateAlloca(
                alloca.Location,
                newType,
                alloca.AddressSpace);

            context.ReplaceAndRemove(alloca, newAlloca);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Converts an alloca node to its initial SSA value.
        /// </summary>
        private static void Convert(
            SSARewriterContext <Value> context,
            ConstructionData data,
            Alloca alloca)
        {
            if (!data.ContainsAlloca(alloca))
            {
                return;
            }

            var initValue = context.Builder.CreateNull(
                alloca.Location,
                alloca.AllocaType);

            ConvertAlloca(context, data, alloca, initValue);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Converts an alloca node to its initial SSA value.
        /// </summary>
        private static void Convert <TConstructionData>(
            SSARewriterContext <Value> context,
            TConstructionData data,
            Alloca alloca)
            where TConstructionData : IConstructionData
        {
            if (!data.ContainsAlloca(alloca))
            {
                return;
            }
            alloca.Assert(!alloca.IsSimpleAllocation);

            // Get the builder and the associated array length value
            var builder          = context.Builder;
            var arrayLengthValue = alloca.ArrayLength.ResolveAs <PrimitiveValue>();

            alloca.AssertNotNull(arrayLengthValue);
            int arrayLength = arrayLengthValue.Int32Value;

            // Create a structure with the appropriate number of fields that correspond
            // to the current array length
            var allocaTypeBuilder = builder.CreateStructureType(arrayLength + 1);

            // Append array length
            allocaTypeBuilder.Add(builder.GetPrimitiveType(BasicValueType.Int32));
            // Append all virtual fields
            for (int i = 0; i < arrayLength; ++i)
            {
                allocaTypeBuilder.Add(alloca.AllocaType);
            }
            var allocationType = allocaTypeBuilder.Seal();

            // Initialize the structure value
            var initValue = builder.CreateNull(alloca.Location, allocationType);

            // ... and set the array length
            initValue = builder.CreateSetField(
                alloca.Location,
                initValue,
                new FieldSpan(new FieldAccess(0)),
                builder.CreateConvertToInt32(alloca.Location, arrayLengthValue));
            ConvertAlloca(context, data, alloca, initValue);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Converts an alloca node to its initial SSA value.
        /// </summary>
        private static void Convert(
            SSARewriterContext <Value> context,
            ConstructionData data,
            Alloca alloca)
        {
            if (!data.ContainsAlloca(alloca))
            {
                return;
            }

            var initValue = context.Builder.CreateNull(
                alloca.Location,
                alloca.AllocaType);

            context.SetValue(context.Block, alloca, initValue);

            data.AddConverted(alloca, new FieldRef(alloca));
            context.Remove(alloca);
        }
Exemplo n.º 13
0
        private void AddDebugInfoForAlloca(Alloca argSlot, IrFunction function, LocalVariableDeclaration localVar)
        {
            uint line = ( uint )localVar.Location.StartLine;
            uint col  = ( uint )localVar.Location.StartColumn;

            DILocalVariable debugVar = Module.DIBuilder.CreateLocalVariable(scope: function.DISubProgram
                                                                            , name: localVar.Name
                                                                            , file: function.DISubProgram.File
                                                                            , line
                                                                            , type: DoubleType
                                                                            , alwaysPreserve: false
                                                                            , debugFlags: DebugInfoFlags.None
                                                                            );

            Module.DIBuilder.InsertDeclare(storage: argSlot
                                           , varInfo: debugVar
                                           , location: new DILocation(Context, line, col, function.DISubProgram)
                                           , insertAtEnd: InstructionBuilder.InsertBlock
                                           );
        }
Exemplo n.º 14
0
        public override Value Visit(VarInExpression varInExpression)
        {
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("VarInScope");
                foreach (var localVar in varInExpression.LocalVariables)
                {
                    Alloca alloca    = LookupVariable(localVar.Name);
                    Value  initValue = Context.CreateConstant(0.0);
                    if (localVar.Initializer != null)
                    {
                        initValue = localVar.Initializer.Accept(this);
                    }

                    InstructionBuilder.Store(initValue, alloca);
                }

                return(varInExpression.Body.Accept(this));
            }
        }
Exemplo n.º 15
0
        public override Value?Visit(VarInExpression varInExpression)
        {
            varInExpression.ValidateNotNull(nameof(varInExpression));
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("VarInScope");
                foreach (var localVar in varInExpression.LocalVariables)
                {
                    Alloca alloca    = LookupVariable(localVar.Name);
                    Value  initValue = Context.CreateConstant(0.0);
                    if (localVar.Initializer != null)
                    {
                        initValue = localVar.Initializer.Accept(this) ?? throw new CodeGeneratorException(ExpectValidExpr);
                    }

                    InstructionBuilder.Store(initValue, alloca);
                }

                return(varInExpression.Body.Accept(this));
            }
        }
Exemplo n.º 16
0
        private void AddDebugInfoForAlloca(Alloca argSlot, IrFunction function, ParameterDeclaration param)
        {
            uint line = ( uint )param.Location.StartLine;
            uint col  = ( uint )param.Location.StartColumn;

            DILocalVariable debugVar = Module.DIBuilder.CreateArgument(scope: function.DISubProgram
                                                                       , name: param.Name
                                                                       , file: function.DISubProgram.File
                                                                       , line
                                                                       , type: DoubleType
                                                                       , alwaysPreserve: true
                                                                       , debugFlags: DebugInfoFlags.None
                                                                       , argNo: checked (( ushort )(param.Index + 1)) // Debug index starts at 1!
                                                                       );

            Module.DIBuilder.InsertDeclare(storage: argSlot
                                           , varInfo: debugVar
                                           , location: new DILocation(Context, line, col, function.DISubProgram)
                                           , insertAtEnd: InstructionBuilder.InsertBlock
                                           );
        }
Exemplo n.º 17
0
 /// <summary cref="IValueVisitor.Visit(Alloca)"/>
 public void Visit(Alloca alloca) =>
 CodeGenerator.GenerateCode(alloca);
Exemplo n.º 18
0
 /// <summary cref="IValueVisitor.Visit(Alloca)"/>
 public void Visit(Alloca alloca)
 {
     // Ignore alloca
 }
Exemplo n.º 19
0
 /// <summary cref="IBackendCodeGenerator.GenerateCode(Alloca)"/>
 public void GenerateCode(Alloca alloca)
 {
     // Ignore alloca
 }
Exemplo n.º 20
0
 /// <summary>
 /// Returns true if the given allocation is a simple allocation and does not
 /// require explicit addresses.
 /// </summary>
 protected override bool CanConvert(Method.Builder builder, Alloca alloca) =>
 base.CanConvert(builder, alloca) &&
 alloca.IsSimpleAllocation &&
 !RequiresAddress(alloca);
Exemplo n.º 21
0
 /// <summary>
 /// Returns true if the given allocation is a simple allocation and does not
 /// require explicit addresses.
 /// </summary>
 protected override bool CanConvert(Method.Builder builder, Alloca alloca) =>
 base.CanConvert(builder, alloca) &&
 // Check whether we require an address or there are array accesses
 // that cannot be converted to statically known field index values.
 alloca.IsArrayAllocation(out var length) &&
Exemplo n.º 22
0
 /// <summary>
 /// Returns the alignment information determined and used for the given
 /// alloca.
 /// </summary>
 /// <param name="alloca">
 /// The alloca to get the alignment information for.
 /// </param>
 /// <returns>The determined and used alignment in bytes.</returns>
 public readonly int GetAllocaAlignment(Alloca alloca) =>
 GetAlignment(
     alloca,
     AllocaAlignments.GetInitialAlignment(alloca));
Exemplo n.º 23
0
 /// <summary>
 /// Returns true if the given allocation can be transformed.
 /// </summary>
 protected virtual bool CanConvert(Method.Builder builder, Alloca alloca) =>
 alloca.AddressSpace == AddressSpace;
Exemplo n.º 24
0
        public override Value?Visit(ForInExpression forInExpression)
        {
            forInExpression.ValidateNotNull(nameof(forInExpression));
            EmitLocation(forInExpression);
            var function = InstructionBuilder.InsertFunction;

            if (function is null)
            {
                throw new InternalCodeGeneratorException("ICE: Expected block attached to a function at this point");
            }

            string varName   = forInExpression.LoopVariable.Name;
            Alloca allocaVar = LookupVariable(varName);

            // Emit the start code first, without 'variable' in scope.
            Value?startVal;

            if (forInExpression.LoopVariable.Initializer != null)
            {
                startVal = forInExpression.LoopVariable.Initializer.Accept(this);
                if (startVal is null)
                {
                    return(null);
                }
            }
            else
            {
                startVal = Context.CreateConstant(0.0);
            }

            // store the value into allocated location
            InstructionBuilder.Store(startVal, allocaVar);

            // Make the new basic block for the loop header.
            var loopBlock = function.AppendBasicBlock("loop");

            // Insert an explicit fall through from the current block to the loopBlock.
            InstructionBuilder.Branch(loopBlock);

            // Start insertion in loopBlock.
            InstructionBuilder.PositionAtEnd(loopBlock);

            // Within the loop, the variable is defined equal to the PHI node.
            // So, push a new scope for it and any values the body might set
            using (NamedValues.EnterScope( ))
            {
                EmitBranchToNewBlock("ForInScope");

                // Emit the body of the loop.  This, like any other expression, can change the
                // current BB.  Note that we ignore the value computed by the body, but don't
                // allow an error.
                if (forInExpression.Body.Accept(this) == null)
                {
                    return(null);
                }

                Value?stepValue = forInExpression.Step.Accept(this);
                if (stepValue == null)
                {
                    return(null);
                }

                // Compute the end condition.
                Value?endCondition = forInExpression.Condition.Accept(this);
                if (endCondition == null)
                {
                    return(null);
                }

                // since the Alloca is created as a non-opaque pointer it is OK to just use the
                // ElementType. If full opaque pointer support was used, then the Lookup map
                // would need to include the type of the value allocated.
                var curVar = InstructionBuilder.Load(allocaVar.ElementType, allocaVar)
                             .RegisterName(varName);
                var nextVar = InstructionBuilder.FAdd(curVar, stepValue)
                              .RegisterName("nextvar");
                InstructionBuilder.Store(nextVar, allocaVar);

                // Convert condition to a bool by comparing non-equal to 0.0.
                endCondition = InstructionBuilder.Compare(RealPredicate.OrderedAndNotEqual, endCondition, Context.CreateConstant(0.0))
                               .RegisterName("loopcond");

                // Create the "after loop" block and insert it.
                var afterBlock = function.AppendBasicBlock("afterloop");

                // Insert the conditional branch into the end of LoopEndBB.
                InstructionBuilder.Branch(endCondition, loopBlock, afterBlock);
                InstructionBuilder.PositionAtEnd(afterBlock);

                // for expression always returns 0.0 for consistency, there is no 'void'
                return(Context.DoubleType.GetNullValue( ));
            }
        }
Exemplo n.º 25
0
 /// <summary>
 /// Returns true if the given alloca should be converted.
 /// </summary>
 /// <param name="alloca">The alloca to check.</param>
 public bool ContainsAlloca(Alloca alloca) => Allocas.Contains(alloca);