diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-06-01 02:15:40 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-06-01 02:15:40 +0800 |
| commit | f3729aee72a60578738f0c2fddcca2831019f546 (patch) | |
| tree | 88eb9af84f43407fa5931746281827e2d9263cc7 | |
| parent | 9de9ac16960a1ac2c0ab967013f2ec6847b7bc21 (diff) | |
add a sha1 test, commandline improvement, limit target to x86 only
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | Lexer.l | 9 | ||||
| -rw-r--r-- | TypeManager.cc | 20 | ||||
| -rw-r--r-- | Version.cc | 15 | ||||
| -rw-r--r-- | Version.hh | 2 | ||||
| -rw-r--r-- | main.cc | 58 | ||||
| -rw-r--r-- | t/sha1.pas | 145 | ||||
| -rw-r--r-- | t/sha1_driver.c | 36 |
8 files changed, 257 insertions, 32 deletions
@@ -6,4 +6,6 @@ out Parser.cc Lexer.cc Parser.hh -*.ll +t/* +!t/*.pas +!t/*.c @@ -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) { @@ -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); } @@ -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" @@ -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; +} |
