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); }
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); }
// TODO: What about ResultIdentifier? public CallInst(LlvmFunction target, string resultIdentifier, IConstruct[] inputs) : base(InstructionName.Call, inputs) { this.Callee = target; this.ResultIdentifier = resultIdentifier; }
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); }