Exemplo n.º 1
0
        public Construct VisitGlobal(Global node)
        {
            // Visit the kind.
            this.VisitKind(node.Kind);

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

            // Create the global variable.
            LlvmGlobal global = this.module.CreateGlobal(node.Identifier, type);

            // Set the linkage to common.
            global.SetLinkage(LLVMLinkage.LLVMCommonLinkage);

            // Assign initial value if applicable.
            if (node.InitialValue != null)
            {
                // Visit the initial value.
                this.Visit(node.InitialValue);

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

                // Set the initial value.
                global.SetInitialValue(initialValue);
            }

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

            // Return the node.
            return(node);
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
0
        public Construct VisitStructDef(StructDef node)
        {
            // Create the body buffer list.
            List <LlvmType> body = new List <LlvmType>();

            // Create a buffer dictionary for the symbol.
            Dictionary <string, LlvmType> symbolProperties = new Dictionary <string, LlvmType>();

            // Map the body's properties onto the body.
            foreach (StructDefProperty property in node.Body)
            {
                // Visit the kind.
                this.VisitKind(property.Kind);

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

                // Append it to the body.
                body.Add(type);

                // Append it to the symbol's properties dictionary.
                symbolProperties.Add(property.Identifier, type);
            }

            // Create the struct.
            LlvmType @struct = this.module.CreateStruct(node.Identifier, body.ToArray());

            // Append the resulting struct onto the stack.
            this.typeStack.Push(@struct);

            // Return the node.
            return(node);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        public Construct VisitCreateInst(CreateInst node)
        {
            // Visit the kind.
            this.VisitKind(node.Kind);

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

            // Create the LLVM alloca instruction.
            LlvmValue value = this.builder.CreateAlloca(type, node.ResultIdentifier);

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

            // Return the node.
            return(node);
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
        public Construct VisitKind(Kind node)
        {
            // Create the initial type.
            LlvmType type = TokenConstants.kindGenerationMap[node.Type]().Wrap();

            // Convert to a pointer if applicable.
            if (node.IsPointer)
            {
                type.ConvertToPointer();
            }

            // Append the resulting type onto the stack.
            this.typeStack.Push(type);

            // Return the node.
            return(node);
        }
Exemplo n.º 8
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);
        }
Exemplo n.º 9
0
 public PointerType(LlvmType pointeeType, uint addressSpace)
 {
     PointeeType  = pointeeType;
     AddressSpace = addressSpace;
 }
Exemplo n.º 10
0
 public FunctionType(bool hasVarargs, LlvmType returnType, IReadOnlyList <LlvmType> paramTypes)
 {
     HasVarargs = hasVarargs;
     ReturnType = returnType;
     ParamTypes = paramTypes;
 }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
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);
        }