Exemplo n.º 1
0
        private FunctionSymbol VisitFunctionDeclaration(FunctionDeclarationStmt fd, bool hasDefination)
        {
            foreach (var arg in fd.Signature.Arguments)
            {
                Assert(arg.Type != "void", $"'void' can't be used as a type.");
                LinkTypeSymbol(arg.Type);
            }
            LinkTypeSymbol(fd.Signature.Return);

            var funcSym = FindSymbol <FunctionSymbol>(fd.Name);

            if (funcSym != null)
            {
                Assert(funcSym.Signature == fd.Signature, $"Function '{fd.Name}' signature mismatch.");
                if (hasDefination)
                {
                    funcSym.HasBody = true;
                }
            }
            else
            {
                funcSym = new FunctionSymbol {
                    Name = fd.Name, Signature = fd.Signature, HasBody = hasDefination
                };
                Assert(GetNearestSymbolTable().TryAdd(funcSym),
                       $"There's another type of symbol with the same name '{fd.Name}'.");
            }
            return(funcSym);
        }
Exemplo n.º 2
0
        private void VisitStmt(Statement stmt, out bool terminate)
        {
            terminate = false;
            if (stmt == null)
            {
                return;
            }
            LoadTypes(stmt.ScopeSymbols);
            switch (stmt)
            {
            case FunctionDeclarationStmt fd:
            {
                break;
            }

            case FunctionStmt f:
            {
                FunctionSymbol funcSym   = f.Symbol;
                TypeSymbol     returnSym = funcSym.Signature.Return.Symbol;
                LLVMTypeRef    funcTy    = LLVM.FunctionType(
                    ReturnType: m_Types[returnSym],
                    ParamTypes: funcSym.Signature.Arguments.Select(arg => m_Types[arg.Type.Symbol]).ToArray(),
                    IsVarArg: false);
                m_Function = LLVM.AddFunction(m_Module, f.Declaration.Name, funcTy);
                m_FunctionPointers.Add(funcSym, m_Function);
                LLVMBasicBlockRef bb = LLVM.AppendBasicBlock(m_Function, "entry");
                LLVM.PositionBuilderAtEnd(m_Builder, bb);

                int paramIndex = 0;
                foreach (var param in m_Function.GetParams())
                {
                    LLVMValueRef ptrArg = LLVM.BuildAlloca(m_Builder, LLVM.TypeOf(param), "arg");
                    LLVM.BuildStore(m_Builder, param, ptrArg);
                    m_VariablePointers.Add(funcSym.Signature.Arguments[paramIndex].Symbol, ptrArg);
                    paramIndex++;
                }

                VisitStmt(f.Body, out bool term);

                if (!term)
                {
                    if (returnSym.IsPrimitive)
                    {
                        CPrimitiveType prim = returnSym.Primitive.Value;
                        if (prim == CPrimitiveType.Void)
                        {
                            LLVM.BuildRetVoid(m_Builder);
                        }
                        else
                        {
                            LLVM.BuildRet(m_Builder, m_PrimitiveLookup[prim].Default.Value);
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                break;
            }

            case BlockStmt block:
            {
                foreach (var childStmt in block.Statements)
                {
                    VisitStmt(childStmt, out bool term);
                    if (term)
                    {
                        terminate = true;
                        break;
                    }
                }
                break;
            }

            case VariableDeclarationStmt vd:
            {
                if (vd.Symbol.IsGlobal)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    LLVMValueRef ptr = LLVM.BuildAlloca(m_Builder, m_Types[vd.Type.Symbol], vd.Name);
                    m_VariablePointers.Add(vd.Symbol, ptr);
                    if (vd.Assignment != null)
                    {
                        LLVMValueRef value = VisitExpr(vd.Assignment);
                        LLVM.BuildStore(m_Builder, value, ptr);
                    }
                }
                break;
            }

            case IfStmt ifs:
            {
                LLVMValueRef i32  = VisitExpr(ifs.Condition);
                LLVMValueRef cond = I32ToCond(i32);

                LLVMBasicBlockRef bbTrue  = LLVM.AppendBasicBlock(m_Function, "if_true");
                LLVMBasicBlockRef bbFalse = LLVM.AppendBasicBlock(m_Function, "if_false");
                LLVMBasicBlockRef bbSucc  = LLVM.AppendBasicBlock(m_Function, "if_succ");

                LLVM.BuildCondBr(m_Builder, cond, bbTrue, bbFalse);

                LLVM.PositionBuilderAtEnd(m_Builder, bbTrue);
                VisitStmt(ifs.True, out bool termTrue);
                if (!termTrue)
                {
                    LLVM.BuildBr(m_Builder, bbSucc);
                }

                LLVM.PositionBuilderAtEnd(m_Builder, bbFalse);
                VisitStmt(ifs.False, out bool termFalse);
                if (!termFalse)
                {
                    LLVM.BuildBr(m_Builder, bbSucc);
                }

                LLVM.PositionBuilderAtEnd(m_Builder, bbSucc);
                break;
            }

            case ReturnStmt ret:
            {
                if (ret.Value == null)
                {
                    LLVM.BuildRetVoid(m_Builder);
                }
                else
                {
                    LLVMValueRef value = VisitExpr(ret.Value);
                    LLVM.BuildRet(m_Builder, value);
                }
                terminate = true;
                break;
            }

            case WhileStmt wh:
            {
                LLVMBasicBlockRef bbCond = LLVM.AppendBasicBlock(m_Function, "while_cond");
                LLVMBasicBlockRef bbBody = LLVM.AppendBasicBlock(m_Function, "while_body");
                LLVMBasicBlockRef bbSucc = LLVM.AppendBasicBlock(m_Function, "while_succ");
                m_BreakableStatementSuccessor.Add(wh, bbSucc);

                LLVM.BuildBr(m_Builder, bbCond);

                LLVM.PositionBuilderAtEnd(m_Builder, bbCond);
                LLVMValueRef i32  = VisitExpr(wh.Condition);
                LLVMValueRef cond = I32ToCond(i32);
                LLVM.BuildCondBr(m_Builder, cond, bbBody, bbSucc);

                LLVM.PositionBuilderAtEnd(m_Builder, bbBody);
                VisitStmt(wh.Body, out bool term);
                if (!term)
                {
                    LLVM.BuildBr(m_Builder, bbCond);
                }

                LLVM.PositionBuilderAtEnd(m_Builder, bbSucc);
                break;
            }

            case BreakStmt brk:
            {
                terminate = true;
                LLVM.BuildBr(m_Builder, m_BreakableStatementSuccessor[brk.Host]);
                break;
            }

            case ExpressionStmt exprStmt:
            {
                VisitExpr(exprStmt.Expression);
                break;
            }

            default:
            {
                throw new ArgumentException("Unrecognizable statement type.");
            }
            }
        }