This repository was archived by the owner on Sep 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodegen.cpp
More file actions
148 lines (119 loc) · 4.22 KB
/
codegen.cpp
File metadata and controls
148 lines (119 loc) · 4.22 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//
// Created by 徐维亚 on 05/06/2018.
//
#include "codegen.h"
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/raw_ostream.h>
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
void CodeGenContext::CreateRead() {
std::vector<llvm::Type *> arg_types;
arg_types.push_back(llvm::Type::getInt8PtrTy(MyContext));
auto printf_type = llvm::FunctionType::get(llvm::Type::getInt32Ty(MyContext), arg_types, true);
read = llvm::Function::Create(printf_type, llvm::Function::ExternalLinkage, llvm::Twine("scanf"),
module);
read->setCallingConv(llvm::CallingConv::C);
}
void CodeGenContext::CreatePrint() {
std::vector<llvm::Type *> printf_arg_types;
printf_arg_types.push_back(llvm::Type::getInt8PtrTy(MyContext));
auto printf_type = llvm::FunctionType::get(llvm::Type::getInt32Ty(MyContext), printf_arg_types, true);
print = llvm::Function::Create(printf_type, llvm::Function::ExternalLinkage, llvm::Twine("printf"),
module);
print->setCallingConv(llvm::CallingConv::C);
}
void CodeGenContext::generateCode(Node *root, const std::string &outputFilename) {
std::cout << "Generating code...\n";
/* Create the top level interpreter function to call as entry */
std::vector<llvm::Type *> argTypes;
llvm::FunctionType *ftype = llvm::FunctionType::get(llvm::Type::getInt32Ty(MyContext), makeArrayRef(argTypes),
false);
// change GlobalValue::InternalLinkage into ExternalLinkage
llvm::Function *mainFunction = llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, "main", module);
llvm::BasicBlock *bblock = llvm::BasicBlock::Create(MyContext, "entry", mainFunction, nullptr);
// create print read ord chr
CreatePrint();
CreateRead();
// create read
/* Push a new variable/block context */
pushBlock(bblock);
blocks.top()->function = mainFunction;
root->codeGen(*this);
llvm::ReturnInst::Create(MyContext, ConstantInt::get(Type::getInt32Ty(MyContext), llvm::APInt(32, 0, false)),currentBlock());
popBlock();
while (!blocks.empty())
popBlock();
// popBlock();
/* Print the bytecode in a human-readable format
to see if our program compiled properly
*/
std::cout << "Code is generated.\n";
// write IR to stderr
std::cout << "code is gen~~~\n";
// module->dump();
llvm::outs() << *module;
std::cout << "code is gen~!~\n";
std::error_code ErrInfo;
// output
llvm::raw_ostream *out = new llvm::raw_fd_ostream(outputFilename, ErrInfo, llvm::sys::fs::F_None);
*out << *module;
// llvm::WriteBitcodeToFile(module, *out);
out->flush();
delete out;
////生成可执行文件
// Initialize the target registry etc.
outputCode("output.s", false);
outputCode("mips.s", true);
}
void CodeGenContext::outputCode(const char *filename, bool mips) {
InitializeAllTargetInfos();
InitializeAllTargets();
InitializeAllTargetMCs();
InitializeAllAsmParsers();
InitializeAllAsmPrinters();
std::string TargetTriple;
if (mips)
TargetTriple = "mips-apple-darwin17.6.0";
else
TargetTriple = sys::getDefaultTargetTriple();
module->setTargetTriple(TargetTriple);
std::string Error;
auto Target = TargetRegistry::lookupTarget(TargetTriple, Error);
if (!Target) {
errs() << Error;
return;
}
std::string CPU; // mips1 for mips: llvm-as < /dev/null | llc -march=x86-64 -mattr=help
if (mips)
CPU = "";
else
CPU = "generic";
auto Features = "";
TargetOptions opt;
auto RM = Optional<Reloc::Model>();
auto TheTargetMachine =
Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);
module->setDataLayout(TheTargetMachine->createDataLayout());
// auto filename = "output.s";
std::error_code EC;
raw_fd_ostream dest(filename, EC, sys::fs::F_None);
if (EC) {
errs() << "Could not open file: " << EC.message();
return;
}
legacy::PassManager pass;
auto FileType = TargetMachine::CGFT_AssemblyFile;
if (TheTargetMachine->addPassesToEmitFile(pass, dest, FileType)) {
errs() << "TheTargetMachine can't emit a file of this type";
return;
}
pass.run(*module);
dest.flush();
outs() << "Wrote " << filename << "\n";
}