Пример #1
0
        public Construct VisitIf(If node)
        {
            // TODO: Action and alternative blocks not being handled, for debugging purposes.

            // Visit the condition.
            this.Visit(node.Condition);

            // Pop the condition off the stack.
            LlvmValue conditionValue = this.valueStack.Pop();

            // Create a zero-value double for the boolean comparison.
            LlvmValue zero = LlvmFactory.Double(0);

            // TODO: Hard-coded name.
            // Build the comparison, condition will be convered to a boolean for a 'ONE' (non-equal) comparison.
            LlvmValue comparison = LLVM.BuildFCmp(this.builder.Unwrap(), LLVMRealPredicate.LLVMRealONE, conditionValue.Unwrap(), zero.Unwrap(), "ifcond").Wrap();

            // Retrieve the parent function from the builder.
            LlvmFunction function = this.builder.Block.Parent;

            // Create the action block.
            LlvmBlock action = function.AppendBlock("then");

            // TODO: Debugging, Ret void for action.
            action.Builder.CreateReturnVoid();

            LlvmBlock otherwise = function.AppendBlock("else");

            // TODO: Debugging, ret void for otherwise.
            otherwise.Builder.CreateReturnVoid();

            LlvmBlock merge = function.AppendBlock("ifcont");

            // TODO: Debugging, ret void for merge.
            merge.Builder.CreateReturnVoid();

            // Build the if construct.
            LlvmValue @if = LLVM.BuildCondBr(this.builder.Unwrap(), comparison.Unwrap(), action.Unwrap(), otherwise.Unwrap()).Wrap();

            // TODO: Complete implementation, based off: https://github.com/microsoft/LLVMSharp/blob/master/KaleidoscopeTutorial/Chapter5/KaleidoscopeLLVM/CodeGenVisitor.cs#L214
            // ...

            // TODO: Debugging, not complete.
            action.Builder.PositionAtEnd(); // ? Delete..

            // Append the if construct onto the stack.
            this.valueStack.Push(@if);

            // Return the node.
            return(node);
        }
Пример #2
0
        public Construct VisitCallInst(CallInst node)
        {
            // Create an argument buffer list.
            List <LlvmValue> arguments = new List <LlvmValue>();

            // Emit the call arguments.
            foreach (Constructs.Construct argument in node.Arguments)
            {
                // Continue if the argument is null.
                if (argument == null)
                {
                    continue;
                }

                // Visit the argument.
                this.Visit(argument);

                // Pop the argument off the value stack.
                LlvmValue argumentValue = this.valueStack.Pop();

                // Append argument value to the argument buffer list.
                arguments.Add(argumentValue);
            }

            // Retrieve the callee function.
            LlvmFunction callee = node.Callee;

            // Ensure argument count is correct (with continuous arguments).
            if (callee.HasInfiniteArguments && arguments.Count < callee.ArgumentCount - 1)
            {
                throw new Exception($"Target function requires at least {callee.ArgumentCount - 1} argument(s)");
            }
            // Otherwise, expect the argument count to be exact.
            else if (arguments.Count != callee.ArgumentCount)
            {
                throw new Exception($"Argument amount mismatch, target function requires exactly {callee.ArgumentCount} argument(s)");
            }

            // Create the function call.
            LlvmValue call = this.builder.CreateCall(callee, node.ResultIdentifier, arguments.ToArray());

            // Append the value onto the stack.
            this.valueStack.Push(call);

            // Return the node.
            return(node);
        }
Пример #3
0
 // TODO: What about ResultIdentifier?
 public CallInst(LlvmFunction target, string resultIdentifier, IConstruct[] inputs) : base(InstructionName.Call, inputs)
 {
     this.Callee           = target;
     this.ResultIdentifier = resultIdentifier;
 }
Пример #4
0
        public Construct VisitRoutine(Routine node)
        {
            // Ensure body was provided or created.
            if (node.Body == null)
            {
                throw new Exception("Unexpected function body to be null");
            }
            // Ensure prototype is set.
            else if (node.Prototype == null)
            {
                throw new Exception("Unexpected function prototype to be null");
            }
            // Ensures the function does not already exist.
            else if (this.module.ContainsFunction(node.Prototype.Identifier))
            {
                throw new Exception($"A function with the identifier '{node.Prototype.Identifier}' already exists");
            }

            // Clear named values.
            this.namedValues.Clear();

            // Create an argument buffer list.
            List <LlvmType> arguments = new List <LlvmType>();

            // Process the prototype's arguments.
            foreach ((Kind kind, Reference reference) in node.Prototype.Arguments)
            {
                // Visit the argument's type.
                this.Visit(kind);

                // Pop the resulting type off the stack.
                LlvmType argumentType = this.typeStack.Pop();

                // Append the argument's type to the argument list.
                arguments.Add(argumentType);
            }

            // Visit the return type node.
            this.Visit(node.Prototype.ReturnKind);

            // Pop off the return type off the stack.
            LlvmType returnType = this.typeStack.Pop();

            // Emit the function type.
            LlvmType type = LlvmFactory.Function(returnType, arguments.ToArray(), node.Prototype.HasInfiniteArguments);

            // Create the function.
            LlvmFunction function = this.module.CreateFunction(node.Prototype.Identifier, type);

            // Register as the temporary, local function.
            this.function = function;

            // Create the argument index counter.
            uint argumentIndexCounter = 0;

            // Name arguments.
            foreach ((Kind kind, Reference reference) in node.Prototype.Arguments)
            {
                // Retrieve the argument.
                LlvmValue argument = function.GetArgumentAt(argumentIndexCounter);

                // Name the argument.
                argument.SetName(reference.Value);

                // Increment the index counter for next iteration.
                argumentIndexCounter++;
            }

            // Visit the body.
            this.VisitSection(node.Body);

            // Pop the body off the stack.
            this.blockStack.Pop();

            // TODO
            // Ensure that body returns a value if applicable.
            // else if (!node.Prototype.ReturnKind.IsVoid && !node.Body.HasReturnValue)
            // {
            //     throw new Exception("Functions that do not return void must return a value");
            // }

            // Verify the function.
            function.Verify();

            // Append the function onto the stack.
            this.valueStack.Push(function);

            // Return the node.
            return(node);
        }