コード例 #1
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var markedBlock = BasicBlock.FunctionBody.GetOrCreateLabeledBlock(Label);

            BuildBr(BasicBlock.Builder, markedBlock.Block);
            return(new BlockCodegen(markedBlock));
        }
コード例 #2
0
        private Tuple <LLVMValueRef[], BasicBlockBuilder> EmitArguments(
            BasicBlockBuilder BasicBlock,
            LLVMValueRef Target,
            IEnumerable <CodeBlock> Arguments)
        {
            int targetArgCount = Target.Pointer == IntPtr.Zero ? 0 : 1;
            var argArr         = Arguments.ToArray <CodeBlock>();
            var allArgs        = new LLVMValueRef[targetArgCount + argArr.Length];

            if (targetArgCount == 1)
            {
                allArgs[0] = BuildBitCast(
                    BasicBlock.Builder,
                    Target,
                    PointerType(Int8Type(), 0),
                    "this_tmp");
            }
            for (int i = 0; i < argArr.Length; i++)
            {
                var argResult = argArr[i].Emit(BasicBlock);
                BasicBlock = argResult.BasicBlock;
                allArgs[targetArgCount + i] = argResult.Value;
            }
            return(new Tuple <LLVMValueRef[], BasicBlockBuilder>(
                       allArgs, BasicBlock));
        }
コード例 #3
0
        private BlockCodegen EmitCall(
            BasicBlockBuilder BasicBlock,
            LLVMValueRef Callee,
            LLVMValueRef[] Arguments)
        {
            bool hasVoidRetType = retType == PrimitiveTypes.Void;

            LLVMValueRef callRef;

            if (CanThrow && BasicBlock.HasUnwindTarget)
            {
                var successBlock = BasicBlock.CreateChildBlock("success");
                callRef = BuildInvoke(
                    BasicBlock.Builder,
                    Callee,
                    Arguments,
                    successBlock.Block,
                    BasicBlock.UnwindTarget,
                    hasVoidRetType ? "" : "call_tmp");
                BasicBlock = successBlock;
            }
            else
            {
                callRef = BuildCall(
                    BasicBlock.Builder,
                    Callee,
                    Arguments,
                    hasVoidRetType ? "" : "call_tmp");
            }

            return(hasVoidRetType
                ? new BlockCodegen(BasicBlock)
                : new BlockCodegen(BasicBlock, callRef));
        }
コード例 #4
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var lhsAddrCodegen = DestinationAddress.Emit(BasicBlock);

            BasicBlock = lhsAddrCodegen.BasicBlock;
            var rhsValueCodegen = Value.Emit(BasicBlock);

            BasicBlock = rhsValueCodegen.BasicBlock;

            // LLVM AtomicRMW instructions always return the *old* value,
            // but we want the *new* value (with Xchg being the lone
            // exception).
            //
            // We can compute the new value by first performing the RMW
            // and then computing the new value ourselves.

            var rmwOp = BuildAtomicRMW(
                BasicBlock.Builder,
                Op,
                lhsAddrCodegen.Value,
                rhsValueCodegen.Value,
                LLVMAtomicOrdering.LLVMAtomicOrderingSequentiallyConsistent,
                false);

            return(new BlockCodegen(
                       BasicBlock,
                       BuildRMWResult(
                           BasicBlock.Builder,
                           Op,
                           rmwOp,
                           rhsValueCodegen.Value)));
        }
コード例 #5
0
        /// <summary>
        /// Populates a 'finally' block with instructions.
        /// </summary>
        /// <param name="FinallyBlock">The 'finally' block to populate.</param>
        /// <param name="LeaveBlock">
        /// The 'leave' block to which the 'finally' block jumps if no exception was thrown.
        /// </param>
        /// <param name="IsPropagatingStorage">
        /// A pointer to a Boolean flag that tells if an exception is being propagated.
        /// </param>
        private void PopulateFinallyBlock(
            BasicBlockBuilder FinallyBlock,
            BasicBlockBuilder LeaveBlock,
            LLVMValueRef IsPropagatingStorage)
        {
            // A finally block is just a normal block that does this:
            //
            // finally:
            //     <finally body>
            //     if (is_handling_exception)
            //     {
            //         unwind;
            //     }
            //     else
            //     {
            //         goto leave_try;
            //     }

            var finallyTail             = FinallyBody.Emit(FinallyBlock).BasicBlock;
            var propagateExceptionBlock = GetManualUnwindTarget(finallyTail);

            BuildCondBr(
                finallyTail.Builder,
                BuildLoad(
                    finallyTail.Builder,
                    IsPropagatingStorage,
                    "is_handling_exception"),
                propagateExceptionBlock,
                LeaveBlock.Block);
        }
コード例 #6
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var destCodegen = Destination.Emit(BasicBlock);

            BasicBlock = destCodegen.BasicBlock;
            var valCodegen = Value.Emit(BasicBlock);

            BasicBlock = valCodegen.BasicBlock;
            var comparandCodegen = Comparand.Emit(BasicBlock);

            BasicBlock = comparandCodegen.BasicBlock;

            var cmpxchg = BuildAtomicCmpXchg(
                BasicBlock.Builder,
                destCodegen.Value,
                comparandCodegen.Value,
                valCodegen.Value,
                LLVMAtomicOrdering.LLVMAtomicOrderingSequentiallyConsistent,
                LLVMAtomicOrdering.LLVMAtomicOrderingSequentiallyConsistent,
                false);

            cmpxchg.SetValueName("atomic_cmpxchg");

            return(new BlockCodegen(
                       BasicBlock,
                       BuildExtractValue(BasicBlock.Builder, cmpxchg, 0, "old_value")));
        }
コード例 #7
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            if (CatchClauses.Count == 0)
            {
                return(TryBody.Emit(BasicBlock));
            }

            var exceptionDataType = StructType(new[] { PointerType(Int8Type(), 0), Int32Type() }, false);

            var catchBlock           = BasicBlock.CreateChildBlock("catch");
            var catchLandingPadBlock = BasicBlock.CreateChildBlock("catch_landingpad");
            var leaveBlock           = BasicBlock.CreateChildBlock("leave");

            // The try block is a regular block that jumps to the 'leave' block.
            //
            // try:
            //     <try body>
            //     br label %leave

            var tryCodegen = TryBody.Emit(BasicBlock.WithUnwindTarget(catchLandingPadBlock, catchBlock));

            BuildBr(tryCodegen.BasicBlock.Builder, leaveBlock.Block);

            PopulateCatchBlock(catchBlock, leaveBlock);
            ItaniumCxxFinallyBlock.PopulateThunkLandingPadBlock(catchLandingPadBlock, catchBlock.Block, false);

            return(new BlockCodegen(leaveBlock, tryCodegen.Value));
        }
コード例 #8
0
 /// <inheritdoc/>
 public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
 {
     return(new BlockCodegen(
                BasicBlock,
                BuildAlloca(BasicBlock.Builder, BasicBlock.FunctionBody.Module.Declare(ElementType),
                            "alloca_tmp")));
 }
コード例 #9
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var markedBlock = BasicBlock.FunctionBody.GetOrCreateLabeledBlock(Label);

            BuildBr(BasicBlock.Builder, markedBlock.Block);
            return(new UnreachableBlock(CodeGenerator, Type).Emit(BasicBlock));
        }
コード例 #10
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var lhsCodegen = address.Emit(BasicBlock);
            var rhsCodegen = val.Emit(lhsCodegen.BasicBlock);

            BuildStore(rhsCodegen.BasicBlock.Builder, rhsCodegen.Value, lhsCodegen.Value);
            return(new BlockCodegen(rhsCodegen.BasicBlock));
        }
コード例 #11
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var vtableCodegen = VTablePointer.Emit(BasicBlock);

            BasicBlock = vtableCodegen.BasicBlock;
            return(new BlockCodegen(
                       BasicBlock,
                       BuildTypeid(BasicBlock.Builder, vtableCodegen.Value)));
        }
コード例 #12
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var firstCodegen  = firstBlock.Emit(BasicBlock);
            var secondCodegen = secondBlock.Emit(firstCodegen.BasicBlock);

            return(new BlockCodegen(
                       secondCodegen.BasicBlock,
                       secondIsResult ? secondCodegen.Value : firstCodegen.Value));
        }
コード例 #13
0
ファイル: BinaryBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var lhsCodegen = lhs.Emit(BasicBlock);
            var rhsCodegen = rhs.Emit(lhsCodegen.BasicBlock);

            return(new BlockCodegen(
                       rhsCodegen.BasicBlock,
                       build(rhsCodegen.BasicBlock.Builder, lhsCodegen.Value, rhsCodegen.Value, "tmp")));
        }
コード例 #14
0
ファイル: BranchBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var targetBlock = IsBreak
                ? BasicBlock.FunctionBody.GetBreakBlock(Tag)
                : BasicBlock.FunctionBody.GetContinueBlock(Tag);

            BuildBr(BasicBlock.Builder, targetBlock);
            return(new BlockCodegen(BasicBlock.CreateChildBlock()));
        }
コード例 #15
0
        /// <summary>
        /// Creates a new basic block builder that appends instructions to
        /// this block, but with a different unwind target.
        /// </summary>
        /// <param name="Target">
        /// The automatic unwind target to which 'invoke' instructions can refer.
        /// </param>
        /// <param name="ManualTarget">
        /// The manual unwind target to which branch instructions can refer.
        /// </param>
        /// <returns>A new basic block builder for the same basic block.</returns>
        public BasicBlockBuilder WithUnwindTarget(
            LLVMBasicBlockRef Target,
            LLVMBasicBlockRef ManualTarget)
        {
            var result = new BasicBlockBuilder(FunctionBody, Block);

            result.UnwindTarget       = Target;
            result.ManualUnwindTarget = ManualTarget;
            return(result);
        }
コード例 #16
0
 /// <summary>
 /// Emits this prologue spec to the given basic block.
 /// </summary>
 /// <param name="BasicBlock">The basic block to populate.</param>
 /// <returns>The next basic block.</returns>
 public BasicBlockBuilder Emit(BasicBlockBuilder BasicBlock)
 {
     for (int i = 0; i < taggedInstructions.Count; i++)
     {
         var codegen = taggedInstructions[i].Value.Emit(BasicBlock);
         BasicBlock = codegen.BasicBlock;
         BasicBlock.FunctionBody.TagValue(taggedInstructions[i].Key, codegen.Value);
     }
     return(BasicBlock);
 }
コード例 #17
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            BuildUnreachable(BasicBlock.Builder);
            var newBlock = BasicBlock.CreateChildBlock("post_unreachable");

            return(new BlockCodegen(
                       newBlock,
                       PrimitiveTypes.Void == Type
                    ? default(LLVMValueRef)
                    : GetUndef(BasicBlock.FunctionBody.Module.Declare(resultType))));
        }
コード例 #18
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var result   = GetParam(BasicBlock.FunctionBody.Function, (uint)Index);
            var llvmType = BasicBlock.FunctionBody.Module.Declare(Type);

            if (result.TypeOf().Pointer != llvmType.Pointer)
            {
                result = BuildBitCast(BasicBlock.Builder, result, llvmType, "bitcast_tmp");
            }
            return(new BlockCodegen(BasicBlock, result));
        }
コード例 #19
0
ファイル: SizeOfBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var type = BasicBlock.FunctionBody.Module.Declare(TypeToMeasure);

            if (!IsReferenceSize)
            {
                type = GetElementType(type);
            }

            return(new BlockCodegen(BasicBlock, ConstTrunc(SizeOf(type), Int32Type())));
        }
コード例 #20
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var continueBlock = BasicBlock.CreateChildBlock("continue_block");
            var breakBlock    = BasicBlock.CreateChildBlock("break_block");

            BasicBlock.FunctionBody.TagFlowBlock(Tag, breakBlock.Block, continueBlock.Block);

            BuildBr(BasicBlock.Builder, continueBlock.Block);
            var bodyResult = Body.Emit(continueBlock);

            BuildBr(bodyResult.BasicBlock.Builder, breakBlock.Block);
            return(new BlockCodegen(breakBlock, bodyResult.Value));
        }
コード例 #21
0
 /// <summary>
 /// Generates code for the object that receives a call, if any.
 /// </summary>
 /// <param name="BasicBlock">The basic block to generate code in.</param>
 /// <param name="Target">An object that will receive a call or <c>null</c>.</param>
 /// <returns>Block codegen.</returns>
 public static BlockCodegen EmitTarget(BasicBlockBuilder BasicBlock, CodeBlock Target)
 {
     if (Target == null)
     {
         return(new BlockCodegen(BasicBlock));
     }
     else
     {
         var targetResult = Target.Emit(BasicBlock);
         BasicBlock = targetResult.BasicBlock;
         return(new BlockCodegen(BasicBlock, targetResult.Value));
     }
 }
コード例 #22
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var baseAddressResult = ArrayPointer.Emit(BasicBlock);

            BasicBlock = baseAddressResult.BasicBlock;
            return(new BlockCodegen(
                       BasicBlock,
                       BuildStructGEP(
                           BasicBlock.Builder,
                           baseAddressResult.Value,
                           (uint)DimensionIndex,
                           "dimension_ptr_tmp")));
        }
コード例 #23
0
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var elements = new LLVMValueRef[structType.InstanceFields.Count];

            for (int i = 0; i < elements.Length; i++)
            {
                var elemBlock  = (CodeBlock)codeGen.EmitDefaultValue(structType.InstanceFields[i].FieldType);
                var elemResult = elemBlock.Emit(BasicBlock);
                BasicBlock  = elemResult.BasicBlock;
                elements[i] = elemResult.Value;
            }
            return(new BlockCodegen(BasicBlock, ConstStruct(elements, false)));
        }
コード例 #24
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var lhsCodegen = lhs.Emit(BasicBlock);
            var rhsCodegen = rhs.Emit(lhsCodegen.BasicBlock);

            return(new BlockCodegen(
                       rhsCodegen.BasicBlock,
                       LLVMSharp.LLVM.BuildFCmp(
                           rhsCodegen.BasicBlock.Builder,
                           predicate,
                           lhsCodegen.Value,
                           rhsCodegen.Value,
                           "tmp")));
        }
コード例 #25
0
ファイル: UnaryBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var operandCodegen = operand.Emit(BasicBlock);

            if (buildConst != null && operandCodegen.Value.IsConstant())
            {
                return(new BlockCodegen(
                           operandCodegen.BasicBlock,
                           buildConst(operandCodegen.Value)));
            }
            else
            {
                return(new BlockCodegen(
                           operandCodegen.BasicBlock,
                           build(operandCodegen.BasicBlock.Builder, operandCodegen.Value, "tmp")));
            }
        }
コード例 #26
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var exceptionDataType    = StructType(new[] { PointerType(Int8Type(), 0), Int32Type() }, false);
            var isPropagatingStorage = BasicBlock.FunctionBody.CreateEntryPointAlloca(
                Int1Type(),
                "exception_value_alloca");

            var finallyBlock           = BasicBlock.CreateChildBlock("finally");
            var finallyLandingPadBlock = BasicBlock.CreateChildBlock("finally_landingpad");
            var finallyExceptionBlock  = BasicBlock.CreateChildBlock("finally_exception");
            var leaveBlock             = BasicBlock.CreateChildBlock("leave");

            // The try block is a regular block that jumps to the finally block.
            //
            // try:
            //     store i1 false, i1* %is_propagating_exception_alloca
            //     <try body>
            //     br label %finally

            BuildStore(
                BasicBlock.Builder,
                ConstInt(Int1Type(), 0, false),
                isPropagatingStorage);
            var tryCodegen = TryBody.Emit(BasicBlock.WithUnwindTarget(finallyLandingPadBlock, finallyExceptionBlock));

            BuildBr(tryCodegen.BasicBlock.Builder, finallyBlock.Block);

            PopulateFinallyBlock(finallyBlock, leaveBlock, isPropagatingStorage);
            PopulateThunkLandingPadBlock(finallyLandingPadBlock, finallyExceptionBlock.Block, true);

            // The 'finally_exception' block is entered if an exception is propagating from
            // the 'try' block. It sets the 'is propagating' flag to 'true' and branches
            // to the finally block.
            //
            // finally_exception:
            //     store i1 true, i1* %is_propagating_exception_alloca
            //     br label %finally

            BuildStore(
                finallyExceptionBlock.Builder,
                ConstInt(Int1Type(), 1, false),
                isPropagatingStorage);
            BuildBr(finallyExceptionBlock.Builder, finallyBlock.Block);

            return(new BlockCodegen(leaveBlock, tryCodegen.Value));
        }
コード例 #27
0
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var ptrResult = BaseAddress.Emit(BasicBlock);

            BasicBlock = ptrResult.BasicBlock;
            var indexVals = new LLVMValueRef[Indices.Count];

            for (int i = 0; i < indexVals.Length; i++)
            {
                var indexResult = Indices[i].Emit(BasicBlock);
                BasicBlock   = indexResult.BasicBlock;
                indexVals[i] = indexResult.Value;
            }
            return(new BlockCodegen(
                       BasicBlock,
                       BuildGEP(BasicBlock.Builder, ptrResult.Value, indexVals, "gep_tmp")));
        }
コード例 #28
0
ファイル: UnboxBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            var boxCodegen = Box.Emit(BasicBlock);

            BasicBlock = boxCodegen.BasicBlock;
            return(new BlockCodegen(
                       BasicBlock,
                       BuildStructGEP(
                           BasicBlock.Builder,
                           BuildBitCast(
                               BasicBlock.Builder,
                               boxCodegen.Value,
                               BasicBlock.FunctionBody.Module.Declare(
                                   elemType.MakePointerType(PointerKind.BoxPointer)),
                               "box_ptr"),
                           1,
                           "unboxed_ptr")));
        }
コード例 #29
0
 private BlockCodegen EmitClause(
     BasicBlockBuilder MergeBlock,
     CodeBlock Body,
     string Name,
     out BasicBlockBuilder ClauseBlock)
 {
     if (Body != null)
     {
         ClauseBlock = MergeBlock.CreateChildBlock(Name);
         var clauseResult = Body.Emit(ClauseBlock);
         BuildBr(clauseResult.BasicBlock.Builder, MergeBlock.Block);
         return(clauseResult);
     }
     else
     {
         ClauseBlock = MergeBlock;
         return(new BlockCodegen(MergeBlock));
     }
 }
コード例 #30
0
ファイル: ReturnBlock.cs プロジェクト: jonathanvdc/flame-llvm
        /// <inheritdoc/>
        public override BlockCodegen Emit(BasicBlockBuilder BasicBlock)
        {
            if (retVal == null)
            {
                return(EmitRetVoid(BasicBlock));
            }

            var retValCodegen = retVal.Emit(BasicBlock);

            BasicBlock = retValCodegen.BasicBlock;
            if (retVal.Type == PrimitiveTypes.Void)
            {
                return(EmitRetVoid(BasicBlock));
            }
            else
            {
                var ret = BuildRet(BasicBlock.Builder, retValCodegen.Value);
                return(new BlockCodegen(BasicBlock));
            }
        }