Skip to content

Commit 58cb399

Browse files
committed
feat: basic code generation
feat: add packed flag to StructType feat: add CallingConv to Function
1 parent 982f94a commit 58cb399

File tree

5 files changed

+87
-36
lines changed

5 files changed

+87
-36
lines changed

include/Util/ErrMsg.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace ErrMsg {
44
namespace Class {
55
namespace APInt {
6-
constexpr const char *constructor = "APInt.constructor needs to be called with new (numBits: number, value: number, isSigned?: boolean)";
6+
constexpr const char *constructor = "APInt.constructor needs to be called with new (numBits: number, value: number | bigint, isSigned?: boolean)";
77
}
88
namespace APFloat {
99
constexpr const char *constructor = "APFloat.constructor needs to be called with new (value: number)";
@@ -579,6 +579,19 @@ namespace ErrMsg {
579579
}
580580
namespace TargetMachine {
581581
constexpr const char *constructor = "TargetMachine.constructor needs to be called with new (external: Napi::External<llvm::TargetMachine>)";
582+
constexpr const char *emitToFile = "TargetMachine.emitToFile needs to be called with (module: Module, path: string, format: CodeGenFileType)";
583+
constexpr const char *emitToBuffer = "TargetMachine.emitToBuffer needs to be called with (module: Module, format: CodeGenFileType)";
584+
constexpr const char *addPassesToEmitFile = "Cannot register passes to emit file. Check registered ASM printers, targets and relevant stuff";
585+
}
586+
namespace ModulePassManager {
587+
constexpr const char *constructor = "ModulePassManager.constructor needs to be called with new (optLevel: OptimizationLevel)";
588+
constexpr const char *createFunctionPassManager = "ModulePassManager.createFunctionPassManager needs to be called with new (ltoPhase: ThinOrFullLTOPhase)";
589+
constexpr const char *addFunctionPasses = "ModulePassManager.addFunctionPasses needs to be called with new (fpm: FunctionPassManager)";
590+
constexpr const char *run = "ModulePassManager.run needs to be called with new (module: Module)";
591+
}
592+
namespace FunctionPassManager {
593+
constexpr const char *constructor = "ModulePassManager.constructor needs to be called with new (external: Napi::External<llvm::TargetMachine>)";
594+
582595
}
583596
}
584597
namespace Namespace::Intrinsic {

llvm-bindings.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
declare namespace llvm {
22
class APInt {
3-
public constructor(numBits: number, value: number, isSigned?: boolean);
3+
public constructor(numBits: number, value: number | bigint, isSigned?: boolean);
44
}
55

66
class APFloat {

src/ADT/APInt.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ llvm::APInt &APInt::Extract(const Napi::Value &value) {
2020
APInt::APInt(const Napi::CallbackInfo &info) : ObjectWrap(info) {
2121
Napi::Env env = info.Env();
2222
unsigned argsLen = info.Length();
23-
if (!info.IsConstructCall() || argsLen < 2 || !info[0].IsNumber() || !info[1].IsNumber() || argsLen >= 3 && !info[2].IsBoolean()) {
23+
if (!info.IsConstructCall() || argsLen < 2 || !info[0].IsNumber() || !(info[1].IsNumber() || info[1].IsBigInt()) || argsLen >= 3 && !info[2].IsBoolean()) {
2424
throw Napi::TypeError::New(env, ErrMsg::Class::APInt::constructor);
2525
}
2626
unsigned numBits = info[0].As<Napi::Number>();
27-
uint64_t val = info[1].As<Napi::Number>().Int64Value();
27+
bool lossless = true;
28+
uint64_t val = info[1].IsNumber()
29+
? info[1].As<Napi::Number>().Int64Value()
30+
: info[1].As<Napi::BigInt>().Int64Value(&lossless);
2831
bool isSigned = false;
2932
if (argsLen >= 3) {
3033
isSigned = info[2].As<Napi::Boolean>();

src/IR/PassManager.cpp

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "llvm/Pass.h"
77
#include "llvm/Passes/PassBuilder.h"
8+
#include "llvm/CodeGen/CodeGenPassBuilder.h"
89
#include "llvm/Transforms/Scalar/SROA.h"
910
#include "llvm/Transforms/Scalar/EarlyCSE.h"
1011
#include "llvm/Transforms/InstCombine/InstCombine.h"
@@ -52,30 +53,40 @@ llvm::OptimizationLevel mapToLLVM(OptimizationLevel::Level opt) {
5253

5354
ModulePassManager::ModulePassManager(const Napi::CallbackInfo &info) : ObjectWrap(info) {
5455
Napi::Env env = info.Env();
55-
56-
level = mapToLLVM((OptimizationLevel::Level) info[0].As<Napi::Number>().Uint32Value());
57-
58-
passBuilder = new llvm::PassBuilder();
59-
60-
moduleAnalysisManager = new llvm::ModuleAnalysisManager();
61-
cgsccAnalysisManager = new llvm::CGSCCAnalysisManager();
62-
functionAnalysisManager = new llvm::FunctionAnalysisManager();
63-
loopAnalysisManager = new llvm::LoopAnalysisManager ();
64-
65-
passBuilder->registerModuleAnalyses(*moduleAnalysisManager);
66-
passBuilder->registerCGSCCAnalyses(*cgsccAnalysisManager);
67-
passBuilder->registerFunctionAnalyses(*functionAnalysisManager);
68-
passBuilder->registerLoopAnalyses(*loopAnalysisManager);
69-
passBuilder->crossRegisterProxies(
70-
*loopAnalysisManager,
71-
*functionAnalysisManager,
72-
*cgsccAnalysisManager,
73-
*moduleAnalysisManager
74-
);
75-
76-
passManager = new llvm::ModulePassManager(
77-
passBuilder->buildPerModuleDefaultPipeline(level)
78-
);
56+
if (info.IsConstructCall() && info.Length() == 1 && info[0].IsNumber()) {
57+
level = mapToLLVM((OptimizationLevel::Level) info[0].As<Napi::Number>().Uint32Value());
58+
59+
passBuilder = new llvm::PassBuilder();
60+
61+
moduleAnalysisManager = new llvm::ModuleAnalysisManager();
62+
cgsccAnalysisManager = new llvm::CGSCCAnalysisManager();
63+
functionAnalysisManager = new llvm::FunctionAnalysisManager();
64+
loopAnalysisManager = new llvm::LoopAnalysisManager ();
65+
66+
passBuilder->registerModuleAnalyses(*moduleAnalysisManager);
67+
passBuilder->registerCGSCCAnalyses(*cgsccAnalysisManager);
68+
passBuilder->registerFunctionAnalyses(*functionAnalysisManager);
69+
passBuilder->registerLoopAnalyses(*loopAnalysisManager);
70+
passBuilder->crossRegisterProxies(
71+
*loopAnalysisManager,
72+
*functionAnalysisManager,
73+
*cgsccAnalysisManager,
74+
*moduleAnalysisManager
75+
);
76+
77+
if (level == llvm::OptimizationLevel::O0) {
78+
passManager = new llvm::ModulePassManager(
79+
passBuilder->buildO0DefaultPipeline(level)
80+
);
81+
return;
82+
}
83+
84+
passManager = new llvm::ModulePassManager(
85+
passBuilder->buildPerModuleDefaultPipeline(level)
86+
);
87+
return;
88+
}
89+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::constructor);
7990
}
8091

8192
llvm::ModulePassManager *ModulePassManager::getLLVMPrimitive() {
@@ -84,6 +95,11 @@ llvm::ModulePassManager *ModulePassManager::getLLVMPrimitive() {
8495

8596
Napi::Value ModulePassManager::createFunctionPassManager(const Napi::CallbackInfo& info) {
8697
Napi::Env env = info.Env();
98+
unsigned argsLen = info.Length();
99+
100+
if (argsLen != 1 || !info[0].IsNumber()) {
101+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::createFunctionPassManager);
102+
}
87103

88104
auto lto = (llvm::ThinOrFullLTOPhase) info[0].As<Napi::Number>().Uint32Value();
89105

@@ -103,14 +119,14 @@ void ModulePassManager::addFunctionPasses(const Napi::CallbackInfo &info) {
103119
Napi::Env env = info.Env();
104120
auto argsLen = info.Length();
105121

106-
if (argsLen != 1) {
107-
throw Napi::TypeError::New(env, "(fpm: FunctionPassManager)");
122+
if (argsLen != 1 || !FunctionPassManager::IsClassOf(info[0])) {
123+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::addFunctionPasses);
108124
}
109125

110126
auto fpm = FunctionPassManager::Extract(info[0]);
111127

112128
if (!fpm) {
113-
throw Napi::TypeError::New(env, "(fpm: FunctionPassManager)");
129+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::addFunctionPasses);
114130
}
115131

116132
passManager->addPass(llvm::createModuleToFunctionPassAdaptor(std::move(*fpm)));
@@ -125,11 +141,15 @@ void ModulePassManager::run(const Napi::CallbackInfo &info) {
125141
auto argsLen = info.Length();
126142

127143
if (argsLen != 1 || !Module::IsClassOf(info[0])) {
128-
throw Napi::TypeError::New(env, "(module: Module)");
144+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::run);
129145
}
130146

131147
auto module = Module::Extract(info[0]);
132148

149+
if (!module) {
150+
throw Napi::TypeError::New(env, ErrMsg::Class::ModulePassManager::run);
151+
}
152+
133153
passManager->run(*module, *moduleAnalysisManager);
134154
}
135155

@@ -167,8 +187,13 @@ llvm::FunctionPassManager *FunctionPassManager::Extract(const Napi::Value &value
167187
}
168188

169189
FunctionPassManager::FunctionPassManager(const Napi::CallbackInfo &info) : ObjectWrap(info) {
170-
auto external = info[0].As<Napi::External<llvm::FunctionPassManager>>();
171-
passManager = external.Data();
190+
Napi::Env env = info.Env();
191+
if (info.IsConstructCall() && info.Length() == 1 && info[0].IsExternal()) {
192+
auto external = info[0].As<Napi::External<llvm::FunctionPassManager>>();
193+
passManager = external.Data();
194+
return;
195+
}
196+
throw Napi::TypeError::New(env, ErrMsg::Class::FunctionPassManager::constructor);
172197
}
173198

174199
llvm::FunctionPassManager *FunctionPassManager::getLLVMPrimitive() {

src/Target/TargetMachine.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ Napi::Value TargetMachine::createDataLayout(const Napi::CallbackInfo &info) {
4646

4747
void TargetMachine::emitToFile(const Napi::CallbackInfo& info) {
4848
Napi::Env env = info.Env();
49+
unsigned argsLen = info.Length();
50+
51+
if (argsLen != 3 || !Module::IsClassOf(info[0]) || !info[1].IsString() || !info[2].IsNumber()) {
52+
throw Napi::TypeError::New(env, ErrMsg::Class::TargetMachine::emitToFile);
53+
}
4954

5055
auto fileName = info[1].As<Napi::String>().Utf8Value();
5156
std::error_code ec;
@@ -57,7 +62,7 @@ void TargetMachine::emitToFile(const Napi::CallbackInfo& info) {
5762
llvm::legacy::PassManager pm{};
5863

5964
if (const_cast<llvm::TargetMachine*>(targetMachine)->addPassesToEmitFile(pm, dest, nullptr, type)) {
60-
throw Napi::TypeError::New(env, "cannot add emit pass");
65+
throw Napi::Error::New(env, ErrMsg::Class::TargetMachine::addPassesToEmitFile);
6166
}
6267

6368
pm.run(*module);
@@ -66,6 +71,11 @@ void TargetMachine::emitToFile(const Napi::CallbackInfo& info) {
6671

6772
Napi::Value TargetMachine::emitToBuffer(const Napi::CallbackInfo& info) {
6873
Napi::Env env = info.Env();
74+
unsigned argsLen = info.Length();
75+
76+
if (argsLen != 2 || !Module::IsClassOf(info[0]) || !info[1].IsNumber()) {
77+
throw Napi::TypeError::New(env, ErrMsg::Class::TargetMachine::emitToBuffer);
78+
}
6979

7080
llvm::SmallVector<char> buffer;
7181
llvm::raw_svector_ostream dest(buffer);
@@ -76,7 +86,7 @@ Napi::Value TargetMachine::emitToBuffer(const Napi::CallbackInfo& info) {
7686
llvm::legacy::PassManager pm{};
7787

7888
if (const_cast<llvm::TargetMachine*>(targetMachine)->addPassesToEmitFile(pm, dest, nullptr, type)) {
79-
throw Napi::TypeError::New(env, "cannot add emit pass");
89+
throw Napi::Error::New(env, ErrMsg::Class::TargetMachine::addPassesToEmitFile);
8090
}
8191

8292
pm.run(*module);

0 commit comments

Comments
 (0)