aboutsummaryrefslogtreecommitdiffstats
path: root/main.cpp
blob: c70c976f5092512f425102f00b38f36aa0fe5981 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
 * lisp-compiler: Compiles LISP using LLVM.
 * Copyright (C) 2022  Clyne Sullivan
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @file main.cpp
 * @brief Program entry point.
 */

/*

Current support:
 - Literals:
   - Integer
   - Double (when decimal point is found)
 - (define name value)
 - (set! defined-name new-value)
 - (lambda (...) ...)
 - (if cond then else)
 - Calling procedures:
   - Defined lambdas
   - Built-in things
   - Undefined procedures are prototyped

TODO:
 - Error reporting!
 - Documentation!
 - Arithmetic
 - String literals?
 - Typed definitions...
 - See R7RS-small for more...

*/

#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"

#include <cstdio>
#include <string>

#include "ast.hpp"
#include "parser.hpp"
#include "state.hpp"

void compileToObjectFile(CompilerState&);
int main(int argc, const char *argv[])
{
    CompilerState state;
    Parser parser;

    for (int i = 1; i < argc; ++i)
        parser.addString(argv[i]);

    auto functype = llvm::FunctionType::get(llvm::Type::getInt32Ty(state.context), {}, false);
    auto func = llvm::Function::Create(functype, llvm::Function::ExternalLinkage, "main", &state.module);
    auto block = llvm::BasicBlock::Create(state.context, "entry", func);
    state.builder.SetInsertPoint(block);

    parser.parse(state);

    state.builder.CreateRet(state.builder.getInt32(0));

    puts("");
    state.module.print(llvm::errs(), nullptr); // prints everything

    compileToObjectFile(state);

    return 0;
}

void compileToObjectFile(CompilerState& state)
{
    llvm::InitializeAllTargetInfos();
    llvm::InitializeAllTargets();
    llvm::InitializeAllTargetMCs();
    llvm::InitializeAllAsmParsers();
    llvm::InitializeAllAsmPrinters();

    auto TargetTriple = "x86_64-pc-linux-gnu";

    std::string error;
    auto Target = llvm::TargetRegistry::lookupTarget(TargetTriple, error);
    if (!error.empty())
        puts(error.c_str());

    auto CPU = "generic";
    auto Features = "";
    llvm::TargetOptions opt;
    auto RM = llvm::Optional<llvm::Reloc::Model>();
    auto TargetMachine = Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);

    std::error_code EC;
    llvm::raw_fd_ostream dest ("out.o", EC, llvm::sys::fs::OF_None);

    llvm::legacy::PassManager pass;
    
    if (TargetMachine->addPassesToEmitFile(pass, dest, nullptr, llvm::CGFT_ObjectFile)) {
        llvm::errs() << "TargetMachine can't emit a file of this type";
    } else {
        pass.run(state.module);
        dest.flush();
    }
}