summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-06-01 02:15:40 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-06-01 02:15:40 +0800
commitf3729aee72a60578738f0c2fddcca2831019f546 (patch)
tree88eb9af84f43407fa5931746281827e2d9263cc7
parent9de9ac16960a1ac2c0ab967013f2ec6847b7bc21 (diff)
add a sha1 test, commandline improvement, limit target to x86 only
-rw-r--r--.gitignore4
-rw-r--r--Lexer.l9
-rw-r--r--TypeManager.cc20
-rw-r--r--Version.cc15
-rw-r--r--Version.hh2
-rw-r--r--main.cc58
-rw-r--r--t/sha1.pas145
-rw-r--r--t/sha1_driver.c36
8 files changed, 257 insertions, 32 deletions
diff --git a/.gitignore b/.gitignore
index 1304f0a..fac49c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,6 @@ out
Parser.cc
Lexer.cc
Parser.hh
-*.ll
+t/*
+!t/*.pas
+!t/*.c
diff --git a/Lexer.l b/Lexer.l
index f2fdc9a..6679b75 100644
--- a/Lexer.l
+++ b/Lexer.l
@@ -11,13 +11,6 @@
using pcc::Parser;
using pcc::Location;
-
-namespace pcc {
- char ToLower(char c){
- return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
- }
-}
-
%}
%option nodefault
@@ -165,8 +158,6 @@ comment {comment1}|{comment2}
}
{identifier} {
- char *name = new char[yyleng];
- std::transform(yytext, yytext+yyleng, name, pcc::ToLower);
return Parser::make_IDENTIFIER(yytext, loc);
}
diff --git a/TypeManager.cc b/TypeManager.cc
index 9c484e4..7402875 100644
--- a/TypeManager.cc
+++ b/TypeManager.cc
@@ -161,6 +161,24 @@ Value TypeManager::CreateCast(std::shared_ptr<Type> DstType,
return builder->CreateSExtOrTrunc(v, DstType->GetLLVMType());
}
}
+
+ // array to pointer decay
+ std::shared_ptr<PointerType> SrcPointerType =
+ std::dynamic_pointer_cast<PointerType>(SrcType);
+ std::shared_ptr<PointerType> DstPointerType =
+ std::dynamic_pointer_cast<PointerType>(DstType);
+ if (SrcPointerType != nullptr && DstPointerType != nullptr) {
+ std::shared_ptr<ArrayType> SrcInnerType =
+ std::dynamic_pointer_cast<ArrayType>(
+ SrcPointerType->GetElementType());
+ if (SrcInnerType->GetElementType() ==
+ DstPointerType->GetElementType()) {
+ Value zero =
+ llvm::ConstantInt::get(PointerIndexType_->GetLLVMType(), 0);
+ Value indices[2] = {zero, zero};
+ return builder->CreateInBoundsGEP(v, indices);
+ }
+ }
Log(LogLevel::PCC_ERROR, "unsupported type casting from %s to %s",
SrcType->GetCommonName(), DstType->GetCommonName());
return nullptr;
@@ -214,7 +232,7 @@ std::shared_ptr<ArrayType>
std::shared_ptr<RecordType>
TypeManager::CreateRecordType(const std::vector<RecordMember>& members) {
- std::string name = "record {";
+ std::string name = "{";
std::vector<RecordMember>::const_iterator MemberIt = members.cbegin();
name.append(std::get<1>(*MemberIt)->GetCommonName());
for (++MemberIt; MemberIt != members.cend(); ++MemberIt) {
diff --git a/Version.cc b/Version.cc
index 02e30e2..7bc9532 100644
--- a/Version.cc
+++ b/Version.cc
@@ -25,12 +25,15 @@ PCC_NORETURN void ShowVersion() {
PCC_NORETURN void ShowHelp() {
std::cerr << PCC_NAME " version " PCC_VERSION_STRING "\n"
- << "Usage: " PCC_NAME " [-vVh] file...\n"
- << " -v Verbose mode.\n"
- " -vv Very verbose mode.\n"
- " -V Show version and exit.\n"
- " -h Show this help and exit.\n"
- " -t Set target's triple."
+ << "Usage: " PCC_NAME " [-vVhiSc] file...\n"
+ << " -v Verbose mode.\n"
+ << " -vv Very verbose mode.\n"
+ << " -V Show version and exit.\n"
+ << " -h Show this help and exit.\n"
+ << " -i Generate LLVM IR (default behavior).\n"
+ << " -S Compile to assembly.\n"
+ << " -c Compile to object file.\n"
+ << " -o <file> Specify output file name."
<< std::endl;
std::exit(0);
}
diff --git a/Version.hh b/Version.hh
index 5b3a7ff..f2f05a3 100644
--- a/Version.hh
+++ b/Version.hh
@@ -5,7 +5,7 @@
#include <iostream>
#define PCC_NAME "pcc"
-#define PCC_VERSION_STRING "0.1.0"
+#define PCC_VERSION_STRING "0.1.1"
#ifndef PCC_OSNAME
#define PCC_OSNAME "unknown platform"
diff --git a/main.cc b/main.cc
index a1ab94a..2ee9699 100644
--- a/main.cc
+++ b/main.cc
@@ -18,8 +18,9 @@
int main(int argc, char* argv[]) {
int rv;
int level = pcc::ToUnderlying(pcc::PCC_WARNING);
- std::string triple = "";
- while ((rv = getopt(argc, argv, "vVht:")) != -1) {
+ std::string OutputFileName;
+ enum { IR, ASSEMBLY, OBJECT } CompileType = IR;
+ while ((rv = getopt(argc, argv, "vVhiSco:")) != -1) {
switch (rv) {
case 'v':
level = (level == 0 ? 0 : level - 1);
@@ -28,8 +29,18 @@ int main(int argc, char* argv[]) {
pcc::ShowVersion();
case 'h':
pcc::ShowHelp();
- case 't':
- triple = optarg;
+ case 'i':
+ CompileType = IR;
+ break;
+ case 'S':
+ CompileType = ASSEMBLY;
+ break;
+ case 'c':
+ CompileType = OBJECT;
+ break;
+ case 'o':
+ OutputFileName = optarg;
+ break;
default:
pcc::Log(pcc::PCC_ERROR, "Unknown option \"%c\".", rv);
pcc::ShowHelp();
@@ -39,9 +50,7 @@ int main(int argc, char* argv[]) {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmParser();
llvm::InitializeNativeTargetAsmPrinter();
- if (triple.empty()) {
- triple = llvm::sys::getDefaultTargetTriple();
- }
+ std::string triple = llvm::sys::getDefaultTargetTriple();
std::string error;
const llvm::Target* target =
llvm::TargetRegistry::lookupTarget(triple, error);
@@ -61,6 +70,11 @@ int main(int argc, char* argv[]) {
pcc::Log(pcc::PCC_ERROR, "No input file specified");
return -1;
}
+ if (!OutputFileName.empty() && optind != argc - 1) {
+ pcc::Log(pcc::LogLevel::PCC_WARNING,
+ "more than one source file specified, the output file name "
+ "will be ignored");
+ }
for (int i = optind; i < argc; i++) {
pcc::Driver driver(argv[i]);
llvm::Module* module = driver.GetContext()->GetModule();
@@ -71,16 +85,32 @@ int main(int argc, char* argv[]) {
if (root != nullptr) {
root->CodeGen();
}
- size_t PostfixPos = filename.rfind(".pas");
- std::string OutputFileName;
- if (PostfixPos == std::string::npos) {
- OutputFileName = filename + ".ll";
- } else {
- OutputFileName = filename.substr(0, PostfixPos) + ".ll";
+ if (OutputFileName.empty()) {
+ const char* postfixs[] = {".ll", ".s", ".o"};
+ size_t PostfixPos = filename.rfind(".pas");
+ if (PostfixPos == std::string::npos) {
+ OutputFileName = filename + postfixs[CompileType];
+ } else {
+ OutputFileName =
+ filename.substr(0, PostfixPos) + postfixs[CompileType];
+ }
}
std::error_code ErrorCode;
llvm::raw_fd_ostream Output(OutputFileName, ErrorCode);
- driver.GetContext()->GetModule()->print(Output, nullptr);
+ switch (CompileType) {
+ case IR:
+ module->print(Output, nullptr);
+ break;
+ case ASSEMBLY:
+ break;
+ case OBJECT:
+ break;
+ default:
+ break;
+ }
+ pcc::Log(pcc::LogLevel::PCC_INFO, "%s compiled to %s", argv[i],
+ OutputFileName.c_str());
+ OutputFileName.clear();
}
return 0;
}
diff --git a/t/sha1.pas b/t/sha1.pas
new file mode 100644
index 0000000..35c9341
--- /dev/null
+++ b/t/sha1.pas
@@ -0,0 +1,145 @@
+program sha1;
+
+type
+ sha1_ctx = record
+ h:array [0..4] of integer;
+ bytes:integer;
+ buf:array [0..63] of char
+ end;
+
+extern memcpy(dst:^char; src:^char; len:integer):^char;
+
+extern memset(buf:^char; c:char; len:integer):^char;
+
+function sha1_init(ctx:^sha1_ctx):void;
+begin
+ ctx^.h[0] := 0x67452301;
+ ctx^.h[1] := -0x10325477;
+ ctx^.h[2] := -0x67452302;
+ ctx^.h[3] := 0x10325476;
+ ctx^.h[4] := -0x3c2d1e10;
+ ctx^.bytes := 0;
+end;
+
+function rol(bits:integer; x:integer):integer;
+begin
+ rol := x shl bits or (x shr (32-bits) and not (-1 shl bits))
+end;
+
+function sha1_body(ctx:^sha1_ctx; data:^char; len:integer):^char;
+var
+ f, k, temp, i, j:integer;
+ a, b, c, d, e:integer;
+ aa, bb, cc, dd, ee:integer;
+ p:^char;
+ w:array [0..79] of integer;
+begin
+ p := data;
+ a := ctx^.h[0];
+ b := ctx^.h[1];
+ c := ctx^.h[2];
+ d := ctx^.h[3];
+ e := ctx^.h[4];
+ repeat begin
+ aa := a;
+ bb := b;
+ cc := c;
+ dd := d;
+ ee := e;
+ for i := 0 to 15 do begin
+ w[i] := 0;
+ for j := 0 to 3 do
+ w[i] := (w[i] shl 8) or (p[i*4+j] and 0xff)
+ end;
+ for i := 16 to 79 do
+ w[i] := rol(1, w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]);
+ for i := 0 to 79 do begin
+ if i<20 then begin
+ f := (b and c) or ((not b) and d);
+ k := 0x5a827999
+ end
+ else if i<40 then begin
+ f := b xor c xor d;
+ k := 0x6ed9eba1
+ end
+ else if i<60 then begin
+ f := (b and c) or (b and d) or(c and d);
+ k := -0x70e44324
+ end
+ else begin
+ f := b xor c xor d;
+ k := -0x359d3e2a
+ end;
+ temp := rol(5, a) + f + e + k + w[i];
+ e := d;
+ d := c;
+ c := rol(30, b);
+ b := a;
+ a := temp
+ end;
+ a := a+aa;
+ b := b+bb;
+ c := c+cc;
+ d := d+dd;
+ e := e+ee;
+ p := p+64;
+ len := len-64
+ end until len=0;
+ ctx^.h[0] := a;
+ ctx^.h[1] := b;
+ ctx^.h[2] := c;
+ ctx^.h[3] := d;
+ ctx^.h[4] := e;
+ sha1_body := p;
+end;
+
+function sha1_update(ctx:^sha1_ctx; data:^char; len:integer):void;
+var
+ used, free:integer;
+begin
+ used := ctx^.bytes and 0x3f;
+ ctx^.bytes := ctx^.bytes+len;
+ if (used<>0) and (used+len<64) then
+ memcpy(@ctx^.buf[used], data, len)
+ else begin
+ if used<>0 then begin
+ free := 64-used;
+ memcpy(@ctx^.buf[used], data, free);
+ data := data+free;
+ len := len-free;
+ sha1_body(ctx, @ctx^.buf, 64)
+ end;
+ if len>=64 then begin
+ data := sha1_body(ctx, data, len and not 0x3f);
+ len := len and 0x3f
+ end;
+ memcpy(@ctx^.buf[0], data, len)
+ end
+end;
+
+function sha1_final(md:^char; ctx:^sha1_ctx):void;
+var
+ used, free:integer;
+ bits, i:integer;
+begin
+ used := ctx^.bytes and 0x3f;
+ ctx^.buf[used] := 0x80;
+ used := used+1;
+ free := 64-used;
+ if free<8 then begin
+ memset(@ctx^.buf[used], 0, free);
+ sha1_body(ctx, @ctx^.buf, 64);
+ used := 0;
+ free := 64
+ end;
+ memset(@ctx^.buf[used], 0, free-8);
+ bits := ctx^.bytes shl 3;
+ for i := 0 to 3 do
+ ctx^.buf[56+i] := 0;
+ for i := 4 to 7 do
+ ctx^.buf[i+56] := bits shr (8*(7-i));
+ sha1_body(ctx, @ctx^.buf, 64);
+ for i := 0 to 19 do
+ md[i] := ctx^.h[i div 4] shr (8*(3-i mod 4));
+end;
+
diff --git a/t/sha1_driver.c b/t/sha1_driver.c
new file mode 100644
index 0000000..212cbf8
--- /dev/null
+++ b/t/sha1_driver.c
@@ -0,0 +1,36 @@
+#include <assert.h>
+#include <stdio.h>
+
+typedef struct ctx_s {
+ int h[5];
+ int bytes;
+ char buf[64];
+} ctx;
+
+void sha1_init(ctx*);
+void sha1_update(ctx*, const char*, int);
+void sha1_final(unsigned char*, ctx*);
+
+int main(int argc, char* argv[]) {
+ ctx c;
+ int i;
+ size_t len;
+ char buf[1024];
+ unsigned char md[20];
+ FILE* f;
+
+ assert(argc == 2);
+ f = fopen(argv[1], "r");
+ sha1_init(&c);
+ while (!feof(f)) {
+ len = fread(buf, 1, 1024, f);
+ sha1_update(&c, buf, (int) len);
+ }
+ sha1_final(md, &c);
+ for (i = 0; i < 20; i++) {
+ printf("%02x", md[i]);
+ }
+ putchar('\n');
+ fclose(f);
+ return 0;
+}