-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlinker.cpp
More file actions
121 lines (105 loc) · 3.45 KB
/
linker.cpp
File metadata and controls
121 lines (105 loc) · 3.45 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
//=============================================================
//
// アセンブリファイル同士のリンクを行う
//
//=============================================================
#include "linker.h"
#include <QMessageBox>
#include <QList>
// TODO
#define DATA_UNIT_SIZE 32
linker::linker()
{
}
bool linker::open(const QString filepath, QFile& file, QTextStream& stream, QFlags<QIODevice::OpenModeFlag> flgs) {
if (filepath.endsWith(".s") == false) {
QMessageBox::critical(
NULL,
"invalid file name",
"source file must be assembly file(" + filepath + ")",
QMessageBox::Ok,
QMessageBox::Cancel);
return false;
}
file.setFileName(filepath);
if (file.open(flgs) == false) {
QMessageBox::critical(
NULL,
"can't open file",
"can't open " + filepath,
QMessageBox::Ok,
QMessageBox::Cancel);
return false;
}
stream.setDevice(&file);
return true;
}
void linker::close(QFile& file) {
file.close();
}
int linker::getHeapSize(QTextStream &stream) {
const QString& line = "";
QRegExp r("[.]init[_]heap[_]size[ \\t]+(\\d+)");
while (stream.atEnd() == false) {
const QString& line = stream.readLine();
int pos = r.indexIn(line);
if (pos > -1) {
return r.cap(1).toInt();
}
}
return 0;
}
void linker::writeHeapInitialize(QTextStream& stream, int heap_size, QTextStream& out) {
const QString& line = "";
while (stream.atEnd() == false && heap_size > 0) {
const QString& line = stream.readLine();
out << line << endl;
bool flg = false;
flg |= line.trimmed().startsWith(".int");
flg |= line.trimmed().startsWith(".long");
flg |= line.trimmed().startsWith(".float");
if (flg) {
heap_size -= DATA_UNIT_SIZE;
}
}
}
bool linker::link(QStringList srcs, QString dst) {
int cnt = srcs.count();
QTextStream stream[cnt + 1];
QFile file[cnt + 1];
// ソースファイルを開く
for (int i = 0; i < cnt; i++) {
if (open(srcs[i], file[i], stream[i], QIODevice::ReadWrite | QIODevice::Text) == false) return false;
}
// 出力ファイルを開く
if (open(dst, file[cnt], stream[cnt], QIODevice::WriteOnly | QIODevice::Text) == false) return false;
// ヒープサイズを合計する
int heap_size = 0;
int heap_sizes[cnt];
for (int i = 0; i < cnt; i++) {
heap_sizes[i] = getHeapSize(stream[i]);
heap_size += heap_sizes[i];
}
// ヒープサイズを書き込む
stream[cnt] << ".init_heap_size\t" << heap_size << endl;
// ヒープの初期化部分の書き込み
for (int i = 0; i < cnt; i++) {
writeHeapInitialize(stream[i], heap_sizes[i], stream[cnt]);
}
// メイン関数へのジャンプ命令
stream[cnt] << "\tjmp\tmin_caml_start" << endl;
// その他のコードの書き込み
QRegExp r("jmp[ \t]+min_caml_start");
for (int i = 0; i < cnt; i++) {
while (stream[i].atEnd() == false) {
const QString& line = stream[i].readLine();
int pos = r.indexIn(line.trimmed());
if (pos > -1) continue;
stream[cnt] << line << endl;
}
}
for (int i = 0; i < cnt + 1; i++) {
close(file[i]);
}
return true;
}