Ejemplo n.º 1
0
        public Construct VisitArray(Constructs.Array node)
        {
            // Prepare the value buffer list.
            List <LlvmValue> values = new List <LlvmValue>();

            // Iterate and emit all the values onto the buffer list.
            foreach (Value value in node.Values)
            {
                // Visit the value.
                this.VisitValue(value);

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

                // Append the value onto the buffer list.
                values.Add(llvmValue);
            }

            // Visit the kind.
            this.VisitKind(node.Kind);

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

            // Create the array.
            LlvmValue array = LlvmFactory.Array(elementType, values.ToArray());

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

            // Return the node.
            return(node);
        }
Ejemplo n.º 2
0
        public Construct VisitExtern(Extern node)
        {
            // Ensure prototype is set.
            if (node.Prototype == null)
            {
                throw new Exception("Unexpected external definition's prototype to be null");
            }

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

            // TODO: What about reference? Arguments must be named for extern?
            foreach ((Kind kind, Reference reference) in node.Prototype.Arguments)
            {
                // Visit the kind.
                this.VisitKind(kind);

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

                // Append onto the arguments list.
                arguments.Add(argumentType);
            }

            // Visit the prototype's return kind.
            this.Visit(node.Prototype.ReturnKind);

            // Pop 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);

            // Emit the external definition to context and capture the LLVM value reference.
            LlvmValue @extern = this.module.CreateFunction(node.Prototype.Identifier, type);

            // Determine if should be registered on the symbol table.
            if (!this.module.ContainsFunction(node.Prototype.Identifier))
            {
                // Register the external definition as a function in the symbol table.
                this.module.RegisterFunction((LlvmFunction)@extern);
            }
            // Otherwise, throw an error.
            else
            {
                throw new Exception($"Warning: Extern definition '{node.Prototype.Identifier}' being re-defined");
            }

            // Push the resulting value onto the stack.
            this.valueStack.Push(@extern);

            // Return the node.
            return(node);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        public Construct VisitInteger(Integer node)
        {
            // Visit the kind.
            this.VisitKind(node.Kind);

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

            // Convert to a constant and return as an llvm value wrapper instance.
            LlvmValue value = LlvmFactory.Int(type, node.Value);

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

            // Return the node.
            return(node);
        }
Ejemplo n.º 5
0
        public Construct VisitValue(Value node)
        {
            // Create the value buffer.
            LlvmValue value;

            // Ensure value is identified as a literal.
            if (!Recognition.IsLiteral(node.Content))
            {
                throw new Exception("Content could not be identified as a valid literal");
            }
            // Integer literal.
            else if (Recognition.IsInteger(node.Content))
            {
                // Visit the kind.
                this.VisitKind(node.Kind);

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

                // Create the type and assign the value buffer.
                value = LlvmFactory.Int(type, int.Parse(node.Content));
            }
            // String literal.
            else if (Recognition.IsStringLiteral(node.Content))
            {
                value = LlvmFactory.String(node.Content);
            }
            // Unrecognized literal.
            else
            {
                throw new Exception($"Unrecognized literal: {node.Content}");
            }

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

            // Return the node.
            return(node);
        }
Ejemplo n.º 6
0
        public Construct VisitPrototype(Prototype node)
        {
            // Retrieve argument count within node.
            uint argumentCount = (uint)node.Arguments.Length;

            // Create the argument buffer array.
            LlvmType[] arguments = new LlvmType[Math.Max(argumentCount, 1)];

            // Attempt to retrieve an existing function value.
            LlvmFunction?function = this.module.GetFunction(node.Identifier);

            // Function may be already defined.
            if (function != null)
            {
                // Function already has a body, disallow re-definition.
                if (function.HasBlocks)
                {
                    throw new Exception($"Cannot re-define function: {node.Identifier}");
                }
                // If the function takes a different number of arguments, reject.
                else if (function.ArgumentCount != argumentCount)
                {
                    throw new Exception("redefinition of function with different # args");
                }
            }
            else
            {
                // TODO: Wrong type.
                for (int i = 0; i < argumentCount; ++i)
                {
                    arguments[i] = LLVM.DoubleType().Wrap();
                }

                // TODO: Support for infinite arguments and hard-coded return type.
                // Create the function type.
                LlvmType type = LlvmFactory.Function(LlvmFactory.Void(), arguments, false);

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

                // Set the function's linkage.
                function.SetLinkage(LLVMLinkage.LLVMExternalLinkage);
            }

            // Process arguments.
            for (int i = 0; i < argumentCount; ++i)
            {
                // Retrieve the argument name.
                string argumentName = node.Arguments[i].Item2.Value;

                // Retrieve the argument at the current index iterator.
                LlvmValue argument = function.GetArgumentAt((uint)i);

                // Name the argument.
                argument.SetName(argumentName);

                // TODO: Watch out for already existing ones.
                // Stored the named argument in the named values cache.
                this.namedValues.Add(argumentName, argument);
            }

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

            // Return the node.
            return(node);
        }
Ejemplo n.º 7
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);
        }