view dang/compiler.d @ 91:1a24e61eb104 new_gen

Fixed the SourceLocation/SourceManager for files stretching by more then one CheckPoints
author johnsen@johnsen-laptop
date Mon, 05 May 2008 17:07:16 +0200
parents 4b6d8563e943
children 771ac63898e2
line wrap: on
line source

module dang.compiler;

import tango.io.Stdout,
       tango.core.Signal,
       tango.core.Memory,
       tango.sys.Process,
       tango.time.StopWatch,
       tango.io.FileConduit,
       tango.io.FilePath;

import lexer.Lexer,
       parser.Parser;

import basic.SourceManager;

import basic.Message;

import ast.Decl;

import tools.AstPrinter,
       tools.DotPrinter;

import gen.CodeGen;

import sema.Visitor,
       sema.AstAction,
       sema.SymbolTableBuilder,
       sema.ImplicitCast,
       sema.Declarations;

import Opt = dang.OptParse;

void checkFiles(char[][] *files)
{
    GC.disable();
    bool non_existant_files = false;
    bool duplicate_files = false;

    char[][] validFiles;

    foreach (file; *files)
    {
        scope path = new FilePath(file);

        if (!path.exists)
        {
            Stderr.formatln("'{}' does not exist", file).newline;
            non_existant_files = true;

            continue;
        }
        
        bool fileInStack = false;
        foreach (vFile; validFiles)
            if (vFile == file)
            {
                fileInStack = true;
                duplicate_files = true;
            }

        if (fileInStack)
            continue;

        validFiles ~= file;
    }

    *files = validFiles;

    if (non_existant_files)
        throw new Exception("All files given must exist");
    if (duplicate_files)
        Stderr("warning: duplicate files ignored").newline;
}

void main(char[][] args)
{
    char[][] filesToHandle;

    Signal!(char[][]*) preStart;

    Signal!(char[]) preLex;
    Signal!(Lexer) postLex;

    Signal!(Lexer) preParse;
    Signal!(Decl[], SourceManager) postParse;

    preStart.attach(&checkFiles);

    auto argParse = new Opt.OptionParser(`Dang "D" compiler v0.0`);

    bool optimize = false;
    bool inline = false;


    SourceManager src_mgr = new SourceManager;
    MessageHandler messages = new MessageHandler(src_mgr);

    argParse.addOption(["-h", "--help"], Opt.Action.Help)
        .help("Show this help message");

    argParse.addOption(["--ast-dump-dot"],
            "what-to-do", Opt.Action.StoreConst, "dot")
        .help("Output the AST in the dot format");
    argParse.addOption(["--ast-dump-code"],
            "what-to-do", Opt.Action.StoreConst, "code")
        .help("Output the AST as code");
    argParse.addOption(["--gen-llvm"],
            "what-to-do", Opt.Action.StoreConst, "gen-llvm")
        .help("Compile to LLVM code (default)");
    argParse.addOption(["-c"],
            "what-to-do", Opt.Action.StoreConst, "compile")
        .help("Compile to .o or executeable");

    argParse.addOption(
            ["-O","--optimize"], {
                optimize = true;
            }
    ).help("Tell LLVM to do its standard optimizations");

    argParse.addOption(
            ["--inline"], {
                inline = true;
            }
    ).help("Tell LLVM that its allowed to inline functions");

    argParse
        .addOption(["--time"], Opt.Action.SetTrue, "time")
        .help("Time the various operations performed.");

    auto options = argParse.parse(args);

    filesToHandle ~= options.args;
    
    // Will throw exception if some files don't exist
    preStart(&filesToHandle);

    struct Measurement { char[] label; double time; }
    Measurement[] timings;

    auto what = options["what-to-do"];
    if (what == "" || what == "gen-llvm")
        postParse.attach(
            (Decl[] decls, SourceManager sm) {
                StopWatch w; w.start;
                auto llvmGen = new CodeGen();
                auto file = new FileConduit("out.bc", FileConduit.WriteCreate);
                llvmGen.gen(decls, file.fileHandle, optimize, inline);
                timings ~= Measurement("Generating LLVM bytecode", w.stop);
            });
    else if (what == "compile")
        postParse.attach(
            (Decl[] decls, SourceManager sm) {
                StopWatch w; w.start;
                auto llvmGen = new CodeGen();
                auto llc = new Process("llc");
                llvmGen.gen(decls, llc.stdin.fileHandle, optimize, inline);
                timings ~= Measurement("Generating assemble bytecode", w.stop);
            });
    else if (what == "dot")
        postParse.attach(
            (Decl[] decls, SourceManager sm) {
                StopWatch w; w.start;
                auto print = new DotPrinter();
                print.print(decls);
                timings ~= Measurement("Generating dot output", w.stop);
            });
    else if (what == "code")
        postParse.attach(
            (Decl[] decls, SourceManager sm) {
                StopWatch w; w.start;
                auto print = new AstPrinter(sm);
                print.print(decls);
                timings ~= Measurement("Converting AST to text", w.stop);
            });
    StopWatch total;
    total.start;
    foreach (file; filesToHandle)
    {
        preLex(file);

        auto start = src_mgr.addFile(file);
        auto lexer = new Lexer(start, src_mgr, messages);
        postLex(lexer);

        preParse(lexer);

        StopWatch watch;
        watch.start;
        auto parser = new Parser(messages);
        auto action = new AstAction(src_mgr);
        auto decls = cast(Decl[])parser.parse(src_mgr, lexer, action);
        timings ~= Measurement("Lex + Parse", watch.stop);
        messages.checkErrors();

        StopWatch watch2;
        watch.start;
        watch2.start;
        (new SymbolTableBuilder).visit(decls);
        auto symbol_table = watch2.stop;
        watch2.start;
        (new Declarations).visit(decls);
        auto declarations = watch2.stop;
        watch2.start;
        (new ImplicitCast).visit(decls);
        auto implicit_casts = watch2.stop;
        watch2.start;

        foreach (decl; decls)
            decl.simplify();
        auto simplify = watch2.stop;
        auto extra_stuff = watch.stop;
        timings ~= Measurement("Extra stuff", watch.stop);
        timings ~= Measurement("  - Building scopes", symbol_table);
        timings ~= Measurement("  - Extracting declarations", declarations);
        timings ~= Measurement("  - Making casts explicit", implicit_casts);

        postParse(decls, src_mgr);
    }
    timings ~= Measurement("Total", total.stop);

    if (options.flag("time"))
        foreach (m; timings)
            Stderr.formatln("{,-45} {}ms", m.label, m.time*1e3);
}